카카오 로그인 구현하기

DDEO._.NU·2025년 7월 11일

Spring

목록 보기
4/5

카카오 로그인을 구현하기 위한 애플리케이션 생성이 진행 되었다는 가정하에 작성된 내용입니다.

시작하기!

기본적으로 카카오 로그인 페이지를 호출하기 위해
https://kauth.kakao.com/oauth/authorizeclient_id redirect_uri response_type 을 파라미터에 붙여 접속해야 합니다.

이 때 CORS가 발생할 수 있으니 주의해야합니다.
CORS에 대해서 알고 싶으시다면 👉 https://velog.io/@dbxlf3018/CORS 👈

카카오 로그인 페이지에 접속하여 로그인이 정상적으로 끝나게 되면 작성한 redirectUri로 인가코드를 넘겨받게 됩니다.

public String oauthRedirect(HttpServletRequest request){
		// 카카오로부터 인가코드를 파라미터로 전달 받음
        String code = request.getParameter("code");

        try {
            // 전달받은 인가코드를 통해 accessToken 발급
            // OAuthToken 객체는 토큰을 넘겨받기 위해 생성한 별도의 객체
            OAuthToken oAuthToken = kakaoApi.getAccessToken(code);

            // 발급받은 토큰을 통해 사용자 정보 조회
            KakaoProfile profile = kakaoApi.getUserInfo(oAuthToken.getAccessToken());
        }catch(Exception e) {
            e.printStackTrace();
        }

        return "/login/redirect";
    }

반환받은 인가코드를 통해 카카오로 부터 인증 토큰을 발급받고 그 토큰을 가지고 로그인한 사용자의 정보를 받아올 수 있습니다.

getAccessToken()

/**
* 인가 코드를 받아 accessToken을 반환하는 메소드
*/
public OAuthToken getAccessToken(String code) {
        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", kakaoApiKey);
        params.add("redirect_uri", redirectUri);
        params.add("code", code);

        //http 바디(params)와 http 헤더(headers)를 가진 엔티티
        HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest =
                new HttpEntity<>(params, headers);

        //reqUrl로 Http 요청 , POST 방식
        ResponseEntity<String> response = rt.exchange(token, HttpMethod.POST, kakaoTokenRequest, String.class);

        String responseBody = response.getBody();

		// GsonBuilder를 사용해서 camelCase를 적용하여 OAuthToken의 객체에 값 적용
        Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
        OAuthToken oAuthToken = gson.fromJson(responseBody, OAuthToken.class);

        return oAuthToken;
    }

OAuthToken

넘겨받는 토큰을 저장할 수 있는 간단한 객체를 만들었습니다.

@Getter
@Setter
public class OAuthToken {
    private String accessToken;
    private String refreshToken;
    private Date accessTokenExpiresAt;
    private Date refreshTokenExpiresAt;
    private String idToken;
    private List<String> scopes;
}

getUserInfo

인증 토큰을 카카오 프로필 호출 url에 같이 담아 보내 사용자의 프로필 정보를 반환받을 수 있습니다.

public KakaoProfile getUserInfo(String accessToken){
        RestTemplate rt = new RestTemplate();
        
        //HttpHeader 오브젝트
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Bearer " + accessToken);
        headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
        
        //Http 헤더를 가진 엔티티
        HttpEntity<MultiValueMap<String,String>> kakaoProfileRequest = new HttpEntity<>(headers);

        //카카오 프로필 호출 url로 Http요청(POST)
        ResponseEntity<String> response = rt.exchange(profile, HttpMethod.POST, kakaoProfileRequest, String.class);

        KakaoProfile kakaoProfile = new KakaoProfile(response.getBody());

        return kakaoProfile;
    }

KakaoProfile

넘어오는 프로필 정보 중 동의를 받는 정보일 경우 kakao_account 객체 안에 정보가 담겨있어 KakaoProfile에 저장 시 별도의 처리를 해주었습니다.

@Getter
@Setter
public class KakaoProfile {
    // 카카오 식별 아이디값
    private Integer id;
    // 로그인 시간
    private Date connectedAt;
    // 이메일
    private String email;

    // 프로필 정보 저장 시 데이터 가공 처리
    public KakaoProfile(String jsonResponseBody){
        JsonParser parser = new JsonParser();
        JsonElement element = parser.parse(jsonResponseBody);
        JsonObject kakaoAccount = element.getAsJsonObject().get("kakao_account").getAsJsonObject();

        this.id = element.getAsJsonObject().get("id").getAsInt();
        this.email = kakaoAccount.get("email").getAsString();


        String connected_at = element.getAsJsonObject().get("connected_at").getAsString();
        connected_at = connected_at.substring(0, connected_at.length() - 1);
        LocalDateTime connectDateTime = LocalDateTime.parse(connected_at, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"));
        this.connectedAt = Date.valueOf(connectDateTime.toLocalDate());
    }

}

이렇게 반환받은 정보를 토대로 DB에 저장 후 세션에 담아 화면에서 로그인 관련 처리를 진행할 수 있습니다.

카카오의 경우 사용자별 고유의 ID값이 같이 넘어오기 때문에 한번 DB에 저장하면 다음에 로그인 했을 때 이미 등록된 사용자인지 확인할 수 있습니다.

0개의 댓글