뚜벅이 한걸음

카카오 로그인 API - REST API (2) 본문

API

카카오 로그인 API - REST API (2)

뚜벅뚜벅뚜벅이 2022. 7. 10. 15:27
반응형


 

카카오 디벨로퍼에서 기본적인 설정을 했으면

이제 개발을 해보자!

현재 STS3에서 JSP로 구현을 하고 있다.


인가 코드 받기

먼저 home.jsp에 로그인 버튼을 만든다.

<button type="button" onclick="location.href=''>카카오 로그인</button>

그리고 문서를 보러 가자

REST API를 만지면서 느낀 건

문서가 필수적이라는 것이다.

문서를 보면 다음과 같이 설명이 나와있다.

인가 코드를 요청할 때 아래와 같이 작성하면 카카오에 요청이 되는 것이다.

보자마자 든 생각은 그래서 저게 뭔데,,,

host는 우리가 localhost를 사용하는 것처럼 도메인에 해당하고, 도메인 뒤에 GET에 쓰여있는 경로를 쓰면 된다.

출처 : https://data-jj.tistory.com/53

위의 그림을 보면 이해가 더 잘 된다.

다음으로 문서를 조금 더 내리면 이렇게 sample이 있다.

sample이 최고다,,ㅎㅎ

RedirectURI는 앱 설정할 때 만든 주소를 입력하면 된다.

나의 경우는 http://localhost:8090/controller/common/kakaoLogin 이다.

REST_API_KEY는 앱 키다.

앱 키는 애플리케이션에 들어가서 앱 키 부분에서 확인할 수 있다.

값을 넣어주면 다음과 같이 버튼을 만들 수 있다.

<button type="button" onclick="location.href='https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}'">카카오 로그인</button>

버튼을 눌러보면 Redirect 되는 것을 확인할 수 있다.

주소창은 다음과 같이 나오게 된다.

code=~~이렇게 된 부분이 있는데 이게 인가 코드이다.

인가 코드는 그때그때 다르게 나온다.

이제 이 코드를 카카오 쪽으로 다시 보내서 토큰을 발급받을 수 있다.

처음에 이 코드를 어디서 처리해야 하나에 대해서 고민이 많았었는데

스프링에 대한 공부 부족이었다.

열심히 공부해 봅시다.


인가 코드로 토큰 요청하기

코드는 요청할 때마다 변하는 값이다.

여기서부터는 뒷단에서 처리할 것이다.

따라서 요청을 처리할 컨트롤러로 간다.

우리 팀은 회원가입과 로그인 관련 처리는 따로 분리해서 CommonController에서 처리하기로 하였다.

CommonController.java

@RequestMapping("/common") 
@Controller public class CommonController{

@RequestMapping(value = "/kakaologin") 
public String login(@RequestParam("code") String code, HttpSession session) throws IOException {
System.out.println(code);
return "common/kakao";
}
}

 

일단 controller에 로그인 메서드를 만들어두고 매개변수로 인가 코드를 받아온다.

@RequestParam 을 사용한다.

그리고 service 만들기!

service에서 코드를 카카오로 넘겨서 토큰을 받아오는 작업을 수행할 것이다.

(나는 Redirect를 kakao.jsp로 할 것이기 때문에 return은 common 폴더의 kakao.jsp로 해주었다.)

그전에 pom.xml에 Gson 라이브러리 추가하기!

응답 데이터가 json 형식이기 때문에 파싱 해주기 위해 쓸 것이다.

(google에서 만든 거라서 Gson 인가 보다)

<dependency> 
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> 
<version>2.8.2</version> 
</dependency>

KakaoService.java

@Service public class KakaoAPI { //컨트롤러에서 사용할 메서드 만들기
//화면에서 파라미터로 넘겨준 code값을 받아오고 POST로 요청을 보내서 토큰을 발급받기

public String getAccessToken (String authorize_code) {

System.out.println("----------------------------토큰발급---------------------------");
String access_Token = "";
String refresh_Token = "";
String id_token =""; 

//토큰발급 요청을 보낼 주소
String reqURL = "https://kauth.kakao.com/oauth/token";

try { 

//URL객체 생성 
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// POST 요청을 위해 기본값이 false인 setDoOutput을 true로
//.setDoOutput(true): URLConnection이 서버에 데이터를 보내는데 사용할 수 있는 지의 여부를 설정하는 것 
conn.setRequestMethod("POST");
conn.setDoOutput(true);

// POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송 
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code");
sb.append("&client_id=본인의 REST_API_KEY");
sb.append("&redirect_uri=본인이 설정한 리다이렉트 경로"); 
sb.append("&code=" + authorize_code); bw.write(sb.toString()); 
bw.flush(); 

//응답확인 
int responseCode = conn.getResponseCode();
System.out.println("responseCode : " + responseCode);
//요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기 

BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = ""; String result = "";
while ((line = br.readLine()) != null) {
result += line;
} 

System.out.println("response body : " + result);

// Gson 라이브러리에 포함된 클래스로 JSON파싱 객체 생성 
JsonParser parser = new JsonParser(); 
JsonElement element = parser.parse(result);

access_Token = element.getAsJsonObject().get("access_token").getAsString(); 
refresh_Token = element.getAsJsonObject().get("refresh_token").getAsString();
id_token = element.getAsJsonObject().get("id_token").getAsString(); 

System.out.println("access_token : " + access_Token);
System.out.println("refresh_token : " + refresh_Token); 
System.out.println("id_token: "+ id_token); 

br.close(); 
bw.close();

} catch (IOException e) {

// TODO Auto-generated catch block e.printStackTrace();
} 
return access_Token; 
}

완성된 메서드는 위와 같다.

메서드를 설명하기 전에 과정을 먼저 보면 다음과 같다.

1. 카카오에 경로를 통해 인가 코드를 보내서 토큰을 요청하면

2. 카카오는 코드를 확인하고 토큰을 Json 객체로 돌려준다.

말만 들으면 너무 쉽다 ㅎㅎ

카카오 문서를 보면 Request와 Response 가 있는데

Request는 우리가 요청을 보낼 때 어떻게 해야 하는지를 써 둔 것이고

Response는 요청의 결과로 결과를 어떻게 돌려주는지를 써 둔 것이다.

먼저 Request를 보면 URL이라고 되어있고 코드를 요청할 때처럼 나와있다

그다음의 Parameter는 이렇게 요청을 보낼 때 필요한 값을 적어 둔 것이다.

이 값들을 같이 보내야 토큰이 나온다.

sample이 있으니까 sample을 보자 ㅎ

Request 부분을 보면 다음과 같이 작성돼있다.


curl-v -X POST https://kauth.kakao.com/oauth/token

-H : "Content_Type: application/x-www-form-urlencoded"

-d : "grant_type=authorization_code"

-d : "client_id =본인 앱 키"

-d : redirect_uri=http://localhost:8090/controller/common/kakaoLogin"

code=" + authorize_code


H는 헤더 부분에 어떤 것을 같이 요청해야 하는 지니고

d는 parameter로 어떤 데이터를 같이 넘겨야 하는지이다.

이 파라미터들은 BufferedWriter와 StringBuilder를 사용해서 작성한다.

여기까지만 코드를 작성해 보면 이렇게 된다.

(공부하려고 남겨둡니다 ㅎㅎ)

1. 먼저 카카오에 어떤 경로로 요청을 보낼지 변수에 담기

String reqURL = "https://kauth.kakao.com/oauth/token";

2.URL 객체 생성

카카오와 소통하기 위해서는 HTTP 통신을 이용해야 하는데

이를 위해서는 HttpURLConnection을 이용해야 한다.

 

HttpURLConnection은 추상 클래스이기 때문에

바로 객체를 생성할 수 없어서 URL 객체를 만들고

그다음 openConnection() 메서드를 호출하면 인스턴스를 받을 수 있다.

openConnection() 메서드를 실행하면 바로 연결이 되는 것은 아니고,

입력 스트림이나 출력 스트림을 가지고 오면 암시적으로 이루어지는 것이라고 한다.

I/O 오류가 발생하면 IOException이 발생하므로 try catch 구문으로 감싸주면 된다.

//URL객체 생성 
try {

URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

3. HTTP 통신 설정해 주기

아까 문서에서 POST로 요청하라고 했으므로 요청 메서드를 POST로 만들어준다.

그리고 이렇게 요청을 하려면 서버에 데이터를 보낼 수 있도록 해야 한다.

따라서 요청을 위해 기본값이 false인 setDoOutput을 true로 설정해 준다.

//.setDoOutput(true): URLConnection이 서버에 데이터를 보내는데 사용할 수 있는 지의 여부를 설정하는 것

conn.setRequestMethod("POST");
conn.setDoOutput(true);

4. 파라미터 넘기기

아까 문서에서 요청을 할 때는 특정 파라미터를 함께 넘기라고 했다.

따라서 POST 요청에 필수로 요구하는 파라미터를 스트림을 통해 전송

내보는 것이므로 outputStream을 이용한다.

(스트림이 연결되면 이제 http 통신이 연결되는 것)

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code"); 
sb.append("&client_id=본인의 REST_API_KEY"); 
sb.append("&redirect_uri=본인이 설정한 리다이렉트 경로");
sb.append("&code=" + authorize_code); 
bw.write(sb.toString());
bw.flush();

5. 제대로 연결이 되었는지 확인하기

200이 뜨면 정상적으로 연결이 된 것이다.

 

int responseCode = conn.getResponseCode(); 
System.out.println("responseCode : " + responseCode);

여기까지가 요청하는 과정이다.


여기서부터는 이제 요청의 결과로 카카오로부터 토큰을 받아올 것이다.

다시 한번 문서를 살펴보자

문서를 조금 더 내리면 이제 응답은 어떤 식으로 해주는지가 나와있다.

우리가 필요한 것은 access_token과 refresh_token이고

OpenID Connect를 이용한다면 id_token까지 받아오면 된다.

(id_token을 이용해서 사용자 정보를 보려고 했는데 받아오기만 하고 보는 건 그냥 토큰으로 했다.

혹시 나중에라도 하시는 분 있으면 저도 알려주세요,,,)

조금 더 문서를 내리면 sample이 있다.

어떤 식으로 응답 데이터가 들어오는지를 알려준다.

HTTP 통신이 정상으로 200이면 이 데이터들을 JSON 객체로 돌려준다.

만약 id_token까지 사용했다면 아래와 같이 값을 받을 수 있다.

나는 아래와 같이 받아왔다.

여기까지 다시 코드를 보면 요청 후 응답 200을 받고 나서부터이다.

  1. 요청을 통해 얻은 JSON 타입의 Response 메시지 읽어오기

아까 요청을 보낼 때는 BufferedWriter를 이용했다.

이번에는 BufferedReader를 사용해서 읽어오자!

요청 정보는 conn.getInputStream()으로 '바이트' 형태로 응답을 가지고 올 수 있다.

(conn에는 아까 만든 HTTP 인스턴스가 있다.)

바이트 형태로는 우리가 사용할 수 없으니

'문자 데이터'로 만들기 위해 InputStreamReader로 매핑 해준다.

그리고 '문자 데이터'를 '문자열'로서 읽어오기 위해 BufferedReader로 한번 더 매핑한다.

BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";

2. 응답 데이터를 반목문을 돌려서 데이터들을 line에 담아서 result로 만들기

값을 찍어보면 응답 데이터들이 잘 들어와 있는 것을 확인할 수 있다.

 

while ((line = br.readLine()) != null) {
result += line;
} 
System.out.println("response body : " + result);

3. Gson 라이브러리에 포함된 클래스로 JSON 파싱 객체 생성

아까 pom.xml에 라이브러리를 넣었었다.

이걸 이용해서 응답 데이터를 파싱 해줄 것이다.

String 형태의 Json을 JSONObject로 만드는 것이다.

① result를 parser의 parse() 메서드에 넣어 elment라는 이름의 변수에 담기

② 그럼 이 elment에 우리가 받은 응답 데이터가 있으므로

.getAsJsonObject()라는 메서드로 JsonObject 형식으로 파싱 된 데이터 꺼내기

③ 그중에서 어떤 값을 꺼낼 것인지 get()으로 정하기

④ 문서에서 얘네는 String 타입이라고 했으므로 String 형태로 가져오도록 하기

마지막으로 값이 잘 들어왔는지 확인하기 위해 찍어보고

return으로 access_token을 해주면 성공!

JsonParser parser = new JsonParser(); 
JsonElement element = parser.parse(result);

access_Token = element.getAsJsonObject().get("access_token").getAsString();
refresh_Token = element.getAsJsonObject().get("refresh_token").getAsString(); 
id_token = element.getAsJsonObject().get("id_token").getAsString(); 

System.out.println("access_token : " + access_Token);
System.out.println("refresh_token : " + refresh_Token); 
System.out.println("id_token: "+ id_token);

br.close();
bw.close();

} catch (IOException e) { 
// TODO Auto-generated catch block e.printStackTrace(); 
} 
return access_Token; 
}

여기까지가 토큰 발급이다.

합쳐서 보면 이렇게 된다.

(처음에 완성 메서드라고 한 것이랑 같은 놈입니다)

kakaoService

@Service public class KakaoAPI { 

//컨트롤러에서 사용할 메서드 만들기
//화면에서 파라미터로 넘겨준 code값을 받아오고 POST로 요청을 보내서 토큰을 발급받기
public String getAccessToken (String authorize_code) {
System.out.println("----------------------------토큰발급---------------------------");
String access_Token = ""; 
String refresh_Token = "";
String id_token =""; 

//토큰발급 요청을 보낼 주소

String reqURL = "https://kauth.kakao.com/oauth/token"; 
try {

//URL객체 생성 
URL url = new URL(reqURL); 
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// POST 요청을 위해 기본값이 false인 setDoOutput을 true로
//.setDoOutput(true): URLConnection이 서버에 데이터를 보내는데 사용할 수 있는 지의 여부를 설정하는 것 conn.setRequestMethod("POST"); conn.setDoOutput(true); // POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송 
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder(); 

sb.append("grant_type=authorization_code"); 
sb.append("&client_id=본인의 REST_API_KEY");
sb.append("&redirect_uri=본인이 설정한 리다이렉트 경로"); 
sb.append("&code=" + authorize_code); 
bw.write(sb.toString());
bw.flush();

//응답확인 200이면 정상 
int responseCode = conn.getResponseCode(); 
System.out.println("responseCode : " + responseCode); 

//요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기 
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
String line = "";
String result = "";

while ((line = br.readLine()) != null) { 
result += line; 
}

System.out.println("response body : " + result);

// Gson 라이브러리에 포함된 클래스로 JSON파싱 객체 생성 
JsonParser parser = new JsonParser(); 
JsonElement element = parser.parse(result);

access_Token = element.getAsJsonObject().get("access_token").getAsString();
refresh_Token = element.getAsJsonObject().get("refresh_token").getAsString(); 
id_token = element.getAsJsonObject().get("id_token").getAsString(); 

System.out.println("access_token : " + access_Token);
System.out.println("refresh_token : " + refresh_Token);
System.out.println("id_token: "+ id_token);

br.close(); 
bw.close();

} catch (IOException e) {
// TODO Auto-generated catch block e.printStackTrace();
}
return access_Token;
}


토큰 발급메서드를 controller에 넣으면 끝!

CommonController.java

@RequestMapping("/common")
@Controller public class CommonController{ 

@Autowired
KakaoAPI kakaoService;

@RequestMapping(value = "/kakaologin")
public String login(@RequestParam("code") String code, HttpSession session) throws IOException { 
System.out.println(code);

//토큰 발급 받기
String access_Token = kakaoService.getAccessToken(code); 
return "common/kakao"; 
}

}

kakaoService import 해주고 메서드를 호출하면 된다.

인자 값으로는 이전에 화면에서 가져온 인가 코드 넣어주기!

다음 게시물은 이 토큰을 이용해서사용자 정보를 보고 가지고 오는 걸 작성해보겟습니다

혹시 제가 잘못이해하고 있는 부분이 있다면 알려주세요!

참고한 사이트

//URL관련

https://blueyikim.tistory.com/2199

//카카오 로그인 관련

https://data-jj.tistory.com/53

반응형

'API' 카테고리의 다른 글

다음 주소 API  (0) 2022.07.11
카카오 로그인 API - REST API(3)  (0) 2022.07.10
카카오 로그인 API - REST API (1)  (0) 2022.07.10