[React / Node.js] 네이버 밴드 로그인 인증 구현
네이버 밴드 API로 뭔가 해보고 싶은 게 생겨서, 일단 가장 먼저 사용자인증부터 구현해보기로 했다.
네이버밴드 API 공식 문서 >> https://developers.band.us/develop/guide/api
밴드 개발자 센터
열린 공간, 함께하는 기술, 경험의 공유. BAND 플랫폼이 애플리케이션 개발에 필요한 다양한 환경을 제공합니다.
developers.band.us
1. 서비스 등록
우선 API 사용을 위해 내 앱을 등록해줘야 한다.
서비스 이름, 유형을 작성하고 리다이렉트 uri를 적어준다.
Redirect URI란, 로그인 요청을 보내 인증을 받으면 인증토큰이 오게 되는데, 그때 리다이렉트될 페이지 주소를 의미한다. 나는 현재 로컬 개발환경에서 테스트 중이고, vite를 사용한 리액트 프로젝트를 할 것이므로 http://localhost:5173/callback 과 같이 적어주었다.
이때 네이버밴드 계정에 내 전화번호가 등록되어 있어야 서비스를 등록할 수 있다. 밴드 홈페이지나 앱에 접속해 등록해주면 된다.
서비스를 등록했다면 client ID와 client secret을 얻을 수 있다.
2. Authorization Code 받기
공식문서를 읽어보면, 사용자 인증은 authorization code를 받는 요청과 토큰을 발급받는 요청으로 2가지가 필요하다. 먼저 코드부터 받아보자.
시키는 대로 하면 된다.
일단 로그인 페이지를 하나 만들어주자. UI는 나중에 만질 것이므로... 그냥 버튼 하나만 만들어줬다.
이렇게 하면 코드 받기는 끝이다. 공식문서 보면 알겠지만, 코드를 받아오면 ?code=어쩌구저쩌구 하는 페이지를 반환해준다. 우리가 필요한건 그 코드. 코드를 사용해 인증토큰을 받아줘야 하기 때문이다.
인증토큰을 처리하는 페이지를 따로 만들어주자. 그리고 location.href로 그 페이지로 이동시켜주자.
라우팅은 이런식으로 해주면 된다.
내가 리다이렉트 주소를 /callback으로 해줬기 때문에, 코드가 정상 반환될 경우 localhost:5173/callback/?code=어쩌구저쩌구 이런식으로 페이지가 반환된다.
그러므로 /callback 에 라우팅해주고, TokenPage에서는
이런 식으로 useLocation을 사용해 param을 받아주자. location.search를 써주면 쿼리문자열을 갖고올 수 있다.
3. 인증토큰 발급... 하기 전에
인증토큰도 공식문서 나와있는 대로 그냥 해주면 되는데.... 여기서 문제가 생긴다.
네이버는 보안상의 이유로 CORS policy를 deny해놨다는 것이다. 이런 세상에.!!!!!! 이게 왜 문제냐면 나는 온리 프론트만을 사용해 개발을 하고 있었고, 나는 백을 만질 줄 모르고, CORS 에러는 프론트에서는 해결을 못 하는 문제다.
그니까 회피를 할 수는 있는데..... 예전에 프로젝트 할 때 그거 회피하려고 클라이언트에서 애쓸 바에는 그냥 백에 연락해서 해결해주세용. 하는게 5억배 편했다.
그래서 그냥........ 백엔드를 만들기로 했다. 세상이 좋아서 공식문서도 많고 선인들의 지혜도 많고 짱지피티도 있다 보니... 뭐든 시작해보기가 예전에 비해 확실히 쉬우므로. 그냥 하자 ㅎㅎ
node.js의 express 프레임워크로 백엔드를 시작해보자.
프론트 폴더 밖에 백엔드용 폴더를 만들고, 폴더 들어가서
npm init -y
npm i express
로 시작하고, 루트에 app.js를 만든다.
express 공식 문서 >> https://expressjs.com/ko/starter/hello-world.html
일단 코드의 작동을 이해하기 위해 기본예제부터 시작하자.
시키는 대로 하면 된다.
쉽게 생각하면 서버를 열고, 3000번 포트에서 요청을 듣기 시작하겠다는 거다.
get이니 post니 하는 건 평소에 api 많이 써봤으니 그거랑 다 똑같다.
요새 진행하는 졸프 프로젝트에서는 백 프레임워크가 Django인데, 그건 파이썬 기반이지만 익스프레스는 js 기반이다. 즉 js가 더 익숙한 나에게는 이게 훨씬 이해하기 편했다! 그리고 따로 막 서버를 사서 뭐 하고 이거하고 저거하고 할 필요 없이 포트만 적어주면 바로 테스트 가능하다는 점도 편하다!
여튼 vite로 프로젝트 생성한 내 프론트엔드의 포트는 현재 5173번이고, 백엔드 서버의 포트는 3000번이다.
즉 프론트에서 백으로 무언가를 줄 때는 3000번으로 주면 된다는 거다. 와 쉽다!
4. 진짜 인증토큰 발급
백엔드 환경도 준비됐으니 인증토큰을 진짜로 발급받아보자.
프론트에서 할 일: 위에서 받아온 Code를 백엔드에게 주기. code는? 현재 리다이렉트된 링크의 쿼리스트링에서 뽑아준다고 했다.
이 페이지는 뭘 하는 페이지가 아니라 인증요청을 처리하는 부분이니까 useEffect를 사용해 렌더링 시 바로 처리되도록 해준다. UI는 마찬가지로... 나중에 수정...
3000번 포트의 /callback으로 요청을 보내는 거다!
그렇다면 백에서도 /callback에서 받아주고 요청 처리해주면 되는것이다
백에서 해야할 거: 공식문서에서 준 url에 필요한 필드를 채워 보내서 인증토큰 받기
캡쳐나누기 귀찮아서 주석을 열심히 달기
왜 body나 header 형식이 저런지는 공식문서를 따른 것이므로... 문서 보면 된다.
여튼 이렇게 해서 잘 응답이 처리된다면,
와! 이중에 access_token이 우리가 필요한 토큰.
이걸 뽑아서 클라이언트에 돌려줬으므로, 5173 포트로 돌아와 디버깅해보면 저 토큰이 잘 나오는 것을 볼 수 있을 것이다.
이제 밴드 계정에 로그인 처리가 잘 됐다면 메인페이지로 간다.
(근데 토큰..갖고 뭘 테스트해보진 않았다.. ㅋㅋㅋ 이래놓고 나중에 오, 트러블슈팅. 하면서 나타날 수도)
아니 근데 요새 로봇이아닙니다 테스트 왜케 어렵지?
암튼 이런식으로... 야매 백엔드로 인증까지 완료해봤다. 결국 눈물흘리며 풀스택의 길로 뚜벅뚜벅 가야하는걸까... 아냐근데 사실난 귀찮은것보단 할수있는게 많아지는 게 좋아 ㅎㅎ
🚀 트러블 슈팅
이 간단한 거 하는데도 잡음이 엄청 많았다. 근데 트러블슈팅이라 말하기도 부끄러운 것들뿐이라 (그리고 넘 짜잘해서 다 잊어버림)...
그럼에도 적자면 (부끄러움은 발전에 좋지 않다.)
1. 서버 변경사항 적용 안됨
내가 가장 오랫동안 ㅋㅋ 머리를 뜯었던 이유는.... 프론트처럼 백도 파일 저장하면 바로 서버에 반영되는 줄 알았다. 그래서 열심히 수정하고 테스트했는데 아~~무것도 안 변하길래 대체뭐지...대체뭐지.... 하다가, 간단한 콘솔로그조차 안 먹는 것을 보고 깨달았다. 아..... 이거 뭐 바꿀 때마다 일일이 서버 재시작해야된다고...............
그럴줄알고 똑똑한 사람들이 이미 다 만들어놨다. nodemon 패키지를 사용해 파일이 수정될 때마다 자동으로 서버를 재시작해줄 수 있다.
npm i nodemon
nodemon app.js 해주면 문제가 사라진다. 으하하 ㅋㅋ 이거때문에 다해놓고 왜안되냐며 머리뜯었다~~
2. API 중복 호출
인증토큰 잘 오고 모든 호출이 잘 되는데도 서버에서 자꾸 오류 로그가 찍혔다. 왜 그러지 싶었는데, 콘솔을 보니 매번 같은 게 2번씩 찍히고 있었다. 이거 때문인가? 싶어서 찾아봤다. (사실 여태 리액트 개발하며 항상 중복호출이 있었는데... 별로 신경써본 적이 없었다. 나는 서버를 만지는 사람이 아니었기에 ㅎㅎ)
리액트는 기본적으로 StrictMode라는 것을 사용하는데, 개발 중 잠재적 문제를 잡아내기 위해 설정되어 있다고 한다.
공식문서 https://react.dev/reference/react/StrictMode
<StrictMode> – React
The library for web and native user interfaces
react.dev
그렇다고 하시네요
근데 이게 활성화되어 있으면 렌더링 단계에서 의도적으로 함수를 두번 호출한다고 한다. 콘솔 2개씩 찍히는 게 이거 때문이라고...
그래서 호출이 두번씩 날라가서, 두번째 호출에서 bad request가 반환되는 것 같았다. 예상대로 StrictMode를 지우고 App/ 만 남기니 서버에서 지겹게 뜨던 긴 오류가 사라졌다.
그치만 오류 뜬다고 실행이 안 되는 것도 아니고... 혹시 또 뭔 잠재적 문제가 생길지 모르니 원래대로 돌려놨다. 어차피 배포할 때는 중복호출 안 된다고 하니 그냥 냅두건 말건 상관없는 것 같다.
갈 길이 멀다!