본문 바로가기
Spring

Spring Controller를 REST 방식으로 변화 - Rest API

by khds 2022. 2. 23.

처음 spring을 공부하고 JSP를 이용하여 프로젝트를 진행했을 때 @Controller를 이용하여 요청이 오면 jsp페이지를 보여주는 방식으로 프로젝트를 진행하였었다. 하지만 이는 옛날 방식이며 요즘 자주 사용하는 방식은 @RestController을 이용한다고 한다. 

 

모바일 시대가 되면서 서버의 데이터를 소비하는 주체가 '브라우저'라는 특정한 애플리케이션에서 앱이나 웹이 서버에서 제공하는 데이터를 소비하게 되었다.  즉, 과거에는 브라우저라는 하나의 대상만을 상대로 HTML이라는 형태만 전달하면 됐었고, 이러한 방식이 @Controller을 이용한 방식이다. 하지만 웹이나 앱은 자신만의 방식으로 화면을 보여주게 되므로 하나의 HTML을 전달하는 방식은 좋은 방식이 아닐 것이다. 앱이나 웹은 각자의 맞게 화면을 구성하고 그것을 위한 순수한 데이터만을 서버로부터 가져오면 되는 것이다.  @RestController을 사용하는 방식은 Rest 방식으로 요청을 처리하는 것이고 순수한 데이터를 반환하는 것이다.

 

REST는 'Representational State Transfer'의 약어로 하나의 URI는 하나의 고유한 리소스(Resource)를 대표하도록 설계된다는 개념에 전송방식을 결합해서 원하는 작업을 지정한다. 예를들어 '/board/123'은 게시물 중에서 123번이라는 고유한 의미를 가지도록 설계하고, 이에 대한 처리는 GET, POST 방식과 같이 추가적인 정보를 통해서 결정한다.

따라서 REST 방식은

URI  +  GET/POST/PUT/DELETE/...     

라고 생각할 수 있다.

URL 과 URI에 대해서 궁금하다면 https://khdscor.tistory.com/42를 참고하길 바란다.

 

URL과 URI 의 차이

웹 개발을 하다 보면 URL와 URI를 자주 듣는다. URL을 기본으로 많이 들어왔기에 'URI도 URL이다'라고 생각을 하는 경우가 많았다. 엄밀하게 말하자면 URL은 URI의 하위 개념이기에 혼용해도 무방하다.

khdscor.tistory.com

 

REST 방식의 데이터 교환에서 가장 특이한 점은 GET/POST 외에 다양한 방식으로 데이터를 전달한다는 점이다. HTTP의 전송방식은 아래와 같은 형태로 사용된다.

작업 전송방식
Create POST
Read GET
Update PUT
Delete DELETE

 

 

REST 방식은 URI와 같이 결합하므로 member라는 자원을 대상으로 전송방식을 결합하면 다음과 같은 형태가 된다. 

작업 전송방식 URI
Create POST /members/new
Read GET /members/{Id}
Update PUT /members/{Id} + body (json 데이터 등)
Delete DELETE /members/{Id}

 

 

 

REST 방식으로 Controller로 진행할 때 간단하게 몇 가지에 대해서 설명해 보겠다.

1. @RestController

@RestController는 Controller가 REST 방식을 처리하기 위한 것이다. 기존의 Controller은 Model에 데이터를 담아서 JSP 등과 같은 뷰로 전달하는 방식이었다. 하지만 @RestController은 Controller의 리턴 타입을 다르게 순수한 데이터로서 다르게 처리한다는 것이다. 이는 @Controller와 메서드 선언부에 @ResponseBody를 이용해서 동일한 결과를 만들 수도 있다. 순수한 데이터는 사용자가 정의한 클래스 타입을 사용할 수 있고, 이를 JSON이나 XML로 자동으로 처리할 수 있다. 

 

참고로 JSON은 'JavaScript Object Notation'의 약어로 구조가 있는 데이터를 '{ }'로 묶고 '키'와 '값'으로 구성하는 경량의 데이터 포맷이다. 프로그래밍 언어에서 말하는 객체들의 구조는'{ }'를 이용해서 아래와 같이 표현할 수 있다.

{
    "이름": "홍길동",
    "나이": "20",
    "성별": "남자"
}

 

 

구조를 표현한 문자열은 프로그래밍 언어에 관계 없이 사용할 수 있기에 XML과 더불어 가장 많이 사용되는 데이터의 표현 방식이다. 아래는 정의한 클래스 ArticleSummaryResponse의 LIst를 반환하는 예시이다. 

@RestController
@RequestMapping("/articles")
public class FindArticleController {

...

@GetMapping("/public")
public List<ArticleSummaryResponse> findPublicMapArticles(ArticleRangeRequest request) {
    List<ArticleSummaryResponse> publicMapArticles = findArticleService.findPublicMapArticles(
        request.getLatitude(), request.getLatitudeRange(),request.getLongitude(), request.getLongitudeRange()
    ); // List<ArticleSummaryResponse>를 가져온다
    return publicMapArticles;
}

...

 

findPublicMapArticles 메서드의 매개변수인 ArticleRangeRequest 타입의 request는 쿼리 스트링을 한 번에 ArticleRangeRequest 타입으로 받는다.(각각 받는다면 각각의 타입을 쓰거나 @RequestParam을 이용할 수 있다.)

 

 

2. ResponseEntity 타입

Rest  방식으로 호출하는 경우는 화면 자체가 아니라 데이터를 전송하는 방식으로 처리되기 때문에 데이터를 요청한 쪽에서는 정상적인 데이터인지 비정상적인 데이터인지를 구분할 수 있어야 한다. 이는 ResponseEntity로 데이터와 함께 HTTP 헤더의 상태 메시지 등을 같이 전달하는 용도로 사용한다. 

아래는 예시 코드이다.

 

@GetMapping("/public")
public ResponseEntity<List<ArticleSummaryResponse>> findPublicMapArticles(ArticleRangeRequest request) {
    List<ArticleSummaryResponse> publicMapArticles = findArticleService.findPublicMapArticles(
        request.getLatitude(), request.getLatitudeRange(),request.getLongitude(), request.getLongitudeRange()
    );
    return ResponseEntity.ok()
        .body(publicMapArticles);
}

 

ResponseEntity.ok() 를 통해 200의 status 값을 같이 보내는 것이다.

이밖에 created(201), No Content(204), Bad Request(400), Unauthorized(401), Not Found(404) 등이 있다.

 

3. @RequestBody

@RequestBody는 전달된 요청의 내용을 이용해서 해당 파라미터의 타입으로 변환을 요구한다. 일반적으로 Post 요청에서 사용되고 서버로 JSON타입으로 보내면 이를 원하는 타입으로 변환하기 위해서 @RequestBody를 사용하는 것이다. 

아래는 예시 코드이다. 

@PostMapping("/test")
public Test test(@RequestBody Test test){
    return test;
}

 

JSON 형태로 요청이 오면 이를 Test 객체에 필드에 각각 매핑하여 Test 타입을 받는 것이다. 

 

참고

코드로 배우는 스프링 웹 프로젝트 - 구멍가게 코딩단