[개발일지/플젝] Django에서 카카오API를 이용한 소셜로그인 구현

이수진·2022년 2월 26일
0
post-thumbnail

개발한 내역들이나 개발하면서 마주했던 이슈들도 앞으로 velog에 함께 정리하려고 합니다.
서비스가 고도화됨에 따라서 기존 회원가입/로그인 인증 시스템에서 소셜로그인을 이용하기로 결정이되었고, 카카오와 구글을 이용하기로 했습니다.

그 중 2주간 제가 맡았던 부분은 기존 회원가입/로그인 인증 시스템을 소셜로그인으로 바꾸기 위한 유저 모델 변경, 소셜로그인 인증 시스템 아키텍처 설계, 카카오 소셜로그인 도입이었습니다.

유저모델은, 카카오 api나 구글 api를 이용하여 가져올 수 있는 사용자 정보에 맞게 필드를 변경하였고,
소셜로그인 인증을 도입함에 따라 회원가입/로그인 아키텍처는 다음과 같이 변경하였습니다.

기존에는 회원가입과 로그인이 따로 분리가 되어있었지만,
소셜로그인 도입 후에는 UI상에는 두 시스템을 하나로 통합하였습니다.
이 과정에서 기존 회원인지의 여부는 백엔드에서 확인합니다.

  • 기존 유저 -> 기존 유저 확인 후, 토큰 발급
  • 새로운 유저 -> DB에 유저 생성 후, 토큰 발급

인증에 있어서 외부 api를 갖다쓰는건 이번이 처음이라 사전에 공부도 많이 했었던 것이 개발하는데 있어서 많은 도움이 된 것 같습니다.
(카카오 developer에서 어플리케이션 등록이나, 인증 키 발급하는 부분은 생략하도록 하겠습니다.)

먼저, 카카오 로그인이 진행되는 과정은 다음과 같습니다.

  • 사용자가 앱에서 카카오 로그인 버튼을 클릭합니다.
  • 사용자가 [카카오톡으로 로그인]을 선택하면 카카오톡 실행 또는 실행 중인 카카오톡으로 연결되고, [다른 카카오계정으로 로그인]을 선택하면 직접 계정 정보를 입력하는 화면이 출력됩니다. 카카오톡이 설치되어 있지 않은 기기나 PC 웹 환경에서는 직접 계정 정보를 입력하여 카카오계정으로 로그인하게끔 진행됩니다.
  • '카카오톡으로 간편로그인'한 경우, 카카오톡에 연결된 카카오계정의 자격정보(Credentials)를 통해 사용자를 인식합니다. 직접 카카오계정을 입력해 로그인한 경우 해당 계정의 자격정보로 인식합니다.
  • 🔥사용자가 필수 항목에 동의하고 로그인을 요청하면 인가 코드(Authorization Code)가 발급됩니다. 이 코드는 앱 정보의 Rediret URI에 전달됩니다.🔥
  • 앱은 전달 받은 인가 코드를 기반으로 토큰을 요청하고 받습니다.

저희는 구현할 때, 두 번의 시행착오를 겪었는데
처음으로 시도했던 방법은 이 모든 과정을 백엔드에서 다 처리하는 것이었습니다.(마지막 부분에서 이 과정과 안되었던 이유를 알려드리겠습니다.)

그리고 성공한 두 번째 방법은 인증 코드를 발급받는 것까지 프론트에서 구현한 뒤, 인증 코드를 백엔드에 전달한 후, 나머지 과정은 백엔드에서 구현하도록 하였습니다.

즉 다음과 같습니다

제가 개발하면서 썼던 api문서를 기반으로 설명해드리겠습니다.

💡 1. 인증코드 요청과 응답(프론트)2. 토큰 요청과 응답(백엔드)3. API 호출과 응답(백엔드)

1. 인증코드 요청(GET Request) - 프론트

인증코드 요청은 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에 코드를 파라미터로 전달해 백엔드로 보내면 됩니다.


2. 토큰 요청과 응답 (POST Request) - 백엔드

토큰 요청은 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")
...

3. API 호출과 응답 (POST Request) - 백엔드

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를 이용한 소셜로그인 구현을 모두 마쳤습니다. ㅎㅎ
뿌듯하네용🥰

profile
꾸준히, 열심히, 그리고 잘하자

0개의 댓글