1편에서는 카카오 로그인을 코드로 구현하기 전에 사전설정을 해봤습니다. 오늘은 Spring Boot에 카카오 로그인을 코드로 구현해보도록 하겠습니다.
https://noaahhh.tistory.com/122
[Spring Boot] 카카오 소셜 로그인 구축기1
카카오 소셜 로그인 구현하기 전에 사전에 설정해야할 것들이 생각보다 많다 글을 읽으면서 잘 따라와 주길 바란다. 0. 카카오 개발자 계정 만들기카카오 개발자 계정이 없다면 아래 링크를 클
noaahhh.tistory.com
만약 설정을 안 하신 분이라면 위의 링크를 들어가 설정해주시기 바랍니다.
참고로 현재의 카카오 로그인은 Spring Security와 JWT 토큰 형식으로 진행되므로 Spring Security 관련 내용은 아래 링크를 참고해주길 바랍니다.
https://noaahhh.tistory.com/121
[Spring Boot] Spring Security를 이용한 인증/인가
Spring Security란?Spring Security는 Spring 기반 애플리케이션에 인증(Authentication)과 인가(Authorization) 기능을 제공하는 강력한 보안 프레임워크입니다. 핵심 특징인증(Authentication)과 인가(Authorization) 처리
noaahhh.tistory.com
1. 아키텍처 설계
참고!!: 아키텍처는 프론트와 백엔드를 구분하는 서비스를 기준으로 작성되었다.
[DB설계]

- DB에 저장을 위한 엔티티는 플랫폼을 구분하는 Provider와 ProviderId를 나눠서 저장
[인증흐름도]

- Client: 카카오에서 인증코드를 받고 서버에 요청을 보내면서 이후 과정은 서버에 넘긴다.
- Server: 클라이언트에서 받은 인증코드를 이용하여 카카오에 접근토큰을 요청하고 접근토큰을 이용해서 유저정보를 요청한다.
2. 설정
[요청설정]
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
카카오서버에 요청하는 RestTemplates는 의존성 주입해서 사용하기 위해 빈으로 등록해준다.
[요청DTO]
@Getter
@Setter
public class KakaoRequest {
@NotBlank
private String code;
}
[응답DTO]
@Getter
@Setter
@AllArgsConstructor
public class LoginResponse {
private String accessToken;
}
3. 서비스
[컨트롤러]
@PostMapping("/kakao/login")
public LoginResponse kakaoLogin(@Valid @RequestBody KakaoRequest request) {
return kakaoService.login(request);
}
[서비스]
public class KakaoService {
private final MemberRepository memberRepository;
private final JwtTokenProvider jwtTokenProvider;
private final RestTemplate restTemplate;
private static final String KAKAO_REDIRECT_URI = "http://localhost:5173/oauth/callback";
private static final String KAKAO_CLIENT_ID = "내거클라이언트아이디넣기";
private static final String KAKAO_CLIENT_SECRET = "내거클라이언트시크릿넣기";
private static final String KAKAO_TOKEN_URL = "https://kauth.kakao.com/oauth/token";
private static final String KAKAO_USERINFO_URL = "https://kapi.kakao.com/v2/user/me";
@Transactional
public LoginResponse login(KakaoRequest request) throws IllegalAccessException {
//접근토큰 요청
String accessToken = getKakaoAccessToken(request);
//유저정보 요청
KakaoUserInfo userInfo = getKakaoUserInfo(accessToken);
//유저정보 생성
String username = createMember(userInfo).getUsername();
//토큰생성
String jwtToken = jwtTokenProvider.createAccessToken(username);
return new LoginResponse(jwtToken);
}
서버의 인증흐름은 다음과 같다
- 접근토큰요청
- 유저정보요청
- 유저정보 DB에 생성
- jwt토큰반환
4. 액세스 토큰 요청
//카카오 접근토큰 요청
private String getKakaoAccessToken(KakaoRequest req) throws IllegalAccessException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 꼭 필요
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "authorization_code");
body.add("code", req.getCode());
body.add("client_id", KAKAO_CLIENT_ID);
body.add("client_secret", KAKAO_CLIENT_SECRET);
body.add("redirect_uri", KAKAO_REDIRECT_URI);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(body, headers);
ResponseEntity<KakaoTokenResponse> response = restTemplate.exchange(
KAKAO_TOKEN_URL,
HttpMethod.POST,
request,
KakaoTokenResponse.class
);
if(response.getBody() == null){
throw new IllegalAccessException("토큰 요청실패");
}
return response.getBody().getAccessToken();
}
카카오의 액세스토큰 요청형식에 맞춰서 토큰 요청로직을 작성한다.
5. 유저 정보 요청
//카카오 유저정보 요청
private KakaoUserInfo getKakaoUserInfo(String accessToken) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setBearerAuth(accessToken); // Authorization: Bearer {token}
HttpEntity<Void> request = new HttpEntity<>(headers);
ResponseEntity<KakaoUserInfo> response = restTemplate.exchange(
KAKAO_USERINFO_URL,
HttpMethod.GET,
request,
KakaoUserInfo.class
);
if(response.getBody() == null){
throw new CUnAuthorizedException("유저정보 요청이 실패했습니다.");
}
return response.getBody();
}
요청하여 받은 인증토큰을 이용해서 유저정보를 요청하는 로직을 작성한다.
5. 유저 정보 생성 및 저장
//회원 생성
private Member createMember(KakaoUserInfo userInfo) {
String providerId = userInfo.getId().toString();
Provider provider = Provider.KAKAO;
boolean exists = memberRepository.existsByProviderAndProviderId(provider, providerId);
if(exists) return memberRepository.findByProviderAndProviderId(provider, providerId)
.orElseThrow(CMissingDataException::new);
Member member = new Member(provider, providerId);
return memberRepository.save(member);
}
6. 적용결과
[로그인화면]

[동의항목]

[성공]

'프로젝트' 카테고리의 다른 글
| [Spring Boot] 카카오 소셜 로그인 구축기1 (0) | 2025.11.08 |
|---|---|
| [Spring Boot] Spring Security를 이용한 인증/인가 (0) | 2025.11.08 |
| [Spring Boot] QueryDSL 적용기 (0) | 2025.11.07 |