JAVA 애플리케이션과 URL 을 연결해주는 클래스
URLConnection과 HttpURLConnection
URLConnection/HttpURLConnection 이란?
URLConnection은 Java 애플리케이션과 URL을 연결해주는 수퍼 클래스로, 일반 URL에 대한 API를 제공하고 하위 클래스인 HttpURLConnection은 Http에 대한 기능을 추가 지원
두 클래스는 모두 추상 클래스로 인스턴스를 직접 만들 수 없는 대신 URL 자체에서 연결을 열어서 URLConnection의 인스턴스를 얻음
URLConnection 클래스는
1) 사용자 인증이나 보안이 설정되어 있지 않은 웹서버에 접속해 파일 등을 다운로드 할 때 많이 사용하며
2) 리소스에 연결하기 전에 구성되어야 하고
3) 인스턴스 재사용이 불가하여, 각 리소스에 대한 커넥션마다 다른 인스턴스를 사용해야 한다.
* 메서드는 아래 참고
https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html
URLConnection (Java Platform SE 7 )
Returns a permission object representing the permission necessary to make the connection represented by this object. This method returns null if no permission is required to make the connection. By default, this method returns java.security.AllPermission.
docs.oracle.com
HttpURLConnection 클래스는
1) URLConnection을 구현한 클래스이며,
2) 데이터 타입이나 길이의 제한이 없어 주로 미리 길이를 알지 못하는 스트리밍 데이터를 주고 받을 때 사용하며,
3) Http URL 처리 시 도움이 되는 메서드를 가지고 있다.
4) 또한, 요청방식을 확인/설정/redirect 여부 결정, 응답 코드와 메시지를 읽고 프록시 서버가 사용되었는지 여부에 대한 확인 메서드를 가지며,
5) URLConnection 클래스의 getPermission() 메서드를 오버라이드 한다.
6) 생성자가 protected로 선언되어 개발자가 직접 HttpURLConnection 객체를 생성할 수 없지만,
7) openConnection() 메서드가 리턴하는 URLConnection 객체는 HttpURLConnection의 인스턴스가 될 수 있어 캐스팅하여 사용하는데, 이와 같은 방식을 많이 사용한다.
* 메서드는 아래 참고
https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html
HttpURLConnection (Java Platform SE 8 )
Returns the error stream if the connection failed but the server sent useful data nonetheless. The typical example is when an HTTP server responds with a 404, which will cause a FileNotFoundException to be thrown in connect, but the server sent an HTML hel
docs.oracle.com
카카오 로그인을 위해 토큰을 받아 회원의 정보를 가져오는 과정 중 토큰을 받아오는 과정만을 이용해 예시로 설명해보고자 한다.
Spring에서 카카오 로그인 하는 방법임을 참고하기를 바라며, REST API 를 이용하여 구현하였다.
* 전체 코드를 참고하고 싶다면 아래 블로깅을 참고하시를 바라며,
(링크 추후 삽입 예정)
구체적인 방법은 아래를 참고하면 된다.
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#unlink
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
우선 토큰을 받아오기 위해서는 인가코드를 받아와야 하는데,
이는 Client_key와 Redirect_URL 만으로도 쉽게 얻을 수 있으며, URL은 아래와 같다.
https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}
인가코드를 받아왔다면 이 인가코드를 이용해 토큰을 요청하면 되는데,
토큰을 요청하기 위해서 토큰을 요청하는 URL에 접속해 필요한 정보를 주고 내가 원하는 토큰에 대한 정보를 받아 올 것이다.
코드를 먼저 보고 설명할 예정이니, 코드와 설명을 함께 보며 이해하는 것을 권장한다.
[KakaoLoginController.java]
@GetMapping("/kakaoLogin")
public String kakaoLogin(@RequestParam("code") String code, Model model){
try{
// (1)
UserInfo userInfo = kakaoLoginService.kakaoLogin(code);
model.addAttribute("userInfo", userInfo);
return "userInfo";
}catch (Exception e){
e.printStackTrace();
return e.getMessage();
}
}
(1) 우선 위에서 받아온 인가 코드를 이용해 Service에 넣어주어 토큰 및 사용자 정보를 가져온다.
* 설명에서 사용자 정보를 가져오는 코드는 생략할 예정이며, 이는 토큰을 가져오는 방법과 동일하기 때문에 직접 해보는 것을 추천한다.
[KakaoLoginService.java]
@Service
public class KakaoLoginService {
public UserInfo kakaoLogin(String code) throws Exception{
String token = getAccessToken(code);
UserInfo userInfo = getUserInfo(token);
return userInfo;
}
// 토큰 요청 로직
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");
// (3)
conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset-utf-8");
conn.setDoOutput(true); // 출력스트림 활성화
// (4)
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=/* 내가 지정한 리다이렉트 URL */");
param.append("&code=").append(code);
bw.write(param.toString());
bw.flush();
// response
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을 통해 접속하여 openConnection() 메서드를 이용해 HttpURLConnection의 인스턴스 생성
- 위의 HttpURLConnection 설명 중 6,7번 설명을 보면, HttpURLConnection 객체를 생성할 수 없지만, openConnection() 메서드가 리턴하는 URLConnection 객체는 HttpURLConnection의 인스턴스가 될 수 있어 캐스팅하여 사용한다고 하였는데, 이를 사용한 것이다.
- 토큰을 얻기 위해 https://kauth.kakao.com/oauth/token에 접속
(2) 접속을 할 때 setRequestMethod() 메서드를 통해 요청 메서드를 설정
- POST 요청을 보내 응답을 받아와야 함
(3) setRequestProperty() 메서드를 이용해 헤더 값 지정
- 카카오 로그인 시 x-www-form-urlencoded 요청으로 보내야 하기 때문에 Content-type 지정
- 요청 시에 헤더값 뿐만 아니라 파미미터(바디값)이 필요하기 때문에 setRequestProperty()로만 요청할 수 없기 때문에, setDoOutput()을 통해 출력 스트림을 활성화
(4) 파라미터 값을 StringBuilder를 이용해 만든 후 BufferWriter를 이용해 해당 값을 넣어줌
- getOutputStream() 메서드를 통해 접속한 다음 BufferWriter를 통해 요청 데이터를 넣어주면 됨
- 요청 형식이 x-www-form-urlencoded 이기 때문에 데이터 형식은 이름2=값1&이름2=값2&이름3=값3&이름4=값4의 형식을 지녀야 한다. (만약 JSON 형식이라면 그에 맞는 형식으로서 문자열을 생성해주면 된다)
BufferReader를 통해 요청 데이터에 대한 응답을 받아온 다음 받아온 데이터에서 내가 사용할 데이터만 가져오면 된다.
데이터의 응답 형태는 JSON이기 때문에 이를 가공해 사용하면 된다.
(5) 토큰 중 정보 요청 시 필요한 토큰은 'access_token'이기 때문에 이를 key로 가진 데이터를 가져와 리턴
- JSON 데이터에서 정보를 가져오기 위해 파싱하여 데이터를 가져온 다음, get(key) 메서드를 이용해 정보를 가져온다.
URL에 접속하고 헤더값 및 바디값을 넣고 필요한 정보를 가져오는 등의 작업 시 많은 메서드를 사용하는데,
메서드는 다양한 역할의 메서드들이 존재하기 때문에 자신에게 필요한 메서드를 적절히 사용하면 된다.
메서드의 종류들은 위에 첨부해 놓은 문서들을 참고하기를 바란다!
'공부 자료 > 자바[JAVA]' 카테고리의 다른 글
[ JAVA ] ArrayList <> Array (0) | 2024.08.05 |
---|---|
[JAVA] 빠른 입출력을 위한 BufferedReader(StringTokenizer) & BufferedWriter (0) | 2023.11.08 |
[JAVA] URLEncoding이란? URL로 변환하기 위한 URLEncoder 사용 (0) | 2023.11.07 |
[JAVA] StringBuilder란? (0) | 2023.11.07 |
[JAVA] ArrayList 생성자 (0) | 2023.08.30 |