Kakao Developers 접속 후 로그인
내 애플리케이션 등록, 앱 아이콘, 앱 이름, 사업자명 작성
앱 키 탭의 REST API 키와 보안 탭의 Client Secret 코드를 저장
아래와 같이 카카오 로그인을 활성화하고 Redirect URI를 설정한다.

아래와 같이 Web 플랫폼 등록도 진행한다. 로컬에서 테스트할 것이기 때문에 기본 도메인은 Redirect URI와 같이 localhost로 설정한다.

동의 항목 탭에서 가져올 정보들을 선택한다. 대부분의 경우 개인정보 동의항목 심사가 필요하기에 프로젝트에서 사용할 닉네임 정도만 가져오도록 하자.


// 카카오 로그인
document.getElementById("kakaoSubmit").addEventListener("click", function () {
window.location.href = "https://kauth.kakao.com/oauth/authorize?response_type=code&"
+ "client_id={발급받은 REST API 키}&redirect_uri=http://localhost:8080/login/oauth2/code/kakao";
});
이후 카카오 로그인 화면에서 로그인을 완료하게 되면, 이전에 설정해두었던 redirect uri인 "http://localhost:8080/login/oauth2/code/kakao"로 GET요청을 보내게 된다.
@Controller
@Slf4j
@RequiredArgsConstructor
@RequestMapping(value = "/login/oauth2/code")
public class OAuth2Controller {
private final SessionLoginService sessionLoginService;
private final KakaoLoginService kakaoLoginService;
@Value("${spring.security.oauth2.client.registration.kakao.client-id}")
private String clientId;
@Value("${spring.security.oauth2.client.registration.kakao.client-secret}")
private String clientSecret;
@GetMapping(value = "/kakao")
@ResponseBody
public RedirectView kakaoLogin(@RequestParam String code, HttpServletRequest httpServletRequest) throws JsonProcessingException {
log.info("code : " + code);
// 액세스 토큰 발급 받기
String oAuth2Token = kakaoLoginService.requestToken(code, clientId, clientSecret);
// 발급받은 토큰으로 회원 정보 가져오기
Member currentMember = kakaoLoginService.requestMemberInfo(oAuth2Token);
// 세션 생성
sessionLoginService.sessionLogin(currentMember, httpServletRequest);
// 메인 페이지로 리디렉션
RedirectView redirectView = new RedirectView();
redirectView.setUrl("http://localhost:5000/mainPage.html");
return redirectView;
}
}
// 액세스 토큰 발급 받기
String oAuth2Token = kakaoLoginService.requestToken(code, clientId, clientSecret);
// 발급받은 토큰으로 회원 정보 가져오기
Member currentMember = kakaoLoginService.requestMemberInfo(oAuth2Token);
@Service
@Slf4j
@RequiredArgsConstructor
public class KakaoLoginServiceImpl implements KakaoLoginService {
private final MemberService memberService;
public String requestToken(String code, String clientId, String clientSecret) throws JsonProcessingException {
// 카카오에 POST 방식으로 key=value 데이터를 요청함.
// RestTemplate 을 사용하면 요청을 편하게 보낼 수 있다.
RestTemplate rt = new RestTemplate();
// HttpHeader 오브젝트 생성
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type",
"application/x-www-form-urlencoded;charset=utf-8");
// HttpBody 오브젝트 생성
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", "authorization_code");
params.add("client_id", clientId);
params.add("redirect_uri", "http://localhost:8080/login/oauth2/code/kakao");
params.add("code", code);
params.add("client_secret", clientSecret);
// HttpHeader 와 HttpBody 를 하나의 오브젝트에 담기
HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(params, headers);
// 오브젝트를 담아 Http POST 로 요청하기
ResponseEntity<String> response = rt.exchange(
"https://kauth.kakao.com/oauth/token", // 요청 url
HttpMethod.POST,
kakaoTokenRequest,
String.class // 응답받을 타입
);
log.info(String.valueOf(response));
// json 형태로 받은 응답을 자바의 object 형태로 파싱 후 access token 만 가져와 리턴
// Gson, Json Simple, ObjectMapper 등 사용 가능
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readTree(response.getBody()).get("access_token").asText();
}
@Override
public Member requestMemberInfo(String token) throws JsonProcessingException {
// 사용자 정보를 받아오기 위한 또 다른 RestTemplate를 사용해서 응답 받기
RestTemplate restTemplate = new RestTemplate();
// HttpHeader 오브젝트 생성
HttpHeaders httpHeaders = new HttpHeaders();
//Content-type 을 HttpHeader에 담는다는 것은 내가 담을 데이터가 key-value 데이터라고 알려주는 것이다
httpHeaders.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
httpHeaders.add("Authorization","Bearer "+ token);
//httpBody 생성 부분
HttpEntity<MultiValueMap<String, String>> kakaoProfileRequest =
new HttpEntity<>(httpHeaders);
//Http 요청하기 - POST방식 그리고 response 변수의 응답을 받음
ResponseEntity<String> responseEntity2 = restTemplate.exchange(
"https://kapi.kakao.com/v2/user/me", //요청 주소
HttpMethod.POST, //요청방법
kakaoProfileRequest, //넘기는 데이터
String.class //받아올 데이터 타입
);
log.info(String.valueOf(responseEntity2));
ObjectMapper objectMapper = new ObjectMapper();
KakaoUserDto kakaoUserDto = new KakaoUserDto(objectMapper.readTree(responseEntity2.getBody()).get("id").asLong(),
objectMapper.readTree(responseEntity2.getBody()).get("properties").get("nickname").asText());
return memberService.kakaoLogin(kakaoUserDto);
}
}