Just Do IT!

[Spring] ResponseEntity란? 본문

개발 공부/Spring

[Spring] ResponseEntity란?

MOON달 2024. 8. 13. 17:09
728x90
반응형

수업 실습 중에 파일 업로드와 다운로드 기능을 하고 있었다.

다운로드 기능 구현하면서 ResponseEntity라는 새로운 객체를 배웠는데, 뭔지 잘 모르겠어서 블로그에 정리해보려고 한다.

 

HTTP(HyperText Transport Protocol)

웹서비스에서 보내는 요청 및 데이터의 형식 Client 와 Server 사이에 요청과 응답을 처리하기 위한 규약이다.

HTTP 요청의 세 가지 요소

  1. Start Line
    • method, URL, 그리고 version으로 이루어져 있다. 서버에서 요청을 받아들이는 첫 줄
  2. Headers
    • 요청에 대한 접속 운영체제, 브라우저, 인증 정보와 같은 부가적인 정보를 담고 있다
  3. Body
    • 요청과 관련된 json, html과 같은 구체적 내용을 포함한다.

HTTP 응답

  1. Status Line
    • HTTP 버전과 헤딩 요청에 대한 처리의 상태를 나타낸다. 200, 404 같은 숫자 코드로 나타낸다.
  2. Headers
  3. 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

 

728x90