2.2.3 REST API
REST는 Representational State Transfer의 약자로, 아키텍처 스타일을 의미한다.
- 아키텍처 스타일: 반복되는 아키텍처 디자인.
- 아키텍처 패턴: 반복되는 문제 상황 해결 도구와 차이가 있음.
REST는 아키텍처 스타일은 6가지 제약조건으로 구성되며, 이를 따르는 API를 RESTful API라고 한다.
REST 아키텍처 스타일의 6가지 제약조건:
- 클라이언트-서버 (Client-Server)
- 클라이언트와 서버의 역할을 분리하여 개발과 확장이 용이하도록 함.
클라이언트-서버 라는 것은 리소스를 관리하는 서버가 존재하고 다수의 클라이언트가 리소스를 소비하려고 네트워크를 통해 서버에 접근하는 구조이다.
리소스란? REST API가 리턴할 수 있는 모든 것을 의미한다. 예를들어 HTML, JSON, 이미지 등이다.
- 클라이언트와 서버의 역할을 분리하여 개발과 확장이 용이하도록 함.
- 상태가 없는 (Stateless)
- 각 요청은 독립적이며 서버는 클라이언트의 상태를 저장하지 않음.
더보기
REST의 Stateless 제약조건에 따라, 서버는 클라이언트의 상태를 기억하지 않기 때문에 로그인의 경우 요청을 보낼 때마다 로그인 정보를 항상 함께 보내야 한다. 또한, 리소스를 수정한 후 그 상태를 유지해야 할 경우에는 서버가 아닌 데이터베이스와 같은 퍼시스턴스 저장소에 상태를 저장해야 한다.
이 내용은 REST의 Stateless(상태 없음) 제약조건을 설명한 것이다.
핵심은 서버가 클라이언트의 상태를 기억하지 않는다는 것이다. 예를 들어:- 로그인 상태를 유지하지 않음
- 서버는 클라이언트가 로그인했는지 기억하지 않음.
- 클라이언트가 요청을 보낼 때마다 **로그인 정보(예: 토큰)**를 포함해서 보내야 함.
- 리소스 상태 유지
- 어떤 리소스를 수정하거나 업데이트한 경우, 그 상태는 서버 메모리가 아니라 데이터베이스 같은 영구 저장소(퍼시스턴스)에 저장됨.
- 이렇게 하면 서버는 클라이언트 상태를 기억하지 않아도 요청을 처리할 수 있음.
간단히 정리하면:
REST에서는 서버가 클라이언트의 상태를 관리하지 않으므로, 클라이언트가 요청마다 필요한 정보를 보내야 하고, 상태 저장은 데이터베이스 같은 시스템에서 담당한다.
예시:
- 로그인 요청: 클라이언트가 서버에 토큰을 포함해 요청함.
- 수정 요청: 데이터를 수정하면, 서버는 상태를 데이터베이스에 저장하고 클라이언트의 상태는 기억하지 않음.
장점: 서버가 상태를 관리하지 않아 더 간단하고 확장성 있는 설계를 할 수 있음.
- 로그인 상태를 유지하지 않음
- 각 요청은 독립적이며 서버는 클라이언트의 상태를 저장하지 않음.
- 캐시 가능 (Cacheable), 캐시되는 데이터
- 응답 데이터는 캐싱될 수 있어야 하며, 이를 통해 성능을 개선함. HTTP에서는 cache -control이라는 헤더에 리소스의 캐시 여부를 명시할 수 있다.
- 일관적인 인터페이스 (Uniform Interface)
- API 설계에서 일관성을 유지하여 클라이언트와 서버 간의 상호작용을 단순화함.
리소스에 접근하는 방식, 요청 형식, 그리고 응답 형식, 즉 URI, 요청의 형태와 웅답의 형태가 애플리케이션 전반에 걸쳐 일관적이어야한다는것이 일관적인 인터페이스방침이다.
- API 설계에서 일관성을 유지하여 클라이언트와 서버 간의 상호작용을 단순화함.
- 계층화 시스템 (Layered System)
- 서버는 계층화된 시스템으로 구성되며, 중간 계층을 통해 보안과 확장성을 제공함.
예를 들어, 서버가 인증 서버, 캐싱 서버, 로드 밸런서를 거쳐 최종적으로 애플리케이션에 도착한다고 가정하면, 이 중간 레이어들은 요청과 응답에 영향을 미치지 않으며, 클라이언트는 이러한 레이어의 존재 유무를 알지 못한다.
- 서버는 계층화된 시스템으로 구성되며, 중간 계층을 통해 보안과 확장성을 제공함.
- 코드 온 디맨드 (Code-On-Demand, 선택사항)
- 서버는 클라이언트에 코드를 전송하고 실행할 수 있음 (예: JavaScript).
이 6가지 제약조건을 따르는 API를 RESTful API라고 한다.
REST는 HTTP와 다르다. REST는 아키텍처이며, HTTP를 이용해 구현하기 쉽고 대부분 그렇게 구현하지만, 엄밀히 말하면 REST는 아키텍처이고 HTTP는 REST 아키텍처를 구현할 때 사용하기에 적합한 프로토콜이다.
2.2.4 컨트롤 레이어 : 스프링 REST API 컨트롤러
implementation 'org.springframework.boot:spring-boot-starter-web'
지금부터 할 연결 작업의 어노테이션은 모두 스프링 부트 스타터 웹 페키지에서 제공하는 것이다.
@RestController
@RequestMapping("test")
public class TestController {
@GetMapping
public String testController() {
return "Hello, World!";
}
}
@GetMapping 어노테이션은 메서드의 리소스와 HTTP 메서드를 지정하는 데 사용된다. 클라이언트가 해당 리소스에 대해 GET 메서드로 요청하면, @GetMapping에 연결된 컨트롤러가 실행된다. 예를 들어, "localhost:8080/test" 경로의 GET 요청은 testController() 메서드와 연결된다는 의미이다. 이러한 작업은 스프링이 자동으로 처리해준다.
@GetMapping과 비슷한 어노테이션으로 @PostMapping, @PutMapping, @DeleteMapping 이 있는데 각각 HTTP 메서드가 POST, PUT, DELETE를 의미한다.
⭐⭐⭐ 매개변수를 넘겨받는 방법
@GetMapping("/{id}")
public String testControllerWithPathVariables(@PathVariable(required = false) int id) {
return "Hello World!" + id;
}
@PathVariable을 이용하면 /{id}와 같이 URI의 경로로 넘 어오는 값을 변수로 받을 수 있다.
@PathVariable도 마찬가지로 경로 변수를 매핑하는 데 사용된다. 예를 들어, @GetMapping("/{id}")에서 {id}는 경로로 들어오는 임의의 숫자나 문자를 변수 id에 매핑하라는 의미이다. 그림 2-28에서처럼 id가 정수형인 경우, test/ 뒤에 오는 정수가 id에 매핑된다. 예를 들어, http://localhost:8080/test/123을 실행하면 컨트롤러의 id 변수에 123이 전달된다. (required = false) 옵션은 이 매개변수가 필수가 아니라는 뜻으로, id=123을 명시하지 않아도 에러가 발생하지 않는다.
@GetMapping("/testRequestParam")
public String testControllerRequestParam(@RequestParam(required = false) int id) {
return "Hello World!" + id;
}
또 다른 방법으로는 @RequestParam을 이용하는 것이다. @RequestParam을 사용하면 ?id={id}와 같은 요청 매개변수로 넘어오는 값을 변수로 받을 수 있다.
@GetMapping("/testRequestBody")
public String testControllerWithRequestBody(@RequestBody TestRequestDTO testRequestDTO) {
return "Hello World! ID " + testRequestDTO.getId()
+ "Message : " + testRequestDTO.getMessgae();
}
@RequestBody를 사용하는 방법도 있다. @RequestBody는 보통 반환하고자 하는 리소스가 복잡할 때 사용된다. 예를 들어, String이나 int 같은 기본 자료형이 아닌, 객체와 같이 복잡한 자료형을 요청에 통째로 보내고 싶은 경우에 사용한다.
@RequestBody는 요청 바디로 전달된 JSON 데이터를 TestRequestBodyDTO 객체로 변환해 가져오라는 뜻이다. 즉, 클라이언트는 요청 바디에 JSON 형태의 문자열을 포함해 서버로 보낸다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
* @since 4.0.1
*/
@AliasFor(annotation = Controller.class)
String value() default "";
}
@RestController는 내부적으로 두 어노테이션의 조합으로 구성되어 있다: @Controller와 @ResponseBody.
- @Controller: 스프링이 이 클래스의 객체를 생성하고, 다른 객체들과의 의존성을 자동으로 연결한다는 의미이다.
- @ResponseBody: 이 클래스의 메서드가 리턴하는 값이 웹 서비스의 ResponseBody로 사용된다는 뜻이다.
즉, 메서드가 값을 리턴하면, 스프링은 리턴된 객체를 JSON 형태로 변환하고, 이를 HttpResponse에 담아 클라이언트에 반환한다.
스프링이 객체를 JSON으로 변환하거나, 네트워크를 통해 전달하거나 저장할 수 있도록 변환하는 과정을 **직렬화(Serialization)**라고 한다. 반대로, JSON과 같은 데이터를 객체로 변환하는 과정을 **역직렬화(Deserialization)**라고 한다.
@GetMapping("/testResponseBody")
public ResponseDTO<?> testControllerResponseBody() {
List<String> list = new ArrayList<>();
list.add("\"Hello World! I'm ResponseBody");
ResponseDTO<String> response = ResponseDTO.<String>builder().data(list).build();
return response;
}
ResponseDTO를 리턴하는 컨트롤러이다.
{
"error": null;
"data" : [
"Hello World! I'm ResponseBody"
]
}
컴파일한 후 localhost8080/test/testResponseBody를 실행시키면 위와 같은 JSON이 리턴된다.
@GetMapping("/testResponseEntity")
public ResponseEntity<?> testControllerResponseEntity() {
List<String> list = new ArrayList<>();
list.add("Hello World! I'm ResponseBody. And you got 400!");
ResponseDTO<String> response = ResponseDTO.<String>builder()
.data(list)
.build();
return ResponseEntity.badRequest().body(response);
}
ResponseEntity는 HTTP 응답의 바디뿐만 아니라, status나 header와 같은 여러 매개변수를 조작하고 싶을 때 사용한다.
ResponseEntity를 리턴하는 것과 ResponseDTO를 리턴하는 경우, 리턴된 body에는 차이가 없다. 하지만 ResponseEntity를 사용하면 헤더와 HTTP Status를 조작할 수 있다는 점이 다르다는 것을 기억하자.
'React.js, 스프링 부트, AWS로 배우는 웹 개발 101' 카테고리의 다른 글
[TIL] 25/01/29, 퍼시스턴스 레이어 : 스프링 데이터 JPA (0) | 2025.01.29 |
---|---|
[TIL] 25/01/28, Service Layer : Business Logic (0) | 2025.01.29 |
[TIL] 25/01/26, 백엔드 서비스 아키텍처 (0) | 2025.01.26 |
[TIL] 25/01/25, build.gradle 속성 (0) | 2025.01.25 |
[TIL] 25/01/21, 웹 서버 기술 (0) | 2025.01.21 |