티스토리 뷰

1️⃣ 네이버 로그인

네이버 로그인 API 공식문서는 예전 버전 이후로 업데이트가 안된 것 같다. 또한 gptea프로젝트는 타입스트립트를 사용하므로 다른 블로그들도 함께 참고하였다.

 

1. App컴포넌트의 isLoggedIn 상태를 상태 끌어올리기를 통해 1. Loggedin컴포넌트와 2. MyGptea컴포넌트의 Nav컴포넌트가 공유한다.

isLoggedIn이 true이면 MyGptea컴포넌트를 렌더링하여 서비스를 이용할 수 있고, false라면 Welcome컴포넌트를 렌더링하여 로그인버튼이 있는 페이지가 뜨도록 했다. 컴포넌트별로 url을 다 다르게 할지, 지금처럼 같은 '/'경로에 조건부 렌더링을 할지 고민했는데, github가 이렇게 되어있어서 참고했다. '/'경로인 홈에서 github 로그인 페이지가 뜨고, 로그인을 하면 같은 경로에서 github 메인 페이지가 뜬다.

얼마 전에 Redux라이브러리 사용법을 공부해서 상태관리 라이브러리로 Redux를 적용해보고 싶다. gptea 프로젝트는 규모가 크지 않아 Recoil이 더 사용하기 쉽고 간편할 것 같은데 Redux를 프로젝트에 적용해본적이 없어서 이번에 연습해보려고 한다. 프로토타입 단계라서 잠시 상태끌어올리기를 통해 상태를 관리하고, 추후 Redux를 도입할 것이다.

 

2. 네이버 로그인 버튼을 누르면 내가 네이버 개발자센터 애플리케이션에 설정해놓은 CallbackURL로 네이버가 access_token을 보내준다. 백엔드에서 gptea login api를 만들면 서버로 프론트엔드가 전송해주어야 한다. 현재는 임시로 로컬스토리지에 저장했다.

한편, 한가지 의문점이 있다. 네이버에서 CallbackURL에 access_token을 실어서 쿼리스트링으로 보내주는데, 이 때 내가 useNavigate를 사용해서 바로 리디렉션을 하긴 하지만, 0.5초정도 유저가 url창에서 access_token을 볼 수 있다. 스크린캡쳐라도 하면 유출이 될 수 있다. 시간이 지나면 만료가 되긴 하지만 공개를 하면 안될 것 같다. 방법을 찾아봐야겠다.

 

🔨 리액트에서 .env 환경변수를 사용할 때 REACT_APP_이름 으로 지어주어야 한다. 그리고 변수를 사용할 때에는 process.env.REACT_APP_이름 으로 사용한다.

🔨 react-router-dom 중첩라우팅을 할 때에는 * 와일드카드를 붙여주어야 한다.

<Routes>
    <Route path='/*' element={isLoggedIn ? <MyGptea setIsLoggedIn={setIsLoggedIn} /> : <Welcome />} />
    <Route path='/login' element={<Loggedin setIsLoggedIn={setIsLoggedIn} />} />
</Routes>

 

2️⃣ 네이버 로그아웃

네이버 api는 로그아웃기능은 제공하지 않는다. 
네이버 로그인 API 공식문서 의 6.1.4. 접근 토큰 삭제 요청을 통해 access_token을 삭제해주어 로그아웃 기능을 구현하였다. 이 때 CORS에러가 발생하였다.

접근 토큰 삭제 요청시 CORS에러

이미 gptea api를 받아오는데 proxy를 설정해두었기 때문에 naver api를 위해 proxy를 추가로 설정해주어야 했다. 미들웨어를 사용해서 proxy를 여러개 둘 수 있는 것 같은데, 우선은 따로 proxy설정을 해주지 않고 fetch요청에 {mode: 'no-cors'} 옵션을 주며 CORS에러를 회피했다.

  const handleNaverLogout = () => {
    fetch(
      `https://nid.naver.com/oauth2.0/token?grant_type=delete&client_id=${process.env.NAVER_CLIENT_ID}&client_secret=${
        process.env.NAVER_SECRET_KEY
      }&access_token=${JSON.parse(localStorage.getItem('access') || '')}&service_provider=NAVER`,
      { mode: 'no-cors' } // CORS
    )
      .then(() => {
        localStorage.removeItem('access');
        setIsLoggedIn(false); // 로그인 상태 갱신
        console.log('logout!');
        navigate('/'); // 홈으로 이동
      })
      .catch((e) => console.log('error!', e));

 

P.S. production에서는 proxy 우회할 수 없기 때문에 브라우저에서 요청하면 cors에러가 발생하므로, 자체 서버에서 접근토큰을 삭제하는 요청을 하는 방식을 사용해야 할 것 같다.
또는 JWT의 경우 토큰에 정보가 담겨있고 토큰의 의미가 접근 권한을 의미하므로 로그아웃시에 토큰을 삭제해주는 것이 맞지만, 서버를 구축하는 여건이 안되고 네이버의 토큰이 JWT가 아닌 다른 토큰 방식이고 접근 토큰의 유효기간이 충분히 짧다면 꼭 삭제해주지 않아도 되지 않을까 라는 생각이 든다. 이 부분은 개인적인 의견으로, 확인이 필요하다.

 

3️⃣ 결과

네이버 로그인/로그아웃 구현

 

 

 

🙌 github commit 🙌

 

feat: make NAVER login and logout feat · evergarden0412/gptea-web@050f451

Show file tree Showing 7 changed files with 114 additions and 13 deletions.

github.com

 

 

Reference

https://developers.naver.com/docs/login/web/web.md

https://hun-dev.tistory.com/33

https://velog.io/@iamminzzy/TIL-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%A1%9C%EA%B7%B8%EC%9D%B8-CORS-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0

 

반응형
댓글