본문 바로가기
Web Programming

Spring boot, URI 쉽게 만들기 ( with UriComponentsBuilder )

by 맑은안개 2021. 5. 3.

출처: Pixabay

들어가며..

  스크래핑, 웹 인증등 타겟 URI 정보를 파라미터와 함께 보낼 때 많은 수의 파라미터로 인해 코드가 길어질 수있다.  본 블로그에서는 카카오 OpenAPI를 통해 인증토큰을 받아오는 과정의 예를 들어 URI 생성하는 방법을 다루어본다. 

  고전적인 방식(String, StringBuffer)을 사용해보고 SpringBoot web 패키지에서 제공하는 개선된 방식( UriComponentsBuilder)을 사용해 본다.  

  

개발환경

- Springboot 2.4.5

 

build.gradle

plugins {
	id 'org.springframework.boot' version '2.4.5'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

- spring-boot-starter-web 디펜던시 추가. ( UriComponentsBuilder 는 org.springframework.web 패키지에 존재 )

 

고전전인 방식(String, StringBuffer)

OauthController.java

package com.example.oauth;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

@Controller
public class OauthController {

    @RequestMapping("/")
    public String index(Model model) {
        model.addAttribute("title", "OAuth test 2.0");
        return "index";
    }

    @RequestMapping("/login/kakao")
    public void kakao(HttpServletResponse httpServletResponse) throws IOException {

        String kakaoAuthUri = "https://kauth.kakao.com/oauth/authorize?client_id=insertYourId&redirect_uri=http://localhost:8080/oauth&response_type=code";

        StringBuilder sb = new StringBuilder();
        sb.append("https://");
        sb.append("kauth.kakao.com");
        sb.append("/oauth/authorize?");
        sb.append("client_id=insertYourId");
        sb.append("&");
        sb.append("redirect_uri=http://localhost:8080/oauth");
        sb.append("&");
        sb.append("response_type=code");
        
        httpServletResponse.sendRedirect(sb.toString());
    }

    @RequestMapping("/oauth")
    public String oauth(@RequestParam String code) {
        // 인증토큰 수신
        System.out.println(code);
        return "oauth";
    }    

}

- String kakaoAuthUri, StringBuffer sb를 사용하여 URI 생성

- StringBuffer가 String 방식보다 가독성이 좋다. 하지만 스키마 구분자(://), 쿼리 구분자(&)등 불필요한 코드를 넣어줘야 한다.

 

개선된 방식(UriComponentsBuilder)

OauthController.java

package com.example.oauth;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

@Controller
public class OauthController {

    @RequestMapping("/")
    public String index(Model model) {
        model.addAttribute("title", "OAuth test 2.0");
        return "index";
    }

    @RequestMapping("/login/kakao")
    public void kakao(HttpServletResponse httpServletResponse) throws IOException {

        UriComponents uriComponents = UriComponentsBuilder.newInstance()
            .scheme("https")
            .host("kauth.kakao.com")
            .path("/oauth/authorize")
            .queryParam("client_id", "Insert your Id")
            .queryParam("redirect_uri", "http://localhost:8080/oauth")
            .queryParam("response_type", "code")
            .build(true);
            
        httpServletResponse.sendRedirect(uriComponents.toString());
    }

    @RequestMapping("/oauth")
    public String oauth(@RequestParam String code) {
        // 인증토큰 수신
        System.out.println(code);
        return "oauth";
    }    

}

- urlComponentsBuilder 는 UriBuilder 의 인터페이스를 구현한 클래스이다.

- StringBuffer 방식에 비해 간결해졌으며 scheme, host, path, queryParam으로 URI 구조를 한눈에 파악할 수 있다. 

- 아래와 같이 get 함수로 URI 정보를 얻는다.

        System.out.println(uriComponents.getScheme());
        System.out.println(uriComponents.getHost());
        System.out.println(uriComponents.getPath());
        System.out.println(uriComponents.getQuery());
        uriComponents.getQueryParams().forEach((key, value) -> {
            System.out.println("key:"+key+", value:"+value);
        });

Output

https
kauth.kakao.com
/oauth/authorize
client_id=InsertYourId&redirect_uri=http://localhost:8080/oauth&response_type=code
key:client_id, value:[InsertYourId]
key:redirect_uri, value:[http://localhost:8080/oauth]
key:response_type, value:[code]
/path1

URI 로드

- fromUriString, fromPath 함수를 사용하여 uri를 읽어 UriComponents객체를 생성한다.

UriComponents inbound_uri = UriComponentsBuilder.fromUriString("https://www.google.com/search?q=java").build(true);
System.out.println(inbound_uri.getHost());
System.out.println(inbound_uri.getQuery());

 

추가

다음과 같이 {{ }} 을 사용하여 Key, Value를 사용하는 Map함수들에 대해 간단히 매핑 할 수 있다.

UriComponents uriComponents = UriComponentsBuilder
        .fromUriString(baseUri)
        .queryParams(new LinkedMultiValueMap<>() {
            {
                add("function", "CURRENCY_EXCHANGE_RATE");
                add("from_currency", fromCurrrencyCode);
                add("to_currency", toCurrencyCode);
                add("apikey", apiKey);
            }
        })
        .build();
반응형