개발한 내역들이나 개발하면서 마주했던 이슈들도 앞으로 velog에 함께 정리하려고 합니다.
서비스가 고도화됨에 따라서 기존 회원가입/로그인 인증 시스템에서 소셜로그인을 이용하기로 결정이되었고, 카카오와 구글을 이용하기로 했습니다.
그 중 2주간 제가 맡았던 부분은 기존 회원가입/로그인 인증 시스템을 소셜로그인으로 바꾸기 위한 유저 모델 변경, 소셜로그인 인증 시스템 아키텍처 설계, 카카오 소셜로그인 도입이었습니다.
유저모델은, 카카오 api나 구글 api를 이용하여 가져올 수 있는 사용자 정보에 맞게 필드를 변경하였고,
소셜로그인 인증을 도입함에 따라 회원가입/로그인 아키텍처는 다음과 같이 변경하였습니다.
기존에는 회원가입과 로그인이 따로 분리가 되어있었지만,
소셜로그인 도입 후에는 UI상에는 두 시스템을 하나로 통합하였습니다.
이 과정에서 기존 회원인지의 여부는 백엔드에서 확인합니다.
인증에 있어서 외부 api를 갖다쓰는건 이번이 처음이라 사전에 공부도 많이 했었던 것이 개발하는데 있어서 많은 도움이 된 것 같습니다.
(카카오 developer에서 어플리케이션 등록이나, 인증 키 발급하는 부분은 생략하도록 하겠습니다.)
먼저, 카카오 로그인이 진행되는 과정은 다음과 같습니다.
- 사용자가 앱에서 카카오 로그인 버튼을 클릭합니다.
- 사용자가 [카카오톡으로 로그인]을 선택하면 카카오톡 실행 또는 실행 중인 카카오톡으로 연결되고, [다른 카카오계정으로 로그인]을 선택하면 직접 계정 정보를 입력하는 화면이 출력됩니다. 카카오톡이 설치되어 있지 않은 기기나 PC 웹 환경에서는 직접 계정 정보를 입력하여 카카오계정으로 로그인하게끔 진행됩니다.
- '카카오톡으로 간편로그인'한 경우, 카카오톡에 연결된 카카오계정의 자격정보(Credentials)를 통해 사용자를 인식합니다. 직접 카카오계정을 입력해 로그인한 경우 해당 계정의 자격정보로 인식합니다.
- 🔥사용자가 필수 항목에 동의하고 로그인을 요청하면 인가 코드(Authorization Code)가 발급됩니다. 이 코드는 앱 정보의 Rediret URI에 전달됩니다.🔥
- 앱은 전달 받은 인가 코드를 기반으로 토큰을 요청하고 받습니다.
저희는 구현할 때, 두 번의 시행착오를 겪었는데
처음으로 시도했던 방법은 이 모든 과정을 백엔드에서 다 처리하는 것이었습니다.(마지막 부분에서 이 과정과 안되었던 이유를 알려드리겠습니다.)
그리고 성공한 두 번째 방법은 인증 코드를 발급받는 것까지 프론트에서 구현한 뒤, 인증 코드를 백엔드에 전달한 후, 나머지 과정은 백엔드에서 구현하도록 하였습니다.
즉 다음과 같습니다
제가 개발하면서 썼던 api문서를 기반으로 설명해드리겠습니다.
💡 1. 인증코드 요청과 응답(프론트) → 2. 토큰 요청과 응답(백엔드) → 3. API 호출과 응답(백엔드)
인증코드 요청은 https://kauth.kakao.com/oauth/authorize
에
response_type
, cliend_id
, redirect_uri
를 파라미터로 전달합니다.
📌 respone_type: code
📌 client_id: 앱에서 발급받은 클라이언트 아이디값
📌 redirect_uri: (프론트의 도메인의 redirect uri를 입력하셔야 합니다)
저희 프론트 코드는 이렇게 되어있습니다.
function kakaoLogin() {
window.location.href = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.REACT_APP_KAKAO_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_KAKAO_REDIRECT_URI}&response_type=code`;
}
이렇게 요청을 날렸을 때, 응답은 설정한 redirect_uri로 인증코드(code)와 함께 돌아옵니다.
설정한 url에 코드를 파라미터로 전달해 백엔드로 보내면 됩니다.
토큰 요청은 https://kauth.kakao.com/auth/token
에
code
, grant_type
, client_id
, redirect_uri
를 파라미터로 전달합니다.
요청에 대한 응답은 json 형태로 access_token을 포함하여 돌아옵니다.
이에 해당하는 코드의 일부분입니다.
...
app_rest_api_key = .env("rest_api_key")
redirect_uri = "https://www.myplanit.site/login/kakao/callback"
code = request.GET.get('code', None)
headers = {
'Access-Control-Allow-Origin': 'https://www.myplanit.site',
'Content-type': 'application/x-www-form-urlencoded;charset=utf-8',
}
data = {
'grant_type': 'authorization_code',
'client_id': app_rest_api_key,
'redirect_uri': redirect_uri,
'code': code
}
token_req = requests.post('https://kauth.kakao.com/oauth/token', headers=headers, data=data)
token_req_json = token_req.json()
access_token = token_req_json.get("access_token")
...
API 호출은 https://kapi.kakao.com/v2/user/me
에
access_token
과 함께 보냅니다.
...
kakao_api_response = requests.post(
"https://kapi.kakao.com/v2/user/me",
headers={
"Authorization": f"Bearer {access_token}",
"Content-type": "application/x-www-form-urlencoded;charset=utf-8",
"Access-Control-Allow-Origin": "https://www.myplanit.site",
},
)
kakao_api_response = kakao_api_response.json()
user_id = kakao_api_response.get('id')
...
응답으로는 사용자의 id를 포함한 정보를 받아올 수 있습니다.
myplanit.site 로 가셔서 직접 보실수도 있습니다.☺️☺️
처음에 진행하였었던 백엔드에서 구현하는 과정에서는 방식에서는 에러가 났었는데,
바로 cors 에러였습니다.
물론 백엔드쪽에서 모든 cors-header와 관련 설정을 다 마친 상태였구요.
구글링을 하며 찾아낸 결과, preflight request(프론트에서 날린 요청)는 redirect(장고에서 날린 redirect)를 허용하지 않는 것 같습니다.
-> CORS Redirect is not allowed for a preflight request
또한, redirect에서는 body로 데이터를 넘겨줄 수 없으므로, 이렇게 접근해서는 힘들 것 같았습니다.
그래서, 앞단의 인증코드 받는 데 까지를 프론트가 처리하고, 이 이후를 백엔드에서 처리하도록 설정하였습니다.
이번주까지 모두 카카오API를 이용한 소셜로그인 구현을 모두 마쳤습니다. ㅎㅎ
뿌듯하네용🥰