REST(Representational State Transfer)는 자원을 이름으로 구분하여 해당 자원의 상태를 컴퓨팅 시스템 간에 주고받는 모든 과정을 의미합니다.
이 가이드에서는 Spring을 사용해 Hello, World! RESTful 웹 서비스를 구현합니다.
http://localhost:8080/greeting에서 HTTP GET 요청을 수신하고, 다음과 같이 JSON으로 응답합니다.
{"id":1,"content":"Hello, World!"}
URL은 Optional한 name 쿼리 파라미터가 추가되어 http://localhost:8080/greeting?name=User 처럼 호출됩니다.
name 쿼리 파라미터가 Null인 경우 default로 World!를 응답합니다. Not Null인 경우 name 쿼리 파라미터의 값을 사용하여 응답합니다.
{"id":1,"content":"Hello, User!"}
테스트 환경 및 주요 아젠다
RESTful 웹 서비스를 구현하고 쿼리 파라미터에 따라서 JSON 서문을 응답하는 Spring 프로젝트입니다.
이 프로젝트의 개발 환경
- 개발 언어 및 환경
- OpenJDK 17.0.9
- Gradle 8.4
- 그 외 환경
- IntelliJ IDEA 2020.3 Ultimate Edition
Getting Started guides처럼 모든 단계를 처음부터 따라 진행하거나 기본 단계를 건너 뛸 수 있습니다.
단계를 건너뛰려면 소스 파일을 Download하거나 GitHub: spring-guides/gs-rest-service를 참고합니다.
Spring Initializr를 사용하여 시작하기
pre-initialized project에서 ZIP 파일을 다운로드합니다.
또는 Spring Initializr를 처음부터 설정하려면
Project:Gradle또는Maven중 하나를 선택합니다.Language:Java를 선택합니다.Dependencies:Spring Web을 선택합니다.
리소스 표현 클래스(Resource Representation Class) 생성
서비스는 /greeting 요청에 대해서 HTTP GET을 수신합니다. 추가적으로는 Optional한 name 파라미터를 쿼리 파라미터에서 읽을 수 있습니다.
이 요청은 200 OK와 함께 다음과 같은 JSON 본문으로 응답됩니다.
{
"id": 1,
"content": "Hello, World!"
}
코드 | 비고 | |
다음 경로 src/main/java/com/example/restservice 패키지에서 Greeting.java 클래스를 생성합니다.
이 클래스는 /greeting 요청에 대한 리소스를 표현합니다.
package com.example.restservice;
public record Greeting(long id, String content) { }
이 클래스는 일반적인 자바의 클래스 형식을 따르지 않습니다.
package com.example.restservice;
public class Greeting
{
// fill up Greeting class's field, method
}
이 애플리케이션은 Jackson JSON을 사용해 Greeting 객체를 자동으로 JSON으로 변환합니다.
리소스 컨트롤러(Resource Controller) 생성
RESTful 웹 서비스를 구현하는 Spring은 컨트롤러(Controller)에서 HTTP 요청을 처리합니다.
다음 경로 src/main/java/com/example/restservice 패키지에서 GreetingController.java 클래스를 생성합니다.
package com.example.restservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicLong;
@RestController
public class GreetingController
{
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name)
{
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
코드 | 비고 | |
RESTful 웹 요청을 처리하는 모든 메소드는 뷰(View) 대신 다음 어노테이션 |
||
어노테이션의 필드 어노테이션의 필드 |
RESTful 웹 서비스의 컨트롤로와 기존 MVC 컨트롤러와의 차이점은 HTTP 응답에 대한 본문을 생성하는 방식입니다.
Greeting 객체를 HTML로 렌더링하기 위한 뷰(View)에 의존하지 않고, Greeting 객체의 필드를 채우고 리턴하는 것으로 대신합니다.
Greeting 객체는 HTTP 응답 과정에서 JSON으로 작성됩니다.
Greeting 객체는 JSON으로 파싱되어야 하며, Spring에서는 JSON 파싱을 위한 메뉴얼적인 코드를 작성할 필요는 없습니다.
MappingJackson2HttpMessageConvert가 classpath에 위치한 jackson 2에 의거해 객체를 자동으로 파싱합니다.
@SpringBootApplication
다음 경로 src/main/java/com/example/restservice 패키지에서 RestServiceApplication.java 클래스를 살펴봅니다.
이 클래스는 Spring Initializr가 Spring Web 의존성을 포함할 때 자동 생성됩니다.
package com.example.restservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RestServiceApplication
{
public static void main(String[] args)
{
SpringApplication.run(RestServiceApplication.class, args);
}
}
코드 | 비고 | |
다음 어노테이션 |
||
해당 클래스를 Application context를 정의하는 |
||
classpath의 Bean, 기타 Bean 그리고 환경 변수를 Spring Boot에 추가합니다. 예를 들어 classpath에 |
||
동일한 패키지 com/example에서 |
||
Spring Boot에서 애플리케이션을 실행합니다. |
이 애플리케이션은 XML과 web.xml 파일을 포함하지 않습니다.
별도의 파이프라인 또는 인프라 구성을 요구하지 않으며 100% 자바로 동작합니다.
JAR 빌드 및 애플리케이션 실행
Gradle 또는 Maven 명령줄을 사용해 애플리케이션을 실행합니다(이 프로젝트에서는 Gradle 사용).
macOS 또는 Linux 기반의 Gradle 환경에서는 ./gradlew bootRun을 실행합니다.
./gradlew bootRun
> Task :bootRun
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.1.5)
2023-11-20T15:55:14.383+09:00 INFO 83040 --- [ main] c.e.restservice.RestServiceApplication : Starting RestServiceApplication using Java 17.0.9 with PID 83040 (/Users/guenbongpark/Downloads/rest-service/build/classes/java/main started by guenbongpark in /Users/guenbongpark/Downloads/rest-service)
2023-11-20T15:55:14.384+09:00 INFO 83040 --- [ main] c.e.restservice.RestServiceApplication : No active profile set, falling back to 1 default profile: "default"
2023-11-20T15:55:14.819+09:00 INFO 83040 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2023-11-20T15:55:14.825+09:00 INFO 83040 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-11-20T15:55:14.825+09:00 INFO 83040 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.15]
2023-11-20T15:55:14.881+09:00 INFO 83040 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-11-20T15:55:14.881+09:00 INFO 83040 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 471 ms
2023-11-20T15:55:15.051+09:00 INFO 83040 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-11-20T15:55:15.056+09:00 INFO 83040 --- [ main] c.e.restservice.RestServiceApplication : Started RestServiceApplication in 0.868 seconds (process running for 1.065)
<==========---> 80% EXECUTING [1m 22s]
> :bootRun
또는 동일한 환경에서 ./gradlew build를 사용해 JAR 파일로 빌드합니다. 빌드가 완료되면 java -jar 명령문으로 JAR 파일을 실행합니다.
$ ./gradlew build
$ java -jar build/libs/gs-rest-service-0.1.0.jar
테스트
애플리케이션을 실행하고 웹 브라우저에서 http://localhost:8080/greeting URL로 요청합니다.
{"id":1,"content":"Hello, World!"}
이번에는 name 쿼리 파라미터를 추가하여 http://localhost:8080/greeting?name=User URL로 요청합니다.
{"id":2,"content":"Hello, User!"}
GreetingController의 @RequestParam이 예상대로 동작하는 것을 알 수 있습니다.
응답 결과로 확인되는 id 필드 역시 처음 요청 1에서 2로 값이 증가하였습니다.
서로 다른 요청이 동일한 GreetingController 객체에 의해서 처리되고 있으며 counter 필드가 정상대로 증분하고 있음을 알 수 있습니다.
'Java > Spring' 카테고리의 다른 글
Spring.io 따라하기: RESTful 웹 서비스에 요청하기 (0) | 2023.11.22 |
---|---|
Spring 5 입문: Chapter 02B. 예제 코드로 Spring 시작하기 (0) | 2023.11.21 |
Spring 5 입문: Chapter 02A. 스프링 프로젝트 시작하기 (0) | 2023.11.17 |
"Could not resolve org.springframework.boot:spring-boot-gradle-plugin:3.x.x" 스프링 프레임워크 플러그인 오류 (0) | 2023.11.07 |
Spring.io 따라하기: Quickstart (0) | 2023.11.07 |