6장 RESTful 웹 서비스 개발

Jasik·2022년 1월 13일
0

ROA(Resource Oriented Architecture)

웹의 리소스로 공개

클라이언트에게 제공할 정보는 웹에서 리소스로 공개. HTTP 프로토콜을 사용해서 리소스에 접근할 수 있다는 것을 의미.

URI를 통한 리소스 식별

리소스에 리소스를 고유하게 식별할 수 있는 URI를 할당.

HTTP 메서드를 통한 리소스의 조작

리소스에 대한 CRUD 조작은 HTTP메서드 (GET, POST, PUT, DELETE)를 용도에 맞게 잘 나눠서 사용.
GET : URI에 지정된 리소스를 가져온다
POST : 리소스를 생성하고 생성된 리소스에 접근할 수 있는 URI를 받아온다.
PUT : URI에 지정한 리소스를 생성하거나 갱신한다.
DELETE : URI에 지정한 리소스를 삭제한다.

적절한 포맷을 사용

리소스 포멧으로는 일기 쉽고 데이터 구조를 잘 표현하는 JSON이나 XML과 같은 포맷 사용.

적절한 HTTP 상태 코드를 사용

1xx : 요청을 접수하고 처리를 계속하고 있음을 알리는 응답 코드
2xx : 요청을 접수하고 처리가 완료됐음을 알리는 응답 코드
3xx : 요청을 완료하기 위해 추가적인 처리(리다이렉트 등)가 필요함을 알리는 응답 코드
4xx : 요청에 결함이 있으므로 처리를 중단함을 알리는 응답 코드
5xx : 요청에 대해 서버가 제대로 처리하지 못함을 알리는 응답 코드

클라이언트와 서버 간의 무상태 통신

애플리케이션 서버가 HTTP 세션과 같은 공유 메모리를 사용하지 않고 요청 데이터만으로 리소스를 조작.

연관된 리소스에 대한 링크

리소스에는 관련된 다른 리소스나 서브 리소스에 대한 하이퍼미디어 링크(URI)를 포함할 수 있다.

프레임워크 아키텍처
화면으로 응답하는 웹 애플리케이션과 다른점 두가지

  • 응답 본문을 생성하기 위한 뷰를 사용하지 않는다
  • '요청 본문 해석'과 '응답 본문 해석'은 HttpMessageConverter라는 컴포넌트에서 처리.

프레임워크의 아키텍처

HttpMessageConverter 활용

스프링 MVC는 HttpMessageConverter를 사용해 요청 본문을 자바 객체로 변환하고 자바 객체를 응답 본문으로 변환한다.

HttpMessageConverter 구현체 중 하나
MappingJackson2HttpMessageConverter : FasterXML Jackson Databind를 이용한 본문(JSON 형식의 미디어 타입) <-> 임의의 자바빈즈 변환용 클래스

리소스 클래스

리소스를 표현하는 자바 클래스를 리소스 클래스라 부른다. 여기서는 Entity 와 같은 도메인 객체와 별개로 다른 클래스를 만들어서 쓴다고 전제한다.

애플리케이션 설정

라이브러리 설정

HttpMessageConverter의 구현 클래스 중 다른 라이브러리에 의존하는 것들이 있는데, 그런 경우 반드시 해당 라이브러리가 클래스패스 상에 있어야 한다.

ex)
리소스 형식으로 JSON을 사용하고, 'FasterXML Jackson Databind'를 의존 라이브러리에 추가.
pom.xml

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

프런트 컨트롤러 설정

Rest api 개발 시에는 ViewResolver 설정은 필요 없다.

HttpMessageConverter 적용

@EnableWebMvc나 <mvc:annotation-driven> 요소를 사용하면 스프링이 제공하는 HttpMessageConverter가 자동으로 적용된다.

HttpMessageConverter 커스터마이징

WebMvcConfigurerAdapter 클래스를 확장하는 클래스에 메서드 오버라이드.

@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(0, mappingJackson2HttpMessageConverter())l
}

오버라이드한 extendMessageConverters 메서드에서 인수로 받은 리스트의 첫 번째 요소에 임의의 HttpMessageConverter를 추가한다.

@RestController 구현

컨트롤러에서 구현하는 주요 처리
선언형 : 요청 매핑, 요청 데이터(리소스) 취득, 입력값 검사 수행
프로그래밍형 : 비즈니스 로직 호출, 응답 데이터(리소스) 반환

화면으로 응답하는 웹 애플리케이션 컨트롤러와의 차이점

  • 요청 데이터를 요청 본문 형태로 받아낼 인수에 @RequestBody를 붙인다
  • 응답할 데이터를 반환하는데 그 결과가 응답 본문 형태가 되도록 메서드에 @RequestBody를 붙인다. (@RestController로 생략 가능. @RestController는 @Controller와 @ResponseBody를 합친 애너테이션)
  • 입력값 검사 결과는 BindingResult로 받지 않고 예외로 받아 처리한다.

CORS 지원

CORS : Cross-Origin Resource Sharing
웹 페이지에서 AJAX를 사용할 때 다른 도메인의 서버 리소스에 접근하기 위한 메커니즘.

CORS를 지원하는 리소스를 지정하는 두 가지 방법

  • 빈을 정의하는 방식으로 애플리케이션 단위로 설정
  • @CrossOrigin 을 사용해 컨트롤러와 핸들러 메서드 단위로 설정

애플리케이션 단위로 CORS 설정

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**");
    }
}

위 설정을 통해 "/api/**"에 해당하는 리소스들에 대한 응답으로 다음과 같은 CORS 제어용 응답 헤더가 설정된다.

Access-Control-Allow-Origin: http://example.com:8080
Access-Control-Allow-Credentials: true
Vary: Origin

예외 처리

오류 응답 JSON 예

{
    "message": "Not Found",
    "documentation_url": "http://developer.github.com/v3"
}
@ControllerAdvice
public class ApiExceptionHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ApiError apiError = new ApiError(ex.getMessage());
        return super.handleExceptionInternal(ex, apiError, headers, status, request);
    }
}

사용자 정의 예외의 처리

애플리케이션을 개발할 때는 요구사항에 맞는 애플리케이션 전용 예외 클래스를 만들어서 쓰는 것이 일반적.

@ExceptionHandler
public ResponseEntity<Object> handleBookNotFoundException(BookNotFoundException ex, WebRequest resuest) {
    return handleExceptionInternal(ex, null, null, HttpStatus.NOT_FOUND, request);
}

REST 클라이언트 구현

RestTemplate

REST api 호출 시 사용하는 클래스.

RestTemplate restTemplate = new RestTemplate();

GitHubUser resource = restTemplate.getForObject(/*uri*/, GitHubUser.class, "spring-projects");

RestTemplate 설정

spring-web dependency 추가.
JSON 사용 시 jackson-databind 추가.

RestTemplate DI 컨테이너에 등록

@Bean
RestTemplate restTemplate() {
    return new RestTemplate();
}

사용 시 RestOperations 인터페이스 타입으로 주입 받아 결합도를 낮추는 것이 좋다.

@Autowired
RestOperations restOperations;
profile
가자~

0개의 댓글