본문 바로가기
한화시스템 Beyond SW Camp/백엔드

[Java] 카카오 로그인

by taeh00n 2025. 1. 31.

https://developers.kakao.com/

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

https://developers.kakao.com/docs/latest/ko/kakaologin/js

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

내 애플리케이션 추가하기

 

카카오로그인 활성화

카카오 로그인을 연동할거기 때문에 대시보드에서 카카오 로그인을 활성화 해준다.

카카오로그인 기능 구현 (앱 키, redirectUri 설정)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body><script src="https://t1.kakaocdn.net/kakao_js_sdk/2.7.4/kakao.min.js"
                integrity="sha384-DKYJZ8NLiK8MN4/C5P2dtSmLQ4KwPaoqAfyA/DfmEc1VDxu4yyC7wy6K1Hs90nka" crossorigin="anonymous"></script>
  <script>
    Kakao.init('JavaScript 키'); // 사용하려는 앱의 JavaScript 키 입력
  </script>

  <a id="kakao-login-btn" href="javascript:loginWithKakao()">
    <img src="https://k.kakaocdn.net/14/dn/btroDszwNrM/I6efHub1SN5KCJqLm1Ovx1/o.jpg" width="222"
         alt="카카오 로그인 버튼" />
  </a>
  <p id="token-result"></p>

  <script>
    function loginWithKakao() {
      Kakao.Auth.authorize({
        redirectUri: 'http://localhost:8080/kakao/code', 
        // 설정한 redirectUrl과 일치해야함
      });
    }

    // 아래는 데모를 위한 UI 코드입니다.
    displayToken()
    function displayToken() {
      var token = getCookie('authorize-access-token');

      if(token) {
        Kakao.Auth.setAccessToken(token);
        Kakao.Auth.getStatusInfo()
                .then(function(res) {
                  if (res.status === 'connected') {
                    document.getElementById('token-result').innerText
                            = 'login success, token: ' + Kakao.Auth.getAccessToken();
                  }
                })
                .catch(function(err) {
                  Kakao.Auth.setAccessToken(null);
                });
      }
    }
    function getCookie(name) {
      var parts = document.cookie.split(name + '=');
      if (parts.length === 2) { return parts[1].split(';')[0]; }
    }
  </script>
  </body>
</html>

 

 

위의 동작은 카카오 로그인 버튼을 클릭 시 loginWithKakao() 가 실행된다.

카카오 OAuth 인증 페이지로 이동해서 로그인 진행 후 로그인이 완료되면 설정한 redirectUri로 이동하여 인증 결과를 전달한다.

JavaScript 키는 앱 키에서 복사해오고 RedirectUri는 꼭 동일하게 설정을 해줘야한다.

KakaoController

@WebServlet("/kakao/*")
public class KakaoController extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String action = request.getPathInfo();
        if ("/code".equals(action)) {
            System.out.println("카카오가 코드를 보내줬다.");
            //인가 코드
            String code = request.getParameter("code");
            System.out.println("카카오에게 받은 인가 코드 : " + code);

            // 인가 코드로 토큰 발급 요청 (HTTP POST로 https://kauth.kakao.com/oauth/token	에 요청 보내기)
            try {
                // HttpClient 생성
                HttpClient client = HttpClient.newHttpClient();

                String formData = String.format(
                        "grant_type=authorization_code&client_id=REST API 키&redirect_uri=http://localhost:8080/kakao/code&code=%s",
                        URLEncoder.encode(code, StandardCharsets.UTF_8)
                );

                // HttpRequest 생성
                HttpRequest httpRequest = HttpRequest.newBuilder()
                        .uri(URI.create("https://kauth.kakao.com/oauth/token"))
                        .header("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
                        .POST(HttpRequest.BodyPublishers.ofString(formData))
                        .build();

                // 요청 보내고 응답 받기
                HttpResponse<String> httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());

                // 응답 출력
                System.out.println("인가 코드로 토큰을 요청했을 때 응답 : " + httpResponse.body());

                String token = httpResponse.body().split("\"access_token\":\"")[1].split("\"")[0];
                System.out.println("인가 코드로 토큰을 요청했을 때 응답에 포함된 토큰 : " + token);


                httpRequest = HttpRequest.newBuilder()
                        .uri(URI.create("https://kapi.kakao.com/v2/user/me"))
                        .header("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
                        .header("Authorization", "Bearer "+token)
                        .POST(HttpRequest.BodyPublishers.ofString(formData))
                        .build();

                httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
                System.out.println("토큰으로 사용자 정보를 요청했을 때 응답 : " +  httpResponse.body());
                System.out.println("토큰으로 사용자 정보를 요청했을 때 응답에 포함된 사용자 정보 : " +
                        httpResponse.body().split("\"nickname\":\"")[1].split("\"")[0]);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

위의 코드는 /kakao/code로 요청이 오면 실행된다.

사용자가 카카오 로그인을 하면 redirect_uri로 설정된 곳으로 인가 코드가 전달된다.

request.getParameter를 통해서 인가 코드를 가져오고 인가 코드로 https://kauth.kakao.com/oauth/token에 토큰 요청을 POST 방식으로 보낸다.

토큰 요청 응답에서 access Token을 추출 후 access Token을 이용해 사용자 정보를 요청한다.

 

formData에 카카오 토큰 요청에 필요한 데이터를 담아야 한다, 이때 client_id 에는 REST API 키를 입력해줘야 한다.

 


API 요청을 별도 유틸 메서드로 분리

public class HttpClientUtil {
    private static HttpClient client;
    private static HttpRequest httpRequest;
    private static HttpResponse<String> httpResponse;

    public static String sendPost(String url, String contentType, String body) {
        try {
            client = HttpClient.newHttpClient();
            httpRequest = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .header("Content-Type", contentType)
                    .POST(HttpRequest.BodyPublishers.ofString(body))
                    .build();
            httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());

            return httpResponse.body();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    // access token 추출
    public static String getAccessToken(String code) {
        String response = sendPost(
                "https://kauth.kakao.com/oauth/token",
                "application/x-www-form-urlencoded;charset=utf-8",
                "grant_type=authorization_code&client_id=REST API 키&redirect_uri=http://localhost:8080/kakao/code&code=" + code
        );
        return response.split("\"access_token\":\"")[1].split("\"")[0];
    }
    // 닉네임 추출
    public static String getUserNickname(String code) {
        try {
            String token = getAccessToken(code);
            httpRequest = HttpRequest.newBuilder()
                    .uri(URI.create("https://kapi.kakao.com/v2/user/me"))
                    .header("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
                    .header("Authorization", "Bearer " + token)
                    .GET()
                    .build();
            httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
            return httpResponse.body().split("\"nickname\":\"")[1].split("\"")[0];
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

 

import utils.HttpClientUtil;

public class KakaoService {
    public boolean kakaoLogin(String code) {
        String userNickname = HttpClientUtil.getUserNickname(code);
        return true;
    }
}