[데브코스] Spring Rest API 2
Updated: Categories: TILW5D4 - 렌더링방식 / ResponseEntity / CORS에 대해 알아보자!
렌더링 방식
MPA (Multiple Page Application)
- 여러개의 페이지로 구성된 APP. 전통적인 방식
SSR
(Server Side Rendering) 방식으로 렌더링- 사용자 데이터는 서버에서 세션으로 처리
- 하나의 URL에 하나의 페이지를 매핑
SPA (Single Page Application)
- 한 개의 페이지로 구성된 APP
CSR
(Client Side Rendering) 방식으로 렌더링함- 사용자 데이터는 브라우저의
local storage
를 함께 활용해 세션 의존도를 줄임 - 히스토리 API + DOM 조작을 통해 새로고침 없이 렌더링
Proxy
- if) React에서 프론트를 서빙하는 웹서버가 있다 (3000번 포트로)
- 만약 프론트 부분에 백엔드로 요청을 보내는 코드를 작성하게 되면 CORS 에러 발생
- 프론트 코드에서 해당 주소를 웹서버로 넘기고 웹서버가 백엔드 서버로 요청해야함 (프록시 적용)
ResponseEntity
- HTTP의 헤더나 상태코드를 처리하기 위한 자료형
- 응답 컨트롤러의 리턴값으로 주고 다양한 메소드를 통해 HTTP 타입을 표현 가능
@GetMapping(".../{데이터}")
@ResponseBody
public ResponseEntity<제네릭> 메소드(@PathVariable(데이터) ...) {
ResponseEntity.ok(...);
ResponseEntity.status(...).body(...);
ResponseEntity.notFound().build();
}
CORS (Cross Origin Resource Sharing)
- 동일한 출처의 리소스에만 접근이 가능하도록 하는 규칙
프로토콜
,호스트
,포트
가 동일하면 Same Origin으로 본다.- 이 블로그에 매우 자세한 설명이 나와있음
단순요청
GET
,HEAD
,POST
메소드 요청- 유저 에이전트가 자동으로 설정한 헤더
Accept
Accept-Language
Content-Language
Content-Type
- Content-Type 헤더는 아래 값들만 허용
application/x-www-form-urlencoded
multipart/form-data
text/plain
예비요청 (Preflight)
- 단순 요청이 아닌경우엔 예비요청을 먼저 보낸다
- 서버가 예비요청을 받고
Access-Control-Allow-Origin
헤더를 포함한 응답을 브라우저로 보내줘야 비로소 본 요청이 이루어짐. - 서버가 요청에 승인을 해주는 것이므로 서버측에서 CORS 모듈을 사용한다
Spring CORS
CORS 설정 - Servlet Context
- Servlet Context Config에서
addCorsMappings
메소드를 사용해 CORS 허용을 해줄 수 있다. - 허용할 Origin, URL, 메소드를 정할 수 있음
@Override
public void addCorsMappings(CorsRegistry registry) {
// api/ 하위로 들어오는 모든 origin의 GET 요청만 허용한다
registry.addMapping("/api/**")
.allowedMethods("GET")
.allowedOrigins("*");
}
CORS 설정 - Annotation
- 컨트롤러 클래스나 포함 메소드에
@CrossOrigin
달아 기능별로 설정도 가능함
@CrossOrigin(origins=" ", methods = RequestMethod.GET)
[ 컨트롤러 or 메소드 ]
DTO
- Request가 오면 메시지 컨버터로 도메인에 맞는 형식으로 변환하여 파라미터로 받을 수 있다.
- 이때 도메인 형식을 정의해주는 것이 바로
DTO
인데 보통 Record 클래스로 작성한다- 도메인을 수정하지 않고 DTO를 만들어주는 것이 좋음
- Request -> 메시지컨버터(
@RequestBody
) ->DTO
-> 사용
Request를 DTO로 변환 후 응답하는 메소드
@PostMapping(".../{데이터}}")
@ResponseBody
public 메소드(@PathVariable("데이터") ..., @RequestBody DTO dto) {
dto.value();
...
}
DTO - Record 클래스 정의
public record DTO(
Value value,
...
) {
// value -> dto
static DTO of(Value value) {
return new CustomerDto(
value.getValue(),
...
);
}
// dto -> customer
// 생성의 책임이 service에 있을지 dto에 있을지는 고민
static Value to(DTO dto) {
return new Customer(
dto.value(),
...
);
}
}