클라이언트에게 제공할 정보는 웹에서 리소스로 공개. HTTP 프로토콜을 사용해서 리소스에 접근할 수 있다는 것을 의미.
리소스에 리소스를 고유하게 식별할 수 있는 URI를 할당.
리소스에 대한 CRUD 조작은 HTTP메서드 (GET, POST, PUT, DELETE)를 용도에 맞게 잘 나눠서 사용.
GET : URI에 지정된 리소스를 가져온다
POST : 리소스를 생성하고 생성된 리소스에 접근할 수 있는 URI를 받아온다.
PUT : URI에 지정한 리소스를 생성하거나 갱신한다.
DELETE : URI에 지정한 리소스를 삭제한다.
리소스 포멧으로는 일기 쉽고 데이터 구조를 잘 표현하는 JSON이나 XML과 같은 포맷 사용.
1xx : 요청을 접수하고 처리를 계속하고 있음을 알리는 응답 코드
2xx : 요청을 접수하고 처리가 완료됐음을 알리는 응답 코드
3xx : 요청을 완료하기 위해 추가적인 처리(리다이렉트 등)가 필요함을 알리는 응답 코드
4xx : 요청에 결함이 있으므로 처리를 중단함을 알리는 응답 코드
5xx : 요청에 대해 서버가 제대로 처리하지 못함을 알리는 응답 코드
애플리케이션 서버가 HTTP 세션과 같은 공유 메모리를 사용하지 않고 요청 데이터만으로 리소스를 조작.
리소스에는 관련된 다른 리소스나 서브 리소스에 대한 하이퍼미디어 링크(URI)를 포함할 수 있다.
프레임워크 아키텍처
화면으로 응답하는 웹 애플리케이션과 다른점 두가지
스프링 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 설정은 필요 없다.
@EnableWebMvc나 <mvc:annotation-driven> 요소를 사용하면 스프링이 제공하는 HttpMessageConverter가 자동으로 적용된다.
WebMvcConfigurerAdapter 클래스를 확장하는 클래스에 메서드 오버라이드.
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, mappingJackson2HttpMessageConverter())l
}
오버라이드한 extendMessageConverters 메서드에서 인수로 받은 리스트의 첫 번째 요소에 임의의 HttpMessageConverter를 추가한다.
컨트롤러에서 구현하는 주요 처리
선언형 : 요청 매핑, 요청 데이터(리소스) 취득, 입력값 검사 수행
프로그래밍형 : 비즈니스 로직 호출, 응답 데이터(리소스) 반환
CORS : Cross-Origin Resource Sharing
웹 페이지에서 AJAX를 사용할 때 다른 도메인의 서버 리소스에 접근하기 위한 메커니즘.
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 api 호출 시 사용하는 클래스.
RestTemplate restTemplate = new RestTemplate();
GitHubUser resource = restTemplate.getForObject(/*uri*/, GitHubUser.class, "spring-projects");
spring-web dependency 추가.
JSON 사용 시 jackson-databind 추가.
RestTemplate DI 컨테이너에 등록
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
사용 시 RestOperations 인터페이스 타입으로 주입 받아 결합도를 낮추는 것이 좋다.
@Autowired
RestOperations restOperations;