본문 바로가기
Web/Spring&SpringBoot

[Spring Security] OAuth2 카카오 로그인 + Jwt 토큰 발급 + 추가 정보로 회원가입(1)

by alphaca202 2024. 8. 19.

이번 프로젝트에서

OAuth2 라이브러리와 카카오 API를 사용해서 로그인과 가입을 진행하고, 

JWT 토큰을 발급해주는 Auth 서버 파트를 맡아서 진행했다. 

 

스프링으로 API 만드는 것만 해봤던 나는 ,, 

뭐 배운대로 하면 되겠지? 하는 생각으로 흔쾌히 하겠다고 했다. 

하지만 .... 일단 생각보다 프론트랑, 카카오 서버와 소통하는 전체 구조를 이해하는 것도,

Spring Security를 쓰는 것도 어려웠다.. (시큐리티 이해는 둘째치고) 😵‍💫

 

일단 !! 여기다가 이렇게 전체적인 프로젝트를 복기해볼 생각이다! 

스프링과 자바 모두 다루는게 거의 처음이라 문법이나, 코드 컨벤션, 객체지향 개념, 같은 것들이 엉망일 수 있다... 

하면서 정말 느꼈던게 스프링 강의를 들어야 겠다는.....걸 느꼈고 그러니까

혹시 잘못된 부분이 있으면 바로 댓글로 지적해주세요!!!! :)


 

일단 이번 포스팅에서는 가장 카카오 로그인의 전체 구조를 살펴볼 것이다! 

이후 포스팅에서는 jwt 토큰과 추가 회원 가입 절차에서 구현할 기능에 대해 소개하고, 

어떻게 구현되었는지 각 클래스를 살펴보면서 설명하겠다. 

 

이번 포스팅 목차 

1. 카카오 로그인의 전체 구조

2. 백에서 모든 책임을 맡을 때 발생할 수 있는 문제

3. 해결 방법 

 

 

1. 카카오 로그인의 전체 구조

 

이것이 OAuth2 카카오 로그인의 전체 구조이다. 

카카오 디벨로퍼 사이트에서 가져왔음!

 

구조를 설명해보자면,, 내가 구현하고자 하는 건 REST API로 카카오 인증을 받아서 로그인을 하는 것이다. 

 

<순서>

1. 프론트에서 하이퍼링크로 요청을 보낸다.

http://localhost:8080/oauth2/authorization/kakao

 

2. 백에서 카카오 서버로 get /oauth2/authorization/kakao 요청을 보냄. 

3. 카카오에서 로그인 웹페이지 띄움 -> 사용자가 로그인

4. 카카오에서 동의 웹페이지 띄움 -> 사용자 동의

5. 카카오가 동의한 것을 확인하면 redirect URI로 인가코드 전달 (여기서 redirect URI는 백엔드임)

6. 백엔드가 이 redirect URI로 인가코드 받은 걸로 토큰 요청

7. 카카오가 토큰을 발급

8. 카카오가 발급해 준 토큰으로 사용자 정보를 조회

9. 카카오에서 준 사용자 정보로 로그인 진행

 

이렇게 하면 백에서 모든 책임을 가지고 소셜 로그인을 구현할 수 있다. 

하지만 우리 서비스의 경우 카카오 로그인으로 받아올 수 있는 정보에다 추가로

학교와 계좌번호 등의 정보를 받아야 했기 때문에 가입이 되지 않은 경우에 가입이 되지 않았다는 응답을 보내야 했다.

 


 

2. 백에서 모든 책임을 맡을 때 발생할 수 있는 문제

 

그러나.... 프론트에서 하이퍼링크로 요청을 보내도록 해야 이 구조가 유효한데

(-> 왜 하이퍼링크로 요청을 보내야 이 구조가 유효한가?)

하이퍼링크로 보냈다보니 응답을 받을 수 없는 문제가 발생했다. 

(-> 하이퍼링크는 왜 응답을 받지 못하는가?)

 

 


3. 해결 방법 

만약 그냥 로그인만 할 경우에는 토큰을 쿠키에 담아서 보내주면 된다. 

 

하지만

1) Refresh Token과 Access Token을 둘 다 사용하는 구조로 가져가야 함

2) 가입 안된 사용자의 경우 추가 정보를 받는 페이지로 넘겨줘야 함

 

1) 번 문제의 해결 방법

  • RefreshToken을 먼저 쿠키에 심어서 보내주고 쿠키의 RefreshToken으로 AccessToken 발급
  • Get /access_token 경로 추가

2) 번 문제의 해결 방법

  • 일단 카카오 로그인을 한 유저를 AuthMember로 Auth 서버의 Repository에 저장 -> 이때 Role : Not Signup User
  • 로그인을 성공한 루트랑 똑같이 OAuth2SuccessHandler로 넘어감. -> Role이 Not Signup User이면 refresh 토큰 발급해서 쿠키에 담아 추가 가입 루트로 리다이렉
  • Not signup user의 경우 코어 서비스 서버에서 확인해서 접근 안되게 한다. -> 접근하려고 하면 추가 가입 루트 반환
  • Auth 서버에서는 로그인 해서 들어온 사용자가 Not signup user이면 -> 가입 루트로 리다이렉
  • 추가 가입 성공 하면 Role을 User로 바꿔서 AuthMember 저장하고 새로 토큰 재발급

이런 구조로 구현하였다. 

 

 

필요한 API URI 목록

1. Get /access_token : access_token 발급 uri (헤더에 RefreshToken 필요)

2. Post /signup : 추가 정보로 회원 가입 uri (헤더에 RefreshToken, AccessToken, 바디에 사용자 정보 필요)

3. Get /reissue_token : accessToken 만료 시 새로운 accessToken 발급 uri (헤더에 RefreshToken, AccessToken 필요)

 

필요한 Entity & Repository

1. AuthMember : 카카오 로그인 성공한 유저를 모두 저장 / 회원가입 안된 유저는 Not signup user로 저장

  • Uuid 
  • Username
  • Email
  • Role

2. RefreshToken : RefreshTokenRedisRepository에 들어갈 Entity

  • Id
  • Authorities (?)
  • RefreshToken

 

Service

1. KakaoMemberDetailsService : 카카오로부터 받은 유저 정보가 레포지토리에 있는지 확인하고 등록된 유저인지 아닌지에 따라 AuthMember를 갱신하고, 저장함. AuthMemberDto 반환

 

2. SignupService : 등록된 유저인지 아닌지에 따라 리다이렉 

 


 

여기까지 전체적인 로그인 과정과 회원 가입 과정에 대한 구조, 

백엔드가 모든 책임을 맡았을 때 발생할 수 있는 문제와

그에 대한 해결점을 정리해보았다. 

 

JWT 토큰 검증 관련 부분은 다음 포스팅에 올리겠습니당 !