Just Do IT!
[Spring] ResponseEntity란? 본문
수업 실습 중에 파일 업로드와 다운로드 기능을 하고 있었다.
다운로드 기능 구현하면서 ResponseEntity라는 새로운 객체를 배웠는데, 뭔지 잘 모르겠어서 블로그에 정리해보려고 한다.
HTTP(HyperText Transport Protocol)
웹서비스에서 보내는 요청 및 데이터의 형식 Client 와 Server 사이에 요청과 응답을 처리하기 위한 규약이다.
HTTP 요청의 세 가지 요소
- Start Line
- method, URL, 그리고 version으로 이루어져 있다. 서버에서 요청을 받아들이는 첫 줄
- Headers
- 요청에 대한 접속 운영체제, 브라우저, 인증 정보와 같은 부가적인 정보를 담고 있다
- Body
- 요청과 관련된 json, html과 같은 구체적 내용을 포함한다.
HTTP 응답
- Status Line
- HTTP 버전과 헤딩 요청에 대한 처리의 상태를 나타낸다. 200, 404 같은 숫자 코드로 나타낸다.
- Headers
- Body
Spring 에서도 마찬가지로 HTTP 에 맞게 데이터를 송수신해야 한다.
Spring에서는 200, 404 등 각각의 응답 상태 코드 뿐만 아니라 Body에 들어갈 내용도 넣어주어야 한다.
데이터를 받아와서 자동으로 구성해주는 것이 바로 @ResponseBody와 ResponseEntity이다.
규격에 맞는 HTTP 응답을 생성하기 위해서는 ResponseEntity를 사용한다.
@ResponseBody
- HTTP 규격에 맞는 응답을 만들어주기 위한 Annotation HTTP 요청을 객체로 변환하거나, 객체를 응답으로 변환하는 HttpMessageConverter 를 사용한다.
- HTTPMessageConverter 는 해당 Annotation 이 붙은 대상을 response body 에 직렬화를 하는 방식으로 작동된다.
- Controller 에서 반환할 객체나 Method 에 @ResponseBody 를 붙히는 것만으로 HTTP 규격에 맞는 값을 반환할 수 있다.
- 단점은, HTTP 규격 구성 요소 중 하나인 Header 에 대해서 유연하게 설정을 할 수 없다는 점이다.
- Status도 메서드 밖에서 Annatation을 사용하여 따로 설정을 해주어야 한다.
- @ResponseBody 만 사용시에 별도의 뷰를 제공하지 않고, 데이터만 전송하는 형식이기 때문이다.
이를 해결하는 것이 ResponseEntity라는 객체이다
ResponseEntity
- 응답으로 변환될 정보를 모두 담은 요소들을 객체로 만들어서 반환해준다.
- 객체의 구성요소에서 HttpMessageConverter는 응답이 되는 본문을 처리해주고, RESTTemplate에 나머지 구성 요소인 Status를 넘겨준다.
- ResponseEntity.status(상태코드).body(객체) ResponseEntity.ok() -> 200(ok) 응답 코드와 body에 데이터를 추가할 경우에는 ok 메소드를 이용할 수 있다
[예시] 이미지 파일 다운로드 하기
실습에서 진행했던 건데, 위 ResponseEntity를 사용해서 이미지 파일 다운로드를 진행했기 때문에 간단히 예시를 적으면서 이해보자. (to me, from me...)
BoardController.java
package com.board.controller;
@Slf4j
@Controller // 컨트롤러 지정 annotaion
@RequestMapping("/board") // 중복되는 url 지정
public class BoardController {
@Autowired // 서비스 빈(Bean) 자동 주입
private BoardService bs;
...
// 다운로드
@RequestMapping("/download")
public ResponseEntity<Resource> downloadFile(@RequestParam("id") int id, @RequestParam("boardId") int boardId)
throws Exception {
FileDTO fileDTO = bs.selectFilterByIds(id, boardId);
String fileName = fileDTO.getOriginFileName();
UrlResource resource;
try {
// 경로에 있는 file resource를 가져오기
resource = new UrlResource("file:" + fileDTO.getStoredFilePath());
} catch (Exception e) {
throw new Exception("파일 다운로드 에러");
}
// 응답 객체 반환
// ok하면 200번대로 이동
// header(응답에 대한 설멍), body 담아주기
// 한글명도 다운로드받아야 한다.
String encodedFileName = UriUtils.encode(fileName, StandardCharsets.UTF_8);
// contents disposition: attachment; filename="" 이런 형식으로 넣어줘야 한다
String contentDispositionValue = "attachment; filename=\"" + encodedFileName + "\"";
// HttpHeaders.CONTENT_DISPOSITION를 쓰면 자동으로 disposition임을 알려준다
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, contentDispositionValue).body(resource);
}
...
}
컨트롤러에 ResponsEntity로 Resource를 받아서 다운로드를 진행하는 걸 알 수 있다.
UrlResource를 사용하여 파일 경로를 기반으로 파일 리소스를 가져온다.
추가로, 파일 이름에 한글이 포함될 경우, UriUtils.encode를 사용하여 파일 이름을 UTF-8로 인코딩한다.
원래 이미지를 저장하려고 할때
contents dispositon: attachment; filename="" 이런 형식으로 전송된다.
- Contents-Disposition 헤더는 HTTP 응답에서 브라우저가 콘텐츠를 어떻게 처리해야 하는지를 지시하는데 사용한다.
- 지금 이렇게 파일을 다운로드하거나, 파일을 올릴 때 이 헤더를 사용한다.
- attachment는 브라우저에게 콘텐츠를 다운로드하도록 지시한다.
- 즉, 브라우저는 콘텐츠를 직접 페이지에 표시하는 대신 사용자의 파일시스템에 저장하게 한다. 이를 통해 사용자는 파일을 다운로드하여 로컬에서 열 수 있다.
- filename="..." 부분은 다운로드할 파일의 이름을 지정한다.
- 이 값은 브라우저가 다운로드할 파일에 기본적으로 제공할 파일 이름을 설정하는 데 사용한다.
이 부분을 header와 body에 담아야 제대로 요청을 보낼 수가 있다.
이럴 때 ResponseEntity를 사용하는 것이다.
ResponseEntity.ok()를 사용하여 HTTP 200 OK 상태 코드와 함께, Content-Dispositon 헤더를 포함한 응답을 반환하고,
그 파일 리소스는 응답의 본문으로 포함된다.
간단해보이지만 아직 잘 모르는 부분이 있어서 풀어서 정리해봤다.
@ResponseBody는 적용해보지 않았지만, 나중에 조금 더 배우면서 어떤 차이점이 있는지 알아봐야겠다.
참고한 블로그
https://velog.io/@injoon2019/%EC%8A%A4%ED%94%84%EB%A7%81-ResponseEntity
[스프링] ResponseEntity
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.htmlExtension of HttpEntity that adds an
velog.io
https://tecoble.techcourse.co.kr/post/2021-05-10-response-entity/
ResponseEntity - Spring Boot에서 Response를 만들자
웹 서비스에서는 많은 정보를 송수신하게 됩니다. 각각의 다른 웹 서비스들이 대화하려면, 서로 정해진 약속에 맞게 데이터를 가공해서 보내야합니다. 보내는 요청 및 데이터의 형식을 우리는 H
tecoble.techcourse.co.kr
'개발 공부 > Spring' 카테고리의 다른 글
[JPA] @EnableJpaAuditing 사용하기 (0) | 2024.08.22 |
---|---|
SpringBoot, JPA 구조 이해하기 (0) | 2024.08.21 |
[Spring] 외부의 정적 리소스 요청 시 WebMvcConfigurer 사용하기 (0) | 2024.08.20 |
SpringBoot에서 Log4jdbc 사용하기 (0) | 2024.08.12 |
[Spring] DB Connection Pool과 Hikari CP란? (0) | 2024.08.12 |