Spring RESTful 웹 서비스 사용하기

■ 참고 – Consuming a RESTful Web Service(RESTful 웹 서비스 사용하기)

■ 이 가이드는 RESTful 웹 서비스를 사용하는 애플리케이션을 만드는 과정을 안내한다. Spring의 RestTemplate을 사용하여 https://gturnquist-quoters.cfapps.io/api/random에서 임의의 Spring Boot 인용문을 검색하는 애플리케이션을 빌드 할 것이다. 대부분의 Spring Getting Started 가이드와 마찬가지로, 처음부터 시작하여 각 단계를 완료하거나 이미 익숙한 기본 설정 단계를 건너 뛸 수 있다.  먼저 Eclipse에서 Maven Project를 생성한다.

■ Eclipse에서 Spring Consuming REST 프로젝트 생성한다. Packaging을 jar로 선택한다.

Eclipse Maven Project 생성

■ Maven의 pom.xml파일을 아래와 같이 작성한다.

<project xmlns="http://maven.apache.org/POM/4.0.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0  http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>net.iotinfra</groupId>
  <artifactId>pilot.consumingrest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

■ Spring Boot Maven 플러그인은 많은 편리한 기능을 제공한다.

  • 클래스 패스에 있는 모든 jar를 모아 하나의 실행가능한 “über-jar”를 빌드하므로 서비스를 실행하고 전송하는 것이 더 편리하다.(über-jar는 패키징시 제작된 모듈과 디펜던시가 하나의 jar에 파일에 포함된 것을 의미. https://opennote46.tistory.com/110)
  • public static void main () 메서드를 검색하여 실행 가능한 클래스로 플래그를 지정한다.
  • Spring Boot 의존성에 맞게 버전 번호를 설정하는 빌트인 의존성 분석기를 제공한다. 원하는 버전을 무시할 수 있지만 기본적으로 Boot에서 선택한 버전 세트가 사용된다.

■ REST 리소스 가져 오기

프로젝트 설정이 완료되면 RESTful 서비스를 사용하는 간단한 애플리케이션을 만들 수있다. RESTful 서비스가 https://gturnquist-quoters.cfapps.io/api/random에 있다. 그것은 Spring Boot에 대한 인용구를 무작위로 가져 와서 JSON 문서로 반환한다. 웹 브라우저나 CURL을 통해 URL을 요청하면 다음과 같은 JSON 문서를 받게된다.

{
   type: "success",
   value: {
      id: 10,
      quote: "Really loving Spring Boot, makes stand alone Spring apps easy."
   }
}

브라우저나 또는 curl을 통해 가져오는 것이 충분히 쉽지만 굉장히 유용하지는 않다. REST 웹 서비스를 사용하는 보다 유용한 방법은 프로그래밍 방식이다. 이 작업을 돕기 위해 Spring은 RestTemplate이라는 편리한 템플릿 클래스를 제공한다. RestTemplate은 대부분의 RESTful 서비스와 한 줄의 요청을 주고 받는다. 또한 이 데이터를 맞춤 도메인 유형에 바인딩 할 수도 있다.

■ Quote.java – 먼저 필요한 데이터를 포함할 도메인 클래스를 만든다.

package pilot.consumingrest.hello;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Quote {
    private String type;
    private Value value;
    public Quote() {
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public Value getValue() {
        return value;
    }
    public void setValue(Value value) {
        this.value = value;
    }
    @Override
    public String toString() {
        return "Quote{" +
                "type='" + type + '\'' +
                ", value=" + value +
                '}';
    }
}

보다시피 이 속성은 몇 가지 속성과 일치하는 getter 메서드가있는 간단한 Java 클래스이다. Jackson JSON 프로세싱 라이브러리의 @JsonIgnoreProperties 어노테이션이 달려있어 이 유형에 바인딩되지 않은 모든 속성을 무시해야 함을 나타낸다.

데이터를 사용자 정의 유형에 직접 바인드하려면 API에서 리턴된 JSON 문서의 키와 완전히 동일한 변수 이름을 지정해야 한다.  JSON 문서의 변수 이름과 키가 일치하지 않는 경우 @JsonProperty 어노테이션을 사용하여 JSON 문서의 정확한 키를 지정해야 한다. 

■ Value.java – 내부 클래스(위의 코드에서 ‘Value’ 클래스) 자체를 내장하려면 추가 클래스가 필요하다.  

package pilot.consumingrest.hello;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Value {
    private Long id;
    private String quote;
    public Value() {
    }
    public Long getId() {
        return this.id;
    }
    public String getQuote() {
        return this.quote;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public void setQuote(String quote) {
        this.quote = quote;
    }
    @Override
    public String toString() {
        return "Value{" +
                "id=" + id +
                ", quote='" + quote + '\'' +
                '}';
    }
}

■ Application.java – 이제 RestTemplate을 사용하는 Application 클래스를 작성하여 Spring Boot quotation 서비스에서 데이터를 가져올 수 있다.

package pilot.consumingrest.hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;

public class Application {
    private static final Logger log = LoggerFactory.getLogger(Application.class);
    public static void main(String args[]) {
        RestTemplate restTemplate = new RestTemplate();
        Quote quote =  restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random",  Quote.class);
        log.info(quote.toString());
    }
}

Jackson JSON 처리 라이브러리가 클래스 경로에 있기 때문에 RestTemplate은 메시지 변환기를 통해 수신 JSON 데이터를 Quote 객체로 변환하는데 RestTemplate을 사용한다. 거기에서 Quote 객체의 내용이 콘솔에 기록된다.
여기서는 RestTemplate을 사용하여 HTTP GET 요청만 했다. 그러나 RestTemplate은 POST, PUT 및 DELETE와 같은 다른 HTTP 타입의 요청도 지원한다.

■ 수정된 Application.java – Spring Boot로 애플리케이션 라이프 사이클 관리하기

지금까지는 응용 프로그램에서 Spring Boot를 사용하지 않았지만 그렇게 할 때 몇 가지 장점이 있다. 장점 중 하나는 Spring Boot가 RestTemplate에서 메시지 변환기를 관리하게하여 사용자 정의를 선언적으로 쉽게 추가 할 수 있게하려는 것이다. 이를 위해 메인 클래스에서 @SpringBootApplication을 사용하고 Spring 부트 애플리케이션과 마찬가지로 main 메소드를 시작하도록 변환한다. 마지막으로 RestTemplate을 CommandLineRunner 콜백으로 이동하여 시작시 스프링 부트에 의해 실행되도록 한다.

package pilot.consumingrest.hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class Application {
       private static final Logger log =  LoggerFactory.getLogger(Application.class);
       public static void main(String args[]) {
              SpringApplication.run(Application.class);
       }
       @Bean
       public RestTemplate restTemplate(RestTemplateBuilder builder) {
              return builder.build();
       }
       @Bean
       public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
              return args -> {
                     Quote quote = restTemplate.getForObject(
                                  "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
                     log.info(quote.toString());
              };
       }
}

RestTemplateBuilder는 Spring에 의해 주입되며 RestTemplate을 생성하기 위해 Spring을 사용할 경우, 메시지 변환기와 요청 팩토리가 있는 Spring Boot에서 발생하는 모든 자동 구성의 이점을 누릴 수 있다. 우리는 RestTemplate을 @Bean으로 추출하여 쉽게 테스트 할 수 있습니다 (그렇게 쉽게 테스트될 수 있다).

■ 애플리케이션을 실행가능하게 만들기

이 서비스를 외부 응용 프로그램 서버에 배포하기 위한 기존 WAR 파일로 패키지화 할 수는 있지만 아래에 설명 된 간단한 방법은 독립 실행 형 응용 프로그램을 만든다. 순수한 Java main () 메소드로 구동되는 실행 가능한 단일 JAR 파일로 모든 것을 패키지화한다. 그동안 외부 인스턴스에 배포하는 대신 Tomcat 서블릿 컨테이너를 HTTP 런타임으로 포함시키기위한 Spring의 지원을 사용한다.

■ 실행 가능한 JAR 빌드하기

Gradle 또는 Maven을 사용하여 명령 줄에서 응용 프로그램을 실행할 수 있다. 또는 모든 필요한 종속성, 클래스 및 자원을 포함하는 단일 실행 가능 JAR 파일을 빌드하고 실행할 수도 있다. 따라서 개발 수명주기, 다양한 환경에서 응용 프로그램으로 서비스를 쉽게 배포, 버전 및 배포 할 수 있다.

Project Build Option

■ 완성된 프로젝트의 디렉토리 구조

완성된 프로젝트의 디렉토리 구조

■ 빌드된 JAR 애플리케이션 실행 1 – DOS창(CMD창)에서 실행

java -jar target/pilot.consumingrest-0.0.1-SNAPSHOT.jar

■ 빌드된 JAR 애플리케이션 실행 2 

Eclipse Menu > Run > Run Configuration…  메뉴에서 실행한다.

애플리케이션 실행

■ 애플리케이션 실행 결과 – Eclipse Console에서 아래와 같이 확인할 수 있다.

애플리케이션 실행 결과