[Spring] 국세청_사업자등록정보 진위확인 및 상태조회 서비스 (WebClient)

 

 

국세청_사업자등록정보 진위확인 및 상태조회 서비스 

 

https://www.data.go.kr/iim/api/selectAPIAcountView.do#/%EC%82%AC%EC%97%85%EC%9E%90%EB%93%B1%EB%A1%9D%20%EC%83%81%ED%83%9C%EC%A1%B0%ED%9A%8C%20API

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

 

 

공공데이터 포털에서 API 사용 신청을 합니다

심의는 자동승인이라 사유 : 웹개발 (개인공부)로 기입하여 요청하니 바로 승인되었습니다

아래 인증키가 발급됩니다. (serviceKey 값)

 

2. 간단 실행해보기

 

아래 URL을 호출하면, 사업자등록정보 진위확인 API 가 실행되어 확인할 수 있도록 해보겠습니다.

(실제로는 * 사업자등록번호(필수), 사업자등록번호(필수),개업일자(필수)과 부가정보 등을 프론트 쪽에서 받아와서 검증하는 프로세스가 맞겠지만 테스트 느낌으로 어떻게 동작되는 지만 살펴보겠습니다.)

http://localhost:8080/api/v1/checkVendor

실행 결과 예시

 

 

3. 구현 소스

VendorProperites

@Getter
@Setter
@ConfigurationProperties(prefix = "vendor")
public class VendorProperties {
    private String vaildURL;
    private String serviceKey;
}

application 에 정의한 URL 과 서비스 키 값을 가져옵니다.

Application Main 쪽에 @EnableConfigurationProperties 에 추가해줍니다.

@SpringBootApplication
@EnableConfigurationProperties({
        CorsProperties.class,
        AppProperties.class,
        VendorProperties.class
})
public class SimpleSrmApplication {


    public static void main(String[] args) {
        SpringApplication.run(SimpleSrmApplication.class, args);
    }

}

 

VendorService

import com.simplesrm.api.common.*;
import com.simplesrm.config.properties.VendorProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Slf4j
@RequiredArgsConstructor
@Service
public class VendorService {

    private final VendorProperties vendorProperties;


    public String VendorValidation()  {

        VendorValidation vendorValidation = VendorValidation.builder()
                .b_no("사업자번호")
                .start_dt("개업일자")
                .p_nm("대표자명")
                .p_nm2("")
                .b_nm("업체명")
                .corp_no("법인번호")
                .b_sector("")
                .b_type("")
                .build();

        String requestBody = "{\n" +
                "  \"businesses\": [\n" +
                "    {\n" +
                "      \"b_no\": \"" + vendorValidation.getB_no() + "\",\n" +
                "      \"start_dt\": \"" + vendorValidation.getStart_dt() + "\",\n" +
                "      \"p_nm\": \"" + vendorValidation.getP_nm() + "\",\n" +
                "      \"p_nm2\": \"" + vendorValidation.getP_nm2() + "\",\n" +
                "      \"b_nm\": \"" + vendorValidation.getB_nm() + "\",\n" +
                "      \"corp_no\": \"" + vendorValidation.getCorp_no() + "\",\n" +
                "      \"b_sector\": \"" + vendorValidation.getB_sector() + "\",\n" +
                "      \"b_type\": \"" + vendorValidation.getB_type() + "\"\n" +
                "    }\n" +
                "  ]\n" +
                "}";

        WebClient webClient = WebClient.builder()
                .baseUrl(vendorProperties.getVaildURL() + vendorProperties.getServiceKey())
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();

        Mono<String> responseMono = webClient.post()
                .bodyValue(requestBody)
                .retrieve()
                .bodyToMono(String.class);

        return responseMono.block();
    }
}
requestBody 문자열을 생성하여 JSON 형식으로 요청 본문을 정의합니다.
vendorValidation 객체의 필드 값을 사용하여 JSON 문자열을 동적으로 생성합니다.
WebClient를 생성하고, 기본 URL과 헤더를 설정합니다.
WebClient는 비동기적인 HTTP 요청을 처리하는데 사용되는 Spring WebFlux의 일부입니다.
WebClient를 사용하여 POST 요청을 보내고, 요청 본문에 requestBody를 포함시킵니다.
그리고 retrieve() 메서드를 호출하여 응답을 검색하고, bodyToMono() 메서드를 사용하여 응답 본문 Mono<String> 형태로 변환합니다.
responseMono.block() 메서드를 호출하여 응답을 동기적으로 가져와서 반환

 

: requestBody 문자열로 JSON 형태로 작성함.

  또는 객체로 뭔가 하고 싶은데;; 이렇게 된 형태를 객체로 담으려고 하다보니 RequestBody 객체 + businesses 객체를 만든 다음, bodyValue에다가 넣어서 사용도 가능해보이나 이게 더 나은 건 지는 모르겠습니다.

import java.util.List;

public class RequestBody {
    private List<Business> businesses;

    public List<Business> getBusinesses() {
        return businesses;
    }

    public void setBusinesses(List<Business> businesses) {
        this.businesses = businesses;
    }
}

public class Business {
    private String b_no;
    private String start_dt;
    private String p_nm;
    private String p_nm2;
    private String b_nm;
    private String corp_no;
    private String b_sector;
    private String b_type;

    public String getB_no() {
        return b_no;
    }

    public void setB_no(String b_no) {
        this.b_no = b_no;
    }

    public String getStart_dt() {
        return start_dt;
    }

    public void setStart_dt(String start_dt) {
        this.start_dt = start_dt;
    }

    public String getP_nm() {
        return p_nm;
    }

    public void setP_nm(String p_nm) {
        this.p_nm = p_nm;
    }

    public String getP_nm2() {
        return p_nm2;
    }

    public void setP_nm2(String p_nm2) {
        this.p_nm2 = p_nm2;
    }

    public String getB_nm() {
        return b_nm;
    }

    public void setB_nm(String b_nm) {
        this.b_nm = b_nm;
    }

    public String getCorp_no() {
        return corp_no;
    }

    public void setCorp_no(String corp_no) {
        this.corp_no = corp_no;
    }

    public String getB_sector() {
        return b_sector;
    }

    public void setB_sector(String b_sector) {
        this.b_sector = b_sector;
    }

    public String getB_type() {
        return b_type;
    }

    public void setB_type(String b_type) {
        this.b_type = b_type;
    }
}
RequestBody requestBody = new RequestBody();
Business business = new Business();
business.setB_no(vendorValidation.getB_no());
business.setStart_dt(vendorValidation.getStart_dt());
business.setP_nm(vendorValidation.getP_nm());
business.setP_nm2(vendorValidation.getP_nm2());
business.setB_nm(vendorValidation.getB_nm());
business.setCorp_no(vendorValidation.getCorp_no());
business.setB_sector(vendorValidation.getB_sector());
business.setB_type(vendorValidation.getB_type());
requestBody.setBusinesses(Collections.singletonList(business));

 

 

4.  WebClient로 했는가?(사용이유)

 

간단하게 구현하는 건 RestTemplate 가 예제도 많고 사용법도 쉬워보였으나 

논블로킹 , 함수형 프로그래밍 등 원티드 백엔드 프리온보딩 과정을 통해 곁다리로 들은 내용도 있고 성능의 경우 사용자가 많아지면, WebClient 가 더 앞서게 되나 일정 사용자 이하에서는 동일함.

 

[차이점]

WebClient: 논블로킹, 이벤트 기반 모델을 사용하여 동시 요청 처리를 효율적으로 수행
RestTemplate: 블로킹 I/O 모델을 사용하며, 각 요청은 응답을 받을 때까지 스레드를 블로킹

 

그렇다고, WebClient 가 논 블로킹 모델만 지원하는 것이 아닌 동기식으로 수행하는 형태 또한 사용이 가능하다는 점 

새로운 프로젝트를 시작하거나 리액티브 프로그래밍을 적용하려는 경우 WebClient를 사용하며 요즘 WebFlux의 사용 추세가 늘고 있다는 점에 있어, 어떤 지 공부도 할 겸해서 적용해보았습니다.

 

 

5. WebClient 관련 해서 참고 하면 좋은 글

 

https://alwayspr.tistory.com/44

 

Spring WebFlux는 어떻게 적은 리소스로 많은 트래픽을 감당할까?

위 그림은 DZone 게시글 중 하나인 Spring WebFlux를 이용한 Boot2와 Spring MVC를 이용한 Boot1을 비교한 그래프이다. 해당 그래프에서는 두 가지 특징을 볼 수 있다. 첫 번째로는 유저가 적을 때에는 성능

alwayspr.tistory.com

 

 

 

https://happycloud-lee.tistory.com/220

 

Spring WebClient 쉽게 이해하기

1. Spring WebClient 이해 이 글을 읽기 전에 먼저 일하는 방식 변화를 이끌고 있는 애자일, 마이크로서비스, 데브옵스, 클라우드에 대해 기본적인 이해를 하실것을 권장 합니다. https://happycloud-lee.tisto

happycloud-lee.tistory.com