[Spring] WebClient를 통한 공공데이터 Open API 호출

2024. 7. 17. 00:34·Back-end/Spring
반응형

공공데이터 Open API를 사용하는 서비스의 흐름을 알기 위해 공부를 하면서 알게 된 내용들을 기록하는 글입니다. 오류나 고쳐야 할 사항들이 있다면 피드백 부탁드리겠습니다!

WebFlux 라이브러리를 사용한 이유

Spring에서 외부 API를 사용할 수 있는 종류는 다음과 같다.

  • HttpURLConnection
  • RestTemplate
  • WebClient

HttpURIConnection은 URLBuilder를 사용하여 코드를 작성한 것으로, 생각보다 코드가 길고 장황하다.

RestTemplate은 Spring에서 지원하는 객체로, 동기식으로 Rest 방식 API를 호출할 수 있는 Spring 내장 클래스이다.

동기적으로 동작하기 때문에 요청/응답 동안 스레드가 차단되는 문제점이 있을 뿐더러, Spring boot 5.x 버전 이후로 Deprecated 되었기에 WebFlux 라이브러리의 WebClient를 사용하기로 결정했다.

 

WebClient를 사용한 Open API 연결

WebClient를 통한 Http 통신은 다음 과정을 거친다.

 

  1. WebClient의 인스턴스를 builder를 통해 생성
  2. url, query parameter등을 설정
  3. 결과 값을 받아 처리

1. build.gradle

implementation 'org.springframework.boot:spring-boot-starter-webflux'

 

webflux를 사용하기 위한 종속성을 추가해준다.

 

2. WebClientConfig 설정

WebClient.Builder를 Bean으로 의존성 주입이 가능하기 때문에 생성자를 통해 의존성을 주입받는다.

@Configuration
public class WebClientConfig {

    @Value("${sample.baseurl}")
    private String baseUrl;

    @Bean
    public WebClient webClient(){
        DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
        factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);

        return WebClient.builder()
                .uriBuilderFactory(factory)
                .baseUrl(baseUrl)
                .build();
    }
}

 

여기서 중요한 부분은 factory.setEncodingMode이다.

 

WebClient는 query parameter를 UriComponentsBuilder#encode() 방식을 이용해서 인코딩하기 때문에 쿼리 파라미터의 값이 달라질 수 있다.

 

따라서 인코딩 방식을 다르게 하거나, 인코딩을 하지 않도록 적용해야 한다.

DefaultUriBuilderFactory() 객체를 생성하여 인코딩 모드를 NONE이나 VALUES_ONLY로 변경한 후, WebClientBuilder에 적용하면 API 통신이 정상적으로 작동할 것이다.

 

나는 VALUES_ONLY를 적용하여 쿼리 파라미터의 값만 인코딩 하였다.

 

3. 비즈니스 로직 구현

package bootcamp.sample.openapi.sample;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;


@Service
@RequiredArgsConstructor
public class SampleService {

    private final WebClient webClient;

    @Value("${sample.encoding}")
    private String encodingKey;

    public Mono<CrimeDTO> getCrime(String page, String perPage) {

        return webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/3074462/v1/uddi:fe3ae686-8f7d-4d82-8c3a-901a02a0aa75")
                        .queryParam("page", page)
                        .queryParam("perPage", perPage)
                        .queryParam("serviceKey", encodingKey)
                        .build())
                .retrieve()
                .bodyToMono(CrimeDTO.class)
                .doOnError(e -> {
                    System.err.println("Error: " + e.getMessage());
                });
    }
}

 

- encodingKey : 공공데이터포탈에서 발급해준 인코딩 키이다. webclient url에 넣어주면 된다.

 

  • uriBuilder를 이용하면 url, query parameter를 깔끔하게 설정 가능하다.
  • .retrieve() 메서드는 WebClient의 주요 메서드 중 하나인데, 해당 메서드를 호출하면 HTTP 요청을 보내고 그에 대한 응답을 받을 수 있다.
  • .bodyToMono()를 통해 응답을 원하는 형태의 객체로 받을 수 있다.

이후에는 .subscribe() 혹은 .block()을 통해 응답을 받을 수 있는데, .block()을 사용하면 응답을 동기적으로 대기하고 받아온다.

 

<추가>

macOS 환경에서 로컬로 webflux를 사용하려했던 결과 다음과 같은 에러가 발생했다.

Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS.

 

이것은 applie silicon(M1, M2 등)을 사용하면서 netty를 사용하면 발생하는 문제다.

따라서 gradle에 다음 dependency를 추가하면 해결할 수 있다.

runtimeOnly 'io.netty:netty-resolver-dns-native-macos:4.1.104.Final:osx-aarch_64' // 추가

참고

https://m42-orion.tistory.com/124

 

[Spring WebFlux] WebClient 통해 공공데이터 Open API 호출하기 + 유의점(SERVICE KEY IS NOT REGISTERED ERROR)

이 글은 공부를 하면서 알게 된 내용들을 기록하는 글 입니다. 오류나 고쳐야 할 사항들이 있다면 지적 부탁드립니다! ✅ WebFlux를 이용한 이유 혼자 공부 겸 진행하고 있는 프로젝트에서 공공데

m42-orion.tistory.com

https://effortguy.tistory.com/282

 

[Spring Webflux] Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. Th

문제 spring webflux 서버를 키니 아래와 같은 에러 로그가 발생했다. Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. 원

effortguy.tistory.com

https://blog.naver.com/hj_kim97/222295259904

 

[Spring]스프링 RestTemplate

스프링 RestTemplate - RestTemplate란?  - RestTemplate의 특징 - RestTemplate 동작 원리 -...

blog.naver.com

https://wpioneer.tistory.com/222

 

[Spring Boot] WebClient 파라미터 인코딩 하는법

WebClient를 사용해서 그냥 호출하게 되면 인코딩을 하지 않아 API 키가 달라지는 경우가 생길수가 있다. 나같은 경우에 그 문제 때문에 골머리를 앓았는데 아래와 같은 방법으로 해결했다. 일단 Uri

wpioneer.tistory.com

 

반응형

'Back-end > Spring' 카테고리의 다른 글

[Spring] 무한 redirection  (0) 2024.08.14
[Spring] Security + JWT + Redis를 활용한 로그인 구현 (1)  (0) 2024.07.20
[Spring] H2 DataBase 사용법  (0) 2024.06.27
[Spring] Spring만의 유효성 검사 @Valid, @Validated 정리  (3) 2024.06.27
[Spring] createdAt, updatedAt 사용하기  (0) 2024.06.19
'Back-end/Spring' 카테고리의 다른 글
  • [Spring] 무한 redirection
  • [Spring] Security + JWT + Redis를 활용한 로그인 구현 (1)
  • [Spring] H2 DataBase 사용법
  • [Spring] Spring만의 유효성 검사 @Valid, @Validated 정리
류건
류건
개발 일지
  • 류건
    건's Dev
    류건
  • 전체
    오늘
    어제
    • 분류 전체보기 (96) N
      • Back-end (56) N
        • Spring (31) N
        • Nest.js (3)
        • Next.js (2)
        • Node.js (3)
      • Infra & Cloud (5) N
        • Cloud Computing (6)
        • Docker (3)
        • AWS (7)
      • Java (2)
      • Computer Science (12)
        • Computer Network (0)
        • Operating System (0)
        • 정보 보호와 시스템 보안 (12)
      • 회고록 (1)
        • 우아한테크코스 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    public key
    JPA
    어노테이션
    nginx
    Nest.js
    CI/CD
    WebClient
    aws
    Docker
    Spring
    EC2
    express.js
    ddl-auto
    Lock
    티스토리챌린지
    Github Actions
    node.js
    ssl
    CORS
    Spring Boot
    Kafka
    https
    Webflux
    CD
    db
    JWT
    정보보호
    오블완
    보안
    고가용성
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.0
류건
[Spring] WebClient를 통한 공공데이터 Open API 호출
상단으로

티스토리툴바