[카카오 로그인 연동 1] 간단시리 카카오로그인 처리 흐름 이해하기
✨ INTRO
우리 서비스에 계정이 필요해서 이참에 카카오로그인을 연동해보자고 했다.
*참고로 SpringBoot 백엔드와 React 프론트엔드로 이루어진 전형적인 웹서비스다.
처음 해보는거라 가장 전체적인 과정을 이해해나갔다.
카카오 로그인 과정에서 가장 먼저 생각해야 할 것은 당연히 사용자의 카카오 로그인일 것이다. 즉 프론트 측에서 이루어져야 하는 과정을 먼저 이해하는 것이 자연스러울 것 같다.
요약하자면 '인가 코드'와 '토큰'을 받아와서
🪄 큰 흐름 알기
서버에 카카오 로그인 요청이 들어오면 아래 흐름대로 로그인을 처리한다.
프론트엔드 / 백엔드로 구분하자면 우리팀은 이렇게 구현했다.
1) 인가 코드 받기 (프론트엔드)
서버가 카카오에 인가코드 받기를 GET 요청하면, 카카오가 사용자에게 카카오로그인 인증을 요청한다. 즉 카카오로그인 페이지를 띄워준다. (만약 이미 카카오계정 세션이 유효하게 있는 상태면 로그인 과정을 당연히 생략한다.)
사용자가 카카오계정으로 로그인하면 사용자에게 '인가'를 위한 동의를 받는다. 이때 사용자는 '동의하고 계속하기' 버튼을 누르게 된다. 그럼 카카오는 Redirect URI로 인가 코드를 전달한다. 이 Redirect URI는 Kakao Developer 사이트에서 미리 설정하게 되어있으며, 프론트엔드 엔드포인트를 지정하면 된다. 그러면 인가코드는 프론트엔드가 잘 받아온다. 이 코드를 서버에 던져준다.
.
.
2) 토큰 받아서 가입처리 (백엔드)
그럼 이제 서버가 전달받은 인가코드를 사용해서 토큰을 요청해 받아오면 되는 구조다.
서버는 카카오로부터 받은 토큰으로 '사용자 정보 가져오기'를 요청할 수 있다. 간단히 말해 카카오 유저 정보를 가져오는 것이다.
그리고 우리 서비스 나름대로 회원가입 절차를 거치면 된다. 좀 더 자세히 설명하자면, 예를 들어 email을 로그인 아이디로 쓸 경우, 인가코드를 통해 카카오로부터 카카오이메일 정보를 불러온다면, 해당 이메일이 우리서비스만의 DB에 있는지 검토하면 가입 여부를 알 수 있는 것이다.
아무튼 그렇게 서버에서는 회원가입여부를 확인 후 로그인과정 or 회원가입 과정을 진행한다. 이때 우리 서비스에서 부가적으로 필요한 로그인, 회원가입 절차를 별도로 넣어줄 수 있다. 그렇게 처리가 완료된다.
🪄 좀 더 자세히: 요청과 응답
로그인 구현에 꼭 필요한 값만 정리해보겠다.
1) 인가 코드 받기
----- 요청 -----
쿼리 스트링으로 아래 정보를 담아 GET요청한다.
https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}
client_id: String
└> REST API 키임. [내 애플리케이션] > [앱 키]에서 확인.
redirect_uri: String
└> [내 애플리케이션] > [카카오 로그인] > [Redirect URI]에서 등록.
response_type: String
└> 이 값은 code라는 문자열로 고정한다.
----- 응답 -----
쿼리 스트링으로 응답이 돌아온다. Location의 code 값을 확인하면 된다.
HTTP/1.1 302 Found
Content-Length: 0
Location: ${REDIRECT_URI}?code=${AUTHORIZE_CODE}
code: String
└> '인가 코드' (토큰 받기 요청에 필요)
2) 토큰 받기
토큰 받기까지 마쳐야 카카오 로그인을 마칠 수 있다.
결론부터 말하자면... 토큰을 받기 위한 POST 요청 후 두 종류의 토큰을 응답받을 수 있다.
- 액세스 토큰: 사용자 인증, 카카오 API 호출 권한 부여하는 용도다. 만료 시간은 REST API를 사용했을 경우 6시간이다. (Android, iOS는 12시간이며, JavaScript는 2시간이다.)
- 리프레시 토큰: 액세스 토큰 재발급에 사용된다. 유효한 리프레시 토큰이 있다면, 사용자가 매번 카카오 로그인하는 인증 절차를 거치지 않아도 액세스 토큰 재발급이 가능하다. 만료 시간은 2달인데, 1달 남았을 때 갱신 가능하다.
(우리 서버는 액세스 토큰만 이용중이다)
참고: 액세스 토큰을 가지고 카카오 측에서 어떻게 처리하냐면...
- 액세스 토큰을 통해서 '토큰 정보 보기'로 액세스 토큰 유효성 검증 후,
- '사용자 정보 가져오기' API를 요청해 필요한 카카오로부터 사용자 정보를 받아 서버 DB에다가 회원가입(로그인)을 완료하는 트랜잭션을 처리한다.
----- 요청 -----
https://kauth.kakao.com/oauth/token로 POST요청 보낸다.
POST요청을 보낼 때 Content-type 헤더는 Content-type: application/x-www-form-urlencoded;charset=utf-8로 지정하라는데, 우리 서버에서 딱히 헤더 지정 없이 보내긴 했다.
body에는 다음 내용을 담는다.
grant_type: String
└> authorization_code 라는 문자열로 고정!
client_id: String
└> 아까랑 동일한 REST API 키임. [내 애플리케이션] > [앱 키]에서 확인.
redirect_uri: String
└> 아까랑 동일한, 인가 코드가 리다이렉트됐던 그 URI임.
code: String
└> 인가 코드 (프론트한테서 넘겨받은!)
----- 응답 -----
token_type: String
└> 토큰 타입인데, bearer 라는 문자열로 고정되어있다.
access_tocken: String
└> 사용자 액세스 토큰 값
expires_in: Integer
└> 액세스 토큰의 만료 시간(초)
refresh_token: String
└> 사용자 리프레시 토큰 값
refresh_token_expires_in: Integer
└> 리프레시 토큰 만료 시간(초)
==> 요청과 응답을 요약하자면 '인가코드를 통해 액세스 토큰 받기' 이다.
3) 사용자 로그인 처리
발급받은 액세스토큰을 가지고,
https://kapi.kakao.com/v2/user/me라는 URL에 access 토큰을 실어서 get요청 보내면 된다. 예를 들어 java에서는 이렇게 설정.. connection.setRequestProperty("Authorization", "Bearer " + accessToken);
그리고나서 connection.getInputStream()하면 내용 읽어들일 수 있고.. 그렇다! 여기서는 대충 설명하겠다. 자세한 백엔드 코드는 나중에..!
아무튼 응답을 읽어들이면, 카카오 유저 정보를 가져올 수 있다. email, kakao 전용 id 숫자 등등..
이제 필요한 정볼르 통해 우리DB에 가입된 유저가 있는지 확인하고, DB에 없는 유저면 회원가입처리하면 된다. 우리는 카카오 email 기준으로 가입시켰다. 그래서 우리는 jwt 토큰을 email 기반으로 생성해 사용하고 있다. 즉 프론트엔드와 백엔드가 jwt 토큰을 주고받고, 백엔드 서버에서 처리할 때 TokenProvider를 통해 디코딩하여 email을 얻는 구조다.