해당 내용은 스프링 공식 Getting Started의 내용을 공부 후 작성되었습니다.
https://spring.io/guides/gs/rest-service
저는 인텔리제이를 사용학고 있기 때문에 따로 STS(Spring Tool Suite)를 설치하지 않았습니다. 이클립스 등의 환경에서는 설치 후 이용해주세요.
여기서는
REST와 RESTful
에 대해서 정말 간략하게만 설명하고 넘어갑니다.
예전에 정리해둔 포스트가 있으니 전체적인 내용은 해당 포스트를 참조해주세요.
RESTful
이란 REST
규칙에 따른 주소 체계를 의미합니다. 주소(url)에 HTTP 요청 메소드(GET, POST 등)를 명시함으로써 주소만 보고도 사용자, 개발자가 지금 웹 애플리케이션에서 무슨 작업을 하고 있구나하고 알 수 있다는 특징이 있습니다.
마찬가지로 HTTP 요청 메소드에 대한 내용은 이 포스트를 참조해주세요.
이 포스트에서 작성하면 포스트가 너무 방대해지고 번잡해져서 생략하는 것이지 불필요해서가 아닙니다. 아래 내용을 제대로 이해하려면
REST, HTTP
두 포스트를 한 번 읽어보시고(또는 먼저 학습한 후) 진행하시는 것을 강력하게 추천드립니다.아래 내용들은
REST, HTTP
두 내용들을 어느정도 알고 있다는 가정 하에 작성되었습니다.
이번에는 스프링에서 가장 기본적인 RESTful 서버를 여는 방법에 대해서 알아보겠습니다.
먼저 Spring Initializr를 이용해서 사용할 프로젝트를 생성합니다. 나머지 설정은 defualt로 사용해도 괜찮지만 Dependencies
에서 Spring Web
은 반드시 추가해주세요.
저는 프로젝트 이름, 패키지 이름을 튜토리얼을 따라서 각각 rest-service와 restservice로 했습니다.
필요하시다면
Spring Initializr
에 대한 설명은 이 포스트를 참조해주세요.
Dependencies로 추가한 Spring Web에 내장 톰캣 서버가 있기 때문에 생성된 프로젝트를 run하면 로컬에서 Spring으로 웹 서버를 구동할 수 있습니다.
이렇게 실행한 서버를 통해 우리는 다음과 같은 JSON 형태의 객체 데이터를 응답받으려고 합니다.
{
"id": 1,
"content": "Hello, World!"
}
서버로부터 응답받기 위한 데이터인 Greeting.java
레코드를 다음과 같이 com.example.restservice
패키지에 생성합니다.
package com.example.restservice;
public record Greeting(long id, String content) { }
기본적으로 포함되어 있는 Jackson JSON
라이브러리를 통해서 Greeting 타입의 인스턴스가 자동으로 JSON으로 해석됩니다.
스프링으로 구축하는 RESTful
의 HTTP 요청 메소드는 컨트롤러
에 의해 처리됩니다. 컨트롤러
는 @RESTController
라는 Annotation으로 식별이 됩니다.
다음은 Greeting 클래스를 응답받기 위한 컨트롤러 코드입니다. 이 컨트롤러는 Greeting 클래스의 새 인스턴스를 반환하여 /greeting
의 GET 요청을 처리합니다.
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));
}
}
마지막 세 줄이 핵심코드로 간결한 코드지만 엄청난 동작들이 숨어있습니다. 하나하나씩 살펴보겠습니다.
@GetMapping("/greeting")
Annotation은 /greeting
에 대한 GET 요청
이 public Greeting greeting()
메소드에 매핑되도록 합니다. 따라서 주소에 /greeting
을 붙이면 greeting()
메소드가 실행되어 응답됩니다.
지금은 서버로부터 데이터를 받는
GET 메소드
만 연습해서@GetMapping
을 이용했는데요.POST 메소드
에 대한 매핑을 하는@PostMapping
Annotation도 있습니다.추가적으로 다른 메소드에 대해 사용할 수 있는
@RequestMapping(method=메소드)
Annotation도 있습니다.
@RequestParam
은 쿼리 문자열 name의 값을 greeting()
의 매개변수 name에 바인딩합니다.
쿼리 문자열
은 주소의 끝에?
로 시작하는 문자열을 가리킵니다.
위 주소에서google.com/search
까지가 주소고 그 뒤에오는?
부터 시작해서 오는 값들이 쿼리 문자열입니다.
쿼리 문자열 name이 전달되지 않는다면 defaultValue인 World가 name의 값으로 사용됩니다.
greeting() 메소드의 본문은 return문 한 줄로 간단합니다.
바로 id와 name을 가진 Greeting 객체를 반환합니다. 이때 id는 counter
에 의해 생성할수록 1에서 시작하여 하나씩 증가하는 값을 가지며, name을 template
필드의 형식에 따라 format되어 값을 가집니다.
name 매개변수의 defaultValue인 World를 예시로 들자면 template가 "Hello, %s!"
형식이므로 content에는 "Hello, World"
가 저장되겠죠.
Spring initializr
를 사용했다면 실행을 위한 애플리케이션 클래스 하나가 처음부터 생성되어있을 것입니다. 지금은 딱히 이 클래스를 수정할 필요 없이 이 클래스의 main 메소드를 실행하면 서비스가 실행됩니다.
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);
}
}
@SpringBootApplication
은 다음 Annotation의 기능을 지원하는 편의성 Annotation 입니다.
여기서 @Target, @Retention, @Documented, @Inherited
는 자바의 메타 어노테이션에서 다뤘었던 내용이니 나머지 세 개만 따로 정리해봤습니다.
@SpringBootConfiguration
은 애플리케이션에 대한 구성을 제공하는 Annotation입니다. 내부적으로 보면 또 다시 @Configuration
과 @Indexed
가 선언되어 있음을 볼 수 있습니다.
@Configuration
: @Bean을 정의하고 스프링 컨테이너에 등록합니다.
빈(Bean)
은 스프링 컨테이너에 의해 관리 및 재사용되는 자바 객체를 의미합니다.
@Indexed
: Bean을 스프링 컨테이너에 등록하는 과정에서 인덱싱과 스트레오타입 설정을 합니다.
@EnableAutoConfiguration
은 스프링부트에게 클래스 경로나 속성 설정 등을 기반으로 빈 추가를 하도록 지시합니다.
@ComponentScan
은 com.example
패키지의 다른 구성 요소나 서비스를 찾도록 스프링에게 알려 컨트롤러를 찾을 수 있게 합니다.
Annotation 동작 이후 main 메소드의 SpringApplication.run()
을 통해 스프링 서비스를 실행합니다.
실행을 하면 다음과 같은 화면이 뜨면서 8080
번 포트에서 톰캣 서버가 시작되었다는 메세지가 출력됩니다.
접속은 http://localhost:8080
를 통해 접속합니다. 에러 페이지가 뜨면 실패한게 아니고 성공한 것입니다. 단순히 http://localhost:8080
페이지에 대한 화면 설정을 할 코드가 없어서 에러가 뜨는 것이지 서버는 성공적으로 실행된 것 이기 때문입니다.
아까 우리는 /greeting
을 통해 GET 요청을 하기로 했으니 http://localhost:8080/greeting
으로 이동합니다. Greeting 객체가 제대로 출력되었음을 확인할 수 있습니다.
혼자서 이것저것 테스트 하다가 id가 4가 된 것이므로 크게 신경 안쓰셔도 됩니다. 중요한 것은 JSON의 형태로 객체가 출력되었음을 보는 것 입니다.
자 그러면 defaultValue를 확인했으니 쿼리 문자열을 통해 name의 값을 전달해볼까요? 쿼리 문자열을 통한 RESTful 주소는 다음과 같이 전달합니다. http://localhost:8080/greeting?name=spring
전달한 name 파라미터의 값이 제대로 content에 적용되었음을 볼 수 있습니다.
이렇게 기본적인 GET 요청을 받는 스프링 RESTful 서버를 체험해보았습니다.