카카오 로그인 - 외부 API 관리

카일·2020년 9월 11일
5

우아한 테크 마켓

목록 보기
2/6
post-thumbnail

안녕하세요. 이번 포스팅에서는 Oauth2를 활용한 카카오 로그인 과정에서 고민했던 문제에 대해서 공유하고자 합니다. 카카오 로그인 관련된 포스팅은 2편에 이어서 할 예정이며 내용은 아래와 같습니다!

  • 외부 API를 사용하는 클래스를 어디서 관리해야 하는가(모듈)? - 이번 포스팅
  • 외부 API를 어떻게 테스트 할까? - 다음 포스팅

Interface와 모듈 분리를 사용하여 구현하였습니다. 관련 코드는 여기서 확인하실 수 있습니다. 👈

카카오 로그인 프로세스

많은 분이 OAUTH2를 사용한 소셜 로그인을 많이 구현해 보셨을거에요! 그래서 이번 포스팅은 구현보다는 Oauth2 전체 프로세스에 대해서만 간략하게 언급하겠습니다. 잘 아시는 분은 바로 아래로 넘어가시면 될 것 같아요!

카카오 로그인

카카오 로그인이 이루어지는 과정은 아래와 같습니다. 각 과정에서 주의해야 할 점들을 간단하게 요약했습니다. 아래의 프로세스가 아시는 분에게는 쉽겠지만, 처음 해보는 분들께는 어려울 수 있습니다.(저에게 어려웠기 때문에..)
중요한 포인트만 요약하자면 인증된 사용자라는 것이 확인된 결과로 카카오 서버는 CODE를 반환합니다. 이 코드를 바탕으로 해당 유저에 접근할 수 있는 토큰을 요청하고 응답으로 받은 토큰으로 사용자 정보를 조회하거나, 다른 요청을 추가로 보낼 수 있습니다.

  1. 사용자는 카카오 로그인을 버튼을 클릭 한다.
  2. 서버나 클라이언트에서 카카오 로그인 페이지로 리다이랙트한다.
  3. 사용자는 카카오 로그인 페이지에서 로그인을 하고 확인을 누른다.
  4. 카카오 서버는 해당 사용자를 확인하여 인증된 사용자인 경우 우리 서버로 요청을 보낸다.
    • 카카오 서버는 이 때 우리가 등록한 URL을 사용한다.
    • 인증된 사용자라는 것을 증명하기 위해서 URL에 Query Param으로 Code라는 것을 함께 보낸다.
  5. 우리 서버는 카카오에 등록한 정보를 함께 카카오 서버로 요청한다. - 이에 카카오 서버는 토큰을 응답한다.
    • 카카오 로그인에서 주의할 점은 ClientID, 4번에서 받은 Code 등의 정보를 QueryParam으로 보내야 한다.
    • 다른 소셜 로그인은 일반적으로 Body를 사용하는데, 카카오는 QueryParam으로 보내야 한다!
  6. 카카오에서 받은 Token을 다시 카카오에게 보내며 사용자 정보를 요청한다.
  7. 응답 받은 카카오 유저 정보를 바탕으로 우리의 사용자를 생성한다.

추가로 한 일

위의 과정을 완료하면 카카오 로그인은 완료가 됩니다. 여기에 추가적으로 저는 카카오에서 제공하는 토큰을 저의 서비스 토큰으로 변환하는 작업을 추가하였습니다. 이러한 작업을 수행한 이유는 다음과 같습니다.

  • 이미 카카오 토큰에 종속적이지만, 카카오 토큰을 그대로 사용하는 것은 저의 서비스가 카카오에 너무 종속적인 형태가 된다고 생각했습니다.
  • 토큰이란 저의 서비스에 대한 인증 및 인가를 하기 위한 도구입니다. 즉 제가 직접 컨트롤 할 수 있어야하며 서비스에 대한 토큰 전략을 결정할 수 있어야 합니다.

외부 API 관리

카카오 로그인을 하기 위해서 추가한 코드들은 어떤 패키지에 위치하는 것이 바람직할지 고민해 보았습니다.

회원과 로그인의 관계에 대해서 고민 해본다면 이에 대한 답을 찾을 수 있을 것 같습니다.

Q. 질문

  • 소셜 로그인은 회원 패키지에서 담당해야 하는 역할인가?

A.답변

  • 관심사의 분리 관점에서 회원과 로그인 모듈은 분리하는 것이 바람직하다고 생각합니다. 회원 패키지는 회원과 관련된 기능만을 수행해야 합니다. 로직의 규모가 작은 경우 로그인 관련 로직이 회원 도메인에 들어올 수 있지만, 장기적인 관점에서 회원과 로그인의 관심사를 분리함으로써 회원은 조금 더 순수하게 회원 관련된 로직에만 집중할 수 있습니다. 둘의 관심사를 분리하는 것이 어려운 일이라면 굳이 지금 할 필요는 없다고 생각합니다. 다만 분리하는 것과 분리하지 않는 것의 차이가 미비하기 때문에 로직이 적은 지금도 분리하는 것이 낫다고 생각합니다.
  • 변경이 자주 일어나는 곳이 덜 일어나는 곳에 의존해야 한다. 소셜 로그인은 카카오 로그인뿐 아니라 네이버, 페이스북 등 다양하게 있습니다. 네이버 로그인이 새로 추가되는 경우 회원 패키지의 코드를 변경해야 할 확률이 높아집니다. 하지만 LoginService가 MemberService에 의존하는 경우 새로운 로그인 방법이 추가되어도 변경의 확률이 거의 희박합니다.(로그인 및 회원가입에서 사용하는 MemberService API는 create & find 정도이기 때문에 거의 바뀔 일이 없는 API입니다.) 따라서 변경이 상대적으로 자주 일어나는 곳에서 적게 일어나는 곳을 의존하는 것이 맞다고 생각합니다.
  • 물론 KakaoLoginService , NaverLoginService를 추상화한 LoginService에 의존한다면 새로운 로그인 방법이 추가되어도 회원 패키지를 변경할 일은 적을 것입니다. 하지만 그럼에도 불구하고 외부 API 스펙이 바뀐다면 추상화된 인터페이스도 변경의 여지가 있습니다. 즉 변경될 확률이 조금 더 높다고 생각합니다.
  • 위와 같은 이유로 저는 Login과 Member패키지를 분리하고 Login 패키지에서 Member 패키지를 의존하는 형태로 구상하였습니다.

사실 Oauth2라는 규약과 함께 외부 모듈이 드라마틱하게 변경될 일은 없을 것 같습니다. 또한 사소한 변경은 LoginService의 구현체만 변경하면 되기 때문에 서로 어떤 형태로 의존하더라도 크게 문제는 없을거라 생각합니다. 다만 어떤게 조금 더 합리적일까라는 관점에서 저의 생각이니, 혹시 이상하거나 다르게 생각하신다면 알려주시면 감사하겠습니다!!

1개의 댓글

comment-user-thumbnail
2021년 5월 16일

잘봤읍니다

답글 달기