[SpringFramework] Kakao API를 이용한 회원가입 및 로그인
SpringFramework에서 Kakao API를 이용한
로그인 및 회원 정보 불러오기
웹사이트를 제작하다 보면 홈페이지 자체 회원가입도 존재하지만,
요즘에는 소셜을 이용한 로그인도 필수일 정도로 대부분의 사이트에서 구현되어 있는 기능이다.
오늘은 이 중 카카오 API를 이용한 로그인 및 회원 정보를 가져올 수 있는 방법에 대해 알아볼 예정이다.
* API안의 내용이 많겠지만, 예시의 편의를 위해 이름(닉네임)과 이메일만 가져올 예정이다.
다른 정보를 가져오기 위한 방법은 이름과 이메일을 가져오는 방식과 동일하기 때문에 개인적으로 실습해 보기를 바란다!
[준비하기]
먼저, API를 사용하기 이전 카카오 개발자센터에서 애플리케이션을 만들어야 해당 애플리케이션에 로그인 시도가 가능하다.
1. 카카오 개발자센터 검색 및 접속
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
2. 상단의 내 애플리케이션 선택 후 애플리케이션 추가하기를 선택
3. 입력 후 저장을 눌러 생성
생성된 애플리케이션을 눌러서 들어가면 사용을 위한 다양한 설정이 존재하는 화면들이 존재하는데
여기서 설정해야 할 것들이 존재한다.
4. 애플리케이션을 어떤 플랫폼에서 사용할지 선택 및 도메인 입력 후 저장
(웹사이트 등록에 사용할 예정)
5. 기본 도메인 저장 시 나오는 버튼을 통해 Redirect 도메인 설정
활성화 상태를 ON으로 설정한 뒤 Redirect URL을 자신이 사용할 도메인으로 설정하면 되는데,
이는 버튼을 클릭한 후 로그인 처리를 한 다음 돌아올 URL을 의미한다.
6. 받아올 개인정보의 상태를 변경
* 사용할 정보에 대해 사용 여부 설정을 진행하면 되며, 필수/선택 선택이 가능하다.
* 나는 이메일과 닉네임만 받아올 예정이며, 이메일의 경우 비즈니스 탭에서 개발 비즈 계정을 설정하면 열리게 된다.
여기까지 설정했다면, API를 사용하기 위한 준비과정이 끝이다.
이제는 코드를 작성하러 갈 예정이며 코드는 API 사이트에서 제공하는 문서를 참고하니,
만약 어려운 것이 있거나 더 필요한 것이 있다면 아래 문서를 참고하기를 바란다.
*REST API 로그인 문서
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
[코드 작성]
* 나는 로그인을 위한 기본 버튼만 화면에 나타낼 것이기 때문에 이 점 참고하길 바란다.
코드는 버튼 있는 화면(jsp)에서 인가 코드를 요청하고 >> Controller 작성 >>
Service에서 토큰 받고 사용자 정보를 요청 및 받아오는 순서로 구현할 예정이다.
1. 인가 코드 요청
- 카카오 로그인 버튼 클릭과 동시에 인가 코드 요청을 보내 인가 코드를 받아오면 된다.
- Client_ID에는 위에서 애플리케이션 등록 시 받은 REST API KEY를 사용하면 된다.
[login.jsp]
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
<!-- oauth/authorize URL로 client_id와 redirect_url을 이용해 코드 요청을 보낸다 -->
<a href="https://kauth.kakao.com/oauth/authorize?client_id=${Client_ID}&redirect_uri=http://localhost:8080/kakaoLogin&response_type=code">
<img src="./image/kakaoLogin.png"/>
</a>
<body>
</html>
인가코드를 잘 받아왔는지 확인하기 위해 Controller를 통해 살펴볼 예정이다.
* 아래 Controller는 인가 코드 확인을 위해 작성한 코드이기에 최종 Controller가 아님
[KakaoLoginController.java]
@Controller
public class KaKaoLoginController {
// (1)
@GetMapping("/login")
public String kakao(){
return "login";
}
// (2)
@GetMapping("/kakaoLogin")
@ResponseBody
public String kakaoLogin(@RequestParam("code") String code, Model model){
System.out.println(code);
return code;
}
}
(1) login.jsp에서 작성한 내용을 가지고 버튼 클릭 시 인가 코드 요청을 보낸다.
(2) 동의 후 게속하기 버튼을 클릭하면 요청 시 보낸 Redirect_URL이 http://localhost:8080/kakaoLogin 였기 때문에 해당 (2)의 컨트롤러 매핑이 코드를 받게 된다.
위와 같이 파라미터에 인가코드를 받아오고, 이 파라미터를 @RequestParam을 이용해 받아오면, 토큰을 요청할 준비가 완료된 것이다.
2. 토큰 요청하여 받기
인가코드를 받아왔다면 이제는 Service에서 인가코드를 이용해 토큰을 받아오는 로직을 작성하면 된다.
[KakaoService.java]
@Service
public class KakaoLoginService {
// 토큰 요청 로직
public String getAccessToken(String code) throws Exception{
// (1)
URL url = new URL("https://kauth.kakao.com/oauth/token");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// (2) 메서드 및 헤더값 지정
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset-utf-8");
conn.setDoOutput(true); // 출력스트림 활성화
// (3) 파라미터 생성
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder param = new StringBuilder();
param.append("&grant_type=authorization_code");
param.append("&client_id=/*REST_API_KEY*/");
param.append("&redirect_uri=http://localhost:8080/kakaoLogin");
param.append("&code=").append(code);
bw.write(param.toString());
bw.flush();
// (4) 응답 받아오기
BufferedReader br;
int resultCode = conn.getResponseCode();
System.out.println(resultCode);
if(resultCode>=200 && resultCode<+300){ // 정상인 경우
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
}else{ //에러
br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
StringBuilder responseBuilder = new StringBuilder();
String line;
while((line=br.readLine()) != null){
responseBuilder.append(line);
}
br.close();
conn.disconnect();
// (5) 가져온 응답에서 토큰값 가져오기
JSONParser parser = new JSONParser();
JSONObject tokens = (JSONObject) parser.parse(responseBuilder.toString());
String token = (String) tokens.get("access_token");
System.out.println(token);
return token;
}
}
전체적인 코드 설명을 우선 하자면, 받아온 인가 코드를 통해 토큰을 요청하고, 받아온 토큰을 이용해 사용자 정보를 요청하고 있다.
토큰의 요청 URL을 통해 헤더와 바디에 요청 시 필요한 정보를 넣어 요청한 다음
받아온 응답값에서 필요한 토큰 정보를 추출하고 있다. 더 자세한 설명은 아래와 같다.
(1) 토큰을 요청하기 위해 URL 설정
- 토큰을 받기 위한 URL을 통해 접속하여 openConnection() 메서드를 이용해 HttpURLConnection의 인스턴스 생성
- URLConnection에 대한 설명은 아래를 참고하길 바람!
https://kcode-recording.tistory.com/319
[JAVA] URL을 통해 서버와 통신하는 URLConnection/HttpURLConnection
JAVA 애플리케이션과 URL 을 연결해주는 클래스 URLConnection과 HttpURLConnection URLConnection/HttpURLConnection 이란? URLConnection은 Java 애플리케이션과 URL을 연결해주는 수퍼 클래스로, 일반 URL에 대한 API를 제
kcode-recording.tistory.com
(2) Kakao API를 이용한 토큰 요청을 위한 메서드 및 헤더값 설정
- 접속을 할 때 setRequestMethod() 메서드를 통해 요청 메서드를 설정
- POST 요청을 보내 응답을 받아와야 함
- setRequestProperty() 메서드를 이용해 헤더 값 지정
- 카카오 로그인 시 x-www-form-urlencoded 요청으로 보내야 하기 때문에 Content-type 지정
- 요청 시에 헤더값 뿐만 아니라 파미미터(바디값)이 필요하기 때문에 setRequestProperty()로만 요청할 수 없기 때문에, setDoOutput()을 통해 출력 스트림을 활성화
(3) 헤더값은 위의 (2) 처럼 setRequestProperty를 이용해서 넣어주면 되지만, 바디값을 넣어주기 위해서는 BufferWriter를 사용
파라미터 값을 StringBuilder를 이용해 만든 후 BufferWriter를 이용해 해당 값을 넣어줌
- getOutputStream() 메서드를 통해 접속한 다음 BufferWriter를 통해 요청 데이터를 넣어주면 됨
- 요청 형식이 x-www-form-urlencoded 이기 때문에 데이터 형식은 이름2=값1&이름2=값2&이름3=값3&이름4=값4의 형식을 지녀야 한다. (만약 JSON 형식이라면 그에 맞는 형식으로서 문자열을 생성해주면 된다)
(4) 요청에 대한 응답을 받아오기
BufferReader를 통해 요청 데이터에 대한 응답을 받아온 다음 받아온 데이터에서 내가 사용할 데이터만 가져오면 된다.
데이터의 응답 형태는 JSON이기 때문에 이를 가공해 사용하면 된다.
* 아래 블로깅에서 BufferWriter/BufferReader에 대해 이해하고 보면 더 빠르게 이해가 가능하다!
https://kcode-recording.tistory.com/320
[JAVA] 빠른 입출력을 위한 BufferedReader(StringTokenizer) & BufferedWriter
빠른 입력을 위한 BufferReader & 빠른 출력을 위한 BufferedWrier 우리는 지금까지 자바를 배우면서 System.out.println()을 통한 출력, Scaner를 통한 입력을 많이 이용하였는데, 이는 입력 키를 누르는 즉시
kcode-recording.tistory.com
[응답 예시]
(5) access_token 값 가져오기
토큰 중 정보 요청 시 필요한 토큰은 'access_token'이기 때문에 이를 key로 가진 데이터를 가져와 리턴
- JSON 데이터에서 정보를 가져오기 위해 파싱하여 데이터를 가져온 다음, get(key) 메서드를 이용해 정보를 가져온다.
3. 사용자 정보 가져오기
이제 토큰을 받아왔다면, 해당 토큰을 이용해 사용자 정보를 요청하면 된다.
[KakaoService.java]
public UserInfo getUserInfo(String token) throws Exception{
// (1) 사용자 정보를 담을 dto 생성
UserInfo userInfo = new UserInfo();
// (2) 정보 요청
URL url = new URL("https://kapi.kakao.com/v2/user/me");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization","Bearer " + token);
conn.setRequestProperty("Content-type", "application/json; charset-utf-8");
// (3) 응답 받기
BufferedReader br;
int resultCode = conn.getResponseCode();
System.out.println(resultCode);
if(resultCode>=200 && resultCode<+300){ // 정상인 경우
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
}else{ //에러
br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
StringBuilder responseBuilder = new StringBuilder();
String line;
while((line=br.readLine()) != null){
responseBuilder.append(line);
}
br.close();
conn.disconnect();
// (4) 받아온 응답 중 사용할 정보 받아오기
JSONParser parser = new JSONParser();
JSONObject info = (JSONObject) parser.parse(responseBuilder.toString());
JSONObject kakaoInfo = (JSONObject) info.get("kakao_account");
String email = (String)kakaoInfo.get("email");
String nickName = (String)((JSONObject)kakaoInfo.get("profile")).get("nickname");
userInfo.setEmail(email);
userInfo.setNickName(nickName);
return userInfo;
}
전체적인 코드를 설명하자면, 위에서 받아온 토큰을 이용해 사용자 정보를 요청하고
받아온 정보 중 사용할 정보를 파싱하여 저장할 예정이다.
(1) User 정보를 담을 dto를 생성해서 객체를 미리 생성해 둠
(2) 사용자 정보를 가져오기 위한 URL 요청
- 자세한 설명은 위의 토큰 받아올 때를 참고하면 된다.
- 사용자 정보 요청 시에는 헤더값만 설정해주면 된다.
(3) 응답 받아오기
(4) 받아온 응답 중 필요한 정보를 JSONParser를 이용해 파싱한 다음 추출
이렇게 하면 로그인 및 사용자 정보를 가져와 활용할 수 있다!
파싱에 대해서는 블로깅할 예정이니, 추후 작성 시 링크를 참고해 놓을 예정이다!