Spring Boot에서 RestTemplate을 통해 카카오 Open API를 호출하여 사용자 정보 받기
*SNS 간편로그인 - 카카오 API 사용 등록 방법 완료 후 진행(관련 글 참고)
*프로세스는 아래 카카오 공식 문서 참고(구글과 네이버 모두 동일)
*Swagger3 관련 소스 포함
*자세한 설명 생략
▷ application.properties 설정
#KAKAO
kakao.client.id="KAKAO에서 제공한 Client ID"
kakao.redirect.uri="KAKAO에 설정한 Redirect URI"
▷ kakao.html
*로그인 화면(간단히 버튼만 생성)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>카카오 테스트 페이지</title>
</head>
<body>
<div align="center">
<h1>카카오 로그인 테스트</h1><br><br>
<a th:href="
@{https://kauth.kakao.com/oauth/authorize(
client_id=${clientId},
redirect_uri=${redirectUri},
response_type=${responseType}
)}">
<img src="/images/kakao_login_btn.png">
</a>
</div>
</body>
</html>
▷ CmmUtil.java
*공통 유틸리티
/**
* 공통 유틸리티
*/
public class CmmUtil {
/**
*
* Object to String
*
* @param Object
* @return String
* @throws JsonProcessingException
*/
public static String getObjStr(Object obj) throws JsonProcessingException {
return new ObjectMapper()
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.writeValueAsString(obj);
}
}
▷ KakaoController.java
* 로그인 화면 진입 Controller 생성
/**
* 카카오 TEST Controller
*/
@Controller
@RequestMapping("test")
public class KakaoContrller {
@Value("${kakao.client.id}")
private String KAKAO_CLIENT_ID;
@Value("${kakao.redirect.uri}")
private String KAKAO_REDIRECT_URI;
@GetMapping("/kakao.do")
public String kakaoLogin(Model model){
model.addAttribute("clientId", KAKAO_CLIENT_ID);
model.addAttribute("redirectUri", KAKAO_REDIRECT_URI);
model.addAttribute("responseType", "code");
return "kakao";
}
}
▷ LGN1001Controller.java
*Redirect Controller 생성
/**
* 카카오 Login Controller
*/
@Slf4j
@RestController
@RequestMapping("xxxx")
@Tag(name = "LGN", description = "Login Controller")
public class LGN1001Controller {
@Autowired
private LGNService lgnService;
@GetMapping("/kakao/login.do")
@Operation(summary = "XXXX-LGN-1001", description = "[카카오] 로그인(Redirect)")
public LGN1001ResVO lgn1001(@Parameter(description = "인가 코드") @RequestParam("code") String code) {
LGN1001ResVO resVO = new LGN1001ResVO();
try {
resVO = lgnService.getLGN1001(code);
log.info("[카카오] 로그인 최종 응답");
log.info(CmmUtil.getObjStr(resVO));
} catch (Exception e) {
}
return resVO;
}
}
▷ LGN1001ResVO.java
*최종 응답 VO
/**
* [카카오] 로그인 응답 VO
*/
@Getter
@Setter
@ToString
@Schema(description = "[카카오] 로그인 응답 VO")
public class LGN1001ResVO extends CmmResVO {
/** 결과 값 */
@JsonProperty("result")
@Schema(description = "결과 값")
public LGN1001VO result;
@Getter
@Setter
@ToString
@Schema(description = "[카카오] 로그인 응답 VO")
public static class LGN1001VO {
@JsonProperty("id")
@Schema(description = "ID")
public long id;
@JsonProperty("connected_at")
@Schema(description = "서비스에 연결 완료된 시각")
public String connectedAt;
@JsonProperty("kakao_account")
@Schema(description = "카카오계정 정보")
public KakaoAccountVO kakaoAccount;
@JsonProperty("properties")
@Schema(description = "사용자 프로퍼티")
public propertiesVO properties;
@Getter
@Setter
@ToString
@Schema(description = "카카오계정 정보 VO")
public static class KakaoAccountVO {
@JsonProperty("profile_nickname_needs_agreement")
@Schema(description = "사용자 동의 시 닉네임 제공 가능")
public boolean profileNicknameNeedsAgreement;
@JsonProperty("profile")
@Schema(description = "프로필 정보")
public ProfileVO profile;
}
@Getter
@Setter
@ToString
@Schema(description = "프로필 정보 VO")
public static class ProfileVO {
@JsonProperty("nickname")
@Schema(description = "닉네임")
public String nickname;
@JsonProperty("is_default_nickname")
@Schema(description = "닉네임이 기본 닉네임인지 여부")
public Boolean isDefaultNickname;
}
@Getter
@Setter
@ToString
@Schema(description = "사용자 프로퍼티 VO")
public static class propertiesVO {
@JsonProperty("nickname")
@Schema(description = "닉네임")
public String nickname;
}
}
}
▷ CmmResVO.java
*공통 응답
/**
* 공통 응답 VO
*/
@Getter
@Setter
@ToString
@Schema(description = "공통 응답 VO")
public class CmmResVO {
/** Result Code */
@JsonProperty("resultCode")
@Schema(description = "Result Code")
public String resultCode = "0000";
/** Result Msg */
@JsonProperty("resultMsg")
@Schema(description = "Result Msg")
public String resultMsg = "성공";
/** Set Result */
public CmmResVO setResCmmResult(String resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
return this;
}
}
▷ LGNService.java
/**
* Login Service
*/
public interface LGNService {
/** [카카오] 로그인 **/
public LGN1001ResVO getLGN1001(String code);
}
▷ LGNServiceImpl.java
/**
* Login ServiceImpl
*
*/
@Service
public class LGNServiceImpl implements LGNService {
@Autowired
private KakaoApiService kakaoApi;
/**
* [카카오] 로그인
*/
@Override
public LGN1001ResVO getLGN1001(String code) {
LGN1001ResVO result = new LGN1001ResVO();
try {
/* [카카오] 토큰 발급 */
KakaoOAuthTokenVO token = kakaoApi.getOAuthToken(code);
/* [카카오] 사용자 정보 조회 */
KakaoUserInfoVO userInfo = kakaoApi.getUserInfo(token.getAccess_token());
/* 사용자 정보 저장 */
/* 응답 값 설정 */
ProfileVO profileVO = new ProfileVO();
profileVO.setNickname(userInfo.getKakaoAccount().getProfile().getNickname());
profileVO.setIsDefaultNickname(userInfo.getKakaoAccount().getProfile().getIsDefaultNickname());
KakaoAccountVO kakaoAccountVO = new KakaoAccountVO();
kakaoAccountVO.setProfileNicknameNeedsAgreement(userInfo.getKakaoAccount().isProfileNicknameNeedsAgreement());
kakaoAccountVO.setProfile(profileVO);
propertiesVO propertiesVO = new propertiesVO();
propertiesVO.setNickname(userInfo.getProperties().getNickname());
LGN1001VO vo = new LGN1001VO();
vo.setId(userInfo.getId());
vo.setConnectedAt(userInfo.getConnectedAt());
vo.setKakaoAccount(kakaoAccountVO);
vo.setProperties(propertiesVO);
result.setResult(vo);
} catch (Exception e) {
}
return result;
}
}
▷ KakaoOAuthTokenVO.java
/**
* [카카오] 토큰 발급 응답 VO
*/
@Getter
@Setter
@ToString
@Schema(description = "[카카오] 토큰 발급 응답 VO")
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoOAuthTokenVO {
@JsonProperty("access_token")
@Schema(description = "갱신된 사용자 액세스 토큰 값")
public String access_token;
@JsonProperty("refresh_token")
@Schema(description = "갱신된 사용자 리프레시 토큰 값, 기존 리프레시 토큰의 유효기간이 1개월 미만인 경우에만 갱신")
public String refresh_token;
}
▷ KakaoUserInfoVO.java
/**
* [카카오] 사용자 정보 조회 응답 VO
*/
@Getter
@Setter
@ToString
@Schema(description = "[카카오] 사용자 정보 조회 응답 VO")
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoUserInfoVO {
@JsonProperty("id")
@Schema(description = "ID")
public long id;
@JsonProperty("connected_at")
@Schema(description = "서비스에 연결 완료된 시각")
public String connectedAt;
@JsonProperty("kakao_account")
@Schema(description = "카카오계정 정보")
public KakaoAccountVO kakaoAccount;
@JsonProperty("properties")
@Schema(description = "사용자 프로퍼티")
public propertiesVO properties;
@Getter
@Setter
@ToString
@Schema(description = "카카오계정 정보 VO")
@JsonIgnoreProperties(ignoreUnknown = true)
public static class KakaoAccountVO {
@JsonProperty("profile_nickname_needs_agreement")
@Schema(description = "사용자 동의 시 닉네임 제공 가능")
public boolean profileNicknameNeedsAgreement;
@JsonProperty("profile")
@Schema(description = "프로필 정보")
public ProfileVO profile;
}
@Getter
@Setter
@ToString
@Schema(description = "프로필 정보 VO")
@JsonIgnoreProperties(ignoreUnknown = true)
public static class ProfileVO {
@JsonProperty("nickname")
@Schema(description = "닉네임")
public String nickname;
@JsonProperty("is_default_nickname")
@Schema(description = "닉네임이 기본 닉네임인지 여부")
public Boolean isDefaultNickname;
}
@Getter
@Setter
@ToString
@Schema(description = "사용자 프로퍼티 VO")
@JsonIgnoreProperties(ignoreUnknown = true)
public static class propertiesVO {
@JsonProperty("nickname")
@Schema(description = "닉네임")
public String nickname;
}
}
▷ KakaoApiService.java
/**
* 카카오 API Service
*
* https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
*/
public interface KakaoApiService {
/** [카카오] 토큰 발급 **/
public KakaoOAuthTokenVO getOAuthToken(String code);
/** [카카오] 사용자 정보 조회 **/
public KakaoUserInfoVO getUserInfo(String accessToken);
}
▷ KakaoApiServiceImpl.java
/**
* 카카오 API ServiceImpl
*
*/
@Slf4j
@Service
public class KakaoApiServiceImpl implements KakaoApiService {
@Value("${kakao.client.id}")
private String KAKAO_CLIENT_ID;
@Value("${kakao.redirect.uri}")
private String KAKAO_REDIRECT_URI;
/**
* [카카오] 토큰 발급
*/
@Override
public KakaoOAuthTokenVO getOAuthToken(String code) {
KakaoOAuthTokenVO result = new KakaoOAuthTokenVO();
try {
log.info("[카카오] 토큰 발급 시작");
if (code == null) {
return result;
}
/* 요청 */
final String uri = "https://kauth.kakao.com/oauth/token";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // MultiValueMap
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "authorization_code");
body.add("client_id", KAKAO_CLIENT_ID);
body.add("redirect_uri", KAKAO_REDIRECT_URI);
body.add("code", code);
/* 응답 */
ResponseEntity<String> res = new RestTemplate().postForEntity(uri, new HttpEntity<>(body, headers), String.class);
result = new ObjectMapper().readValue(res.getBody(), KakaoOAuthTokenVO.class);
log.info("[카카오] 토큰 발급 종료");
} catch (Exception e) {
}
return result;
}
/**
* [카카오] 사용자 정보 조회
*/
@Override
public KakaoUserInfoVO getUserInfo(String accessToken) {
KakaoUserInfoVO result = new KakaoUserInfoVO();
try {
log.info("[카카오] 사용자 정보 조회 시작");
if (accessToken == null) {
return result;
}
/* 요청 */
final String uri = "https://kapi.kakao.com/v2/user/me";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // MultiValueMap
headers.add("Authorization", "Bearer " + accessToken);
/* 응답 */
ResponseEntity<String> res = new RestTemplate().postForEntity(uri, new HttpEntity<>(headers), String.class);
result = new ObjectMapper().readValue(res.getBody(), KakaoUserInfoVO.class);
log.info("[카카오] 사용자 정보 조회 종료");
} catch (Exception e) {
}
return result;
}
}
▷ 결과
▷ 관련 글
SNS 간편로그인 - 카카오 API 사용 등록 방법
카카오 Open API를 사용하기 위한 카카오 developers 앱 등록*자세한 설명 생략 ▷ 카카오 API 사용 등록 방법 ① 내 애플리케이션 생성 Kakao Developers카카오 API를 활용하여 다양한 어플리케이션을
coding-today.tistory.com
RestTemplate Post 요청 보내기
RestTemplate로 Post 요청을 보내고, 응답 코드를 확인하는 메서드*Header 값(Authorization)만 추가하고, Body는 빈 값으로 요청*자세한 설명 생략 /** * POST 요청 */public static boolean sendPost(String jwt) { boolean r
coding-today.tistory.com
Objcet to String
Object를 String으로 변환하는 간단한 방법 /** * * Object to String * * @param Object * @return String */ public static String getObjStr(Object obj) { String str = ""; try { str = new ObjectMapper().writeValueAsString(obj); } catch (Exception e)
coding-today.tistory.com
JSON Unrecognized field 해결방법(@JsonIgnoreProperties)
JSON 데이터를 구성하는 요소가 가변적일 때 무시하는 방법 *소스는 변하지 않았지만 연동 했던 API 응답 값이 변했다고 가정 ▷ ERROR - JSON 데이터를 매핑하지 못해 에러 발생 com.fasterxml.jackson.databi
coding-today.tistory.com
SNS 간편로그인 - 구글 API 사용 등록 방법
구글 Open API를 사용하기 위한 구글 developers 사용 설정*자세한 설명 생략 ▷ 구글 API 사용 등록 방법 ⓛ 프로젝트 생성 Google 클라우드 플랫폼로그인 Google 클라우드 플랫폼으로 이동accounts.goog
coding-today.tistory.com
SNS 간편로그인 - 네이버 API 사용 등록 방법
네이버 Open API를 사용하기 위한 네이버 developers 앱 등록*자세한 설명 생략 ▷ 네이버 API 사용 등록 방법 ① 내 애플리케이션 생성 애플리케이션 - NAVER Developers developers.naver.com ▷ 관련 글 S
coding-today.tistory.com
▷ 참고
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
[Spring] 카카오 로그인 API 사용 방법
Kakao Developers이미지 설명에 각 이미지 내용에 대한 위치(경로) 적어뒀으니 참고해 주세요. 1. KakaoDevelopers 접속https://developers.kakao.com/ Kakao Developers카카오 API를 활용하여 다양한 어플리케이션을
innovation123.tistory.com
'▶ Back-End > Java' 카테고리의 다른 글
SNS 간편로그인 - 네이버 로그인 API 호출 및 사용자 정보 받기 (0) | 2024.07.16 |
---|---|
SNS 간편로그인 - 구글 로그인 API 호출 및 사용자 정보 받기 (0) | 2024.07.15 |
RestTemplate Post 요청 보내기 (0) | 2024.07.04 |
LocalDate Jackson Data Format 변경 (0) | 2023.11.23 |
@RestControllerAdvice - 전역 예외 처리 (0) | 2023.11.17 |
댓글