본문 바로가기
Language/☕️Java

JAVA로 카카오 메시지 API연동

by 발개발자 2022. 2. 25.
반응형

토이프로젝트를 진행하던 , 카카오 메시지 API연동이 필요하던 참이었다.

목적이 Spring scheduler 이용해 일정 시간마다 필요한 정보를 나에게 메시지를 뿌려주는 것이기 때문에 따로 화면단이 필요 없었다.

좀 편하게 하려고 누군가 java로 카카오 API 연동한 사례를 찾아보려고 했는데, 아무리 찾아봐도 백엔드단에서 카카오 메시지 API 연동을 Java 이용한 사례가 없기 때문에 직접 구현해서 공유해보려고 한다. ㅠㅠ 

언젠가 누군가에겐 1g의 도움이 되길 바라며 작성해볼까 한다,,

 

STEP1. Kakao Develpopers 가입 애플리케이션 추가

https://developers.kakao.com/ 해당 사이트에 가입한 후, 내 어플리케이션을 추가해준다.

 

 

STEP2. 내 애플리케이션 셋팅

코드를 작업하기에 앞서, 로그인 카카오 API에서 return해주는 인가코드 값을 받아줄 서버의 IP, PORT 입력해준다. 애플리케이션 > 제품 설정 > 카카오 로그인을 들어가면 등록해줄 있다. 본인의 경우 local에서 88 port 인가코드 값을 받을 것이다. 즉, http://localhost:88 을 controller로 작성하여 kakao API에서 Return 해주는 code값을 받을 예정이다.

 

 

카카오 메시지를 사용하기 위해 브라우저를 통해 카카오 로그인을 진행한 후 발급받은 인가코드를 통해 토큰을 받급받고 해당 토큰으로 메시지를 전송할 수 있기 때문에, 코드작성에 앞서 문서를 읽어보는 것을 권유한다.

 

이해하기 | Kakao Developers 문서

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

이해하기 | Kakao Developers 문서

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

 

 

STEP3. 프로젝트 생성

Spring initializr 통해 Spring Web 디펜던시를 추가해준 프로젝트를 생성한다.

 

 

Project Import 의존성을 추가해준다.

 

 > build.gradle

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation group: 'org.json', name: 'json', version: '20210307'

	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

KAKAO API에서 json형태로 응답해주는 값들을 java에서 손쉽게 파싱하게위해 json dependency를 추가해 준다.

 

 

STEP 4. Class 생성

 

먼저, HttpCall서비스를 담당해줄 클래스를 작성해준다. 본인은 RestTemplate 통해 HttpCallService 구현할 것이다.

RestTemplate를 쓰면 코드의 분량도 훨씬 적어지고 가독성이 좋기 때문에 선택했다. 

 

> HttpCallService

public class HttpCallService {
	protected static final String APP_TYPE_URL_ENCODED = "application/x-www-form-urlencoded;charset=UTF-8";
	protected static final String APP_TYPE_JSON = "application/json;charset=UTF-8";

	/**
	* Http 요청 클라이언트 객체 생성 method
	*
	* @ param Map<String,String> header HttpHeader 정보
	* @ param Object params HttpBody 정보
	* @ return HttpEntity 생성된 HttpClient객체 정보 반환
	* @ exception 예외사항
	*/
    public HttpEntity<?> httpClientEntity(HttpHeaders header, Object params) {
    	HttpHeaders requestHeaders = header;

        if (params == null || "".equals(params))
            return new HttpEntity<>(requestHeaders);
        else
            return new HttpEntity<>(params, requestHeaders);
    }

	/**
	* Http 요청 method
	*
	* @ param String url 요청 URL 정보
	* @ param HttpMethod method 요청 Method 정보
	* @ param  HttpEntity<?> entity 요청 EntityClient 객체 정보
	* @ return HttpEntity 생성된 HttpClient객체 정보 반환
	*/
    public ResponseEntity<String> httpRequest(String url, HttpMethod method, HttpEntity<?> entity){
		RestTemplate restTemplate = new RestTemplate();
    	return restTemplate.exchange(url, method, entity,String.class);
    }

    /**
	* Http 요청 method
	*
	* @ param URI url 요청 URL 정보
	* @ param HttpMethod method 요청 Method 정보
	* @ param  HttpEntity<?> entity 요청 EntityClient 객체 정보
	* @ return HttpEntity 생성된 HttpClient객체 정보 반환
	*/
    public ResponseEntity<String> httpRequest(URI url, HttpMethod method, HttpEntity<?> entity){
		RestTemplate restTemplate = new RestTemplate();
    	return restTemplate.exchange(url, method, entity,String.class);
    }
}

 

 

그 다음 해당 HttpCallService 통해 카카오 API에서 토큰을 발급받을 클래스를 작성해준다.

 

> AuthService

@Service
public class AuthService extends HttpCallService{
	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private static final String AUTH_URL = "https://kauth.kakao.com/oauth/token";

	public static String authToken;

	public boolean getKakaoAuthToken(String code)  {
		HttpHeaders header = new HttpHeaders();
		String accessToken = "";
		String refrashToken = "";
		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();

		header.set("Content-Type", APP_TYPE_URL_ENCODED);

		parameters.add("code", code);
		parameters.add("grant_type", "authorization_code");
		parameters.add("client_id", "your client id");
		parameters.add("redirect_url", "http://localhost:88");
		parameters.add("client_secret", "your client secret");

		HttpEntity<?> requestEntity = httpClientEntity(header, parameters);

		ResponseEntity<String> response = httpRequest(AUTH_URL, HttpMethod.POST, requestEntity);
		JSONObject jsonData = new JSONObject(response.getBody());
		accessToken = jsonData.get("access_token").toString();
		refrashToken = jsonData.get("refresh_token").toString();
		if(accessToken.isEmpty() || refrashToken.isEmpty()) {
			logger.debug("토큰발급에 실패했습니다.");
			return false;
		}else {
		    authToken = accessToken;
		    return true;
		}
	}

}

client_id는 Kakao Developers 내 애플리케이션 해당 사이트에서 내 애플리케이션을 클릭하고 들어가면

이런식으로 키값을 확인할 수 있다. 여기서 REST API키 값을 입력해주면 된다.

 

client_secret은 아래의 사진에 있는 메뉴에 들어가면 발급받을 수 있다. 필수 값이 아니기 때문에, 발급을 안받고 parameter에서 삭제해도 무사히 진행될 것이다.

 

 

 

다음 직접 카카오 메시지를 보낼 클래스를 작성해주자!

 

> DefaultMessageDto 

@Data
public class DefaultMessageDto {
	private String objType;
	private String text;
	private String webUrl;
	private String mobileUrl;
	private String btnTitle;
}

카카오 API에 Request할때 필수로 필요한 값들을 Dto로 셋팅해 놓는다.

 

> MessageService

@Service
public class MessageService extends HttpCallService{
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	private static final String MSG_SEND_SERVICE_URL = "https://kapi.kakao.com/v2/api/talk/memo/default/send";
	private static final String SEND_SUCCESS_MSG = "메시지 전송에 성공했습니다.";
	private static final String SEND_FAIL_MSG = "메시지 전송에 실패했습니다.";

	private static final String SUCCESS_CODE = "0"; //kakao api에서 return해주는 success code 값

	public boolean sendMessage(String accessToken, DefaultMessageDto msgDto) {
		JSONObject linkObj = new JSONObject();
		linkObj.put("web_url", msgDto.getWebUrl());
		linkObj.put("mobile_web_url", msgDto.getMobileUrl());

		JSONObject templateObj = new JSONObject();
		templateObj.put("object_type", msgDto.getObjType());
		templateObj.put("text", msgDto.getText());
		templateObj.put("link", linkObj);
		templateObj.put("button_title", msgDto.getBtnTitle());


		HttpHeaders header = new HttpHeaders();
		header.set("Content-Type", APP_TYPE_URL_ENCODED);
		header.set("Authorization", "Bearer " + accessToken);

		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
		parameters.add("template_object", templateObj.toString());

		HttpEntity<?> messageRequestEntity = httpClientEntity(header, parameters);

		String resultCode = "";
		ResponseEntity<String> response = httpRequest(MSG_SEND_SERVICE_URL, HttpMethod.POST, messageRequestEntity);
		JSONObject jsonData = new JSONObject(response.getBody());
		resultCode = jsonData.get("result_code").toString();

		return successCheck(resultCode);
	}

	public boolean successCheck(String resultCode) {
		if(resultCode.equals(SUCCESS_CODE)) {
			logger.info(SEND_SUCCESS_MSG);
			return true;
		}else {
			logger.debug(SEND_FAIL_MSG);
			return false;
		}

	}
}

HttpCallService를 상속받아 실제 Message 전송을 담당할 클래스이다. KAKAO 메시지 API에 연동하기 위해 발급받은 token값이 필요하다. token 값은 AuthService에서 static 값으로 셋팅해준다. 

 

> CustomMessageService

@Service
public class CustomMessageService {

	@Autowired
	MessageService messageService;

	public boolean sendMyMessage() {
		DefaultMessageDto myMsg = new DefaultMessageDto();
		myMsg.setBtnTitle("자세히보기");
		myMsg.setMobileUrl("");
		myMsg.setObjType("text");
		myMsg.setWebUrl("");
		myMsg.setText("메시지 테스트입니다.");

		String accessToken = AuthService.authToken;

		return messageService.sendMessage(accessToken, myMsg);
	}
}

실제로 보낼 메시지를 작성한 클래스이다.

 

 

> BaseController

@RestController
public class BaseController {

	@Autowired
	AuthService authService;

	@Autowired
	CustomMessageService customMessageService;

	@GetMapping("/")
	public String serviceStart(String code) {
		if(authService.getKakaoAuthToken(code)) {
			customMessageService.sendMyMessage();
			return "메시지 전송 성공";
		}else {
			return "토큰발급 실패";
		}
	}
}

최초 카카오 로그인시 카카오 API에서 http://localhost:88로 reutrn해주는 code값을 받는 컨트롤러다. code값을 받은 후 토큰을 발급받아 바로 메시지를 전송할 것이다.

 

즉, 순서를 정리하자면,

1) web을 통해 카카오 API 인가코드를 받기위한 접근 및 로그인

2) 카카오 API에서 Return해주는 인가코드값 BaseController에서 수신 및 AuthService로 전달

3) 해당 코드값을 통해 AuthService에서 토큰 발급 및 static 값으로 token 셋팅

4) customMessageService에서 dto 셋팅과 static값인 token값을 MessageService로 전달

5) MessageService에서 KAKAO API에 메시지 요청

6) 실제 카카오 메시지 전송

순으로 진행된다.

 

STEP5. 메시지 전송해보기.

여러차례 설명하듯, 카카오 API 이용하기 위해 로그인을 통해 인가 코드를 받고 인가코드를 통해 엑세스 토큰과 리프레시 토큰을 받을  있다. 자세한 내용은 아래 문서를 참고하면 될 것 같다.

 

REST API | Kakao Developers 문서

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

 

먼저 카카오 인가코드를 받고 엑세스 토큰을 받기위해 브라우저를 통해 해당 URL 에 접근해서 로그인을 해보자.

https://kauth.kakao.com/oauth/authorize?client_id=your_client_id&redirect_uri=http://localhost:88&response_type=code&scope=talk_message

 

참고로 client_id에 아까 확인한 client_id값을 입력해주면된다.

 

그러면 로그인 창으로 redirect 시킬 것이다.

 

로그인을 진행 하면 KAKAO에서 내가 RedirectUri로 설정한 http:/localhost:88 로 인가코드값을 던져준 후 호출하게 된다.

 

 

 

위의 코드와 똑같이 작성하면 정상적으로 메시지가 전송된 걸 확인할 수 있다.

 

정리

Java를 사용한 예시가 없었던 이유는 java로 HttpCall을 진행하기에 번거로우며, js로 이미 많은 예제가 있고 실제 공식 문서에서도 참고자료로 제공해주기 때문이다. 하지만 결국 거의 대부분의 API연동은 Http요청과 응답을 통해 진행된다. 따라서 Java에서도 RestTemplate을 이용하여 HttpRequest, Response를 처리할 수 있었으며 어렵지 않게 작업할 수 있었음을 보여준 것 같다.

 

Git source

asd9211/kakao_api_demo: java - kakao 메시지 api 데모 (github.com)

 

GitHub - asd9211/kakao_api_demo: java - kakao 메시지 api 데모

java - kakao 메시지 api 데모 . Contribute to asd9211/kakao_api_demo development by creating an account on GitHub.

github.com

 

물론 위의 예제 코드는 급하게 하는 방식만 보여주느라 조금 지저분 할 수 있어 아래 실제로 본인이 실제로 자동 알람 메시지 프로젝트를 작업하고 있는 git을 올려놓고 글을 마무리하고자 한다.

끗!

 

asd9211/kkotalk_alarm: 카카오톡 알람 프로젝트 (github.com)

 

GitHub - asd9211/kkotalk_alarm: 카카오톡 알람 프로젝트

카카오톡 알람 프로젝트. Contribute to asd9211/kkotalk_alarm development by creating an account on GitHub.

github.com

 

반응형

댓글