백엔드 개발을 진행하다 보면, 이미지나 파일 같은 raw data 를 직접 return 해야 하는 경우가 발생합니다. 물론 download 기능을 구현할 때에도 마찬가지겠지만, 그 이외에도 이러한 기능이 필요한 경우가 간혹 있습니다.
이 post에는 sample 이 존재하지 않습니다. 필요 시 나중에 추가하도록 하겠습니다.
dependency 추가
API 를 작성할 것이므로 아래 dependency 를 추가합니다. 아마 대부분의 API서버에 이미 추가되어 있을 것입니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
implementation("org.springframework.boot:spring-boot-starter-web")
@ResponseBody
사용하기
가장 간단히 사용할 수 있는 것은 @ResponseBody
annotation 을 추가하는 것입니다.
@GetMapping("/get-text")
public @ResponseBody String getText() {
return "Hello world";
}
이렇게 하면, view 를 찾는 것 대신에 Hello World 라는 문자열 자체를 return 하게 됩니다.
@Controller
대신 @RestController
를 사용하는 Controller 를 구현하게 되면, 위 @ResponseBody
가 없어도 view를 찾지 않고 그대로 문자열을 return 합니다.
이미지 return 을 위한 produces
사용하기
이미지나 파일을 return 하는 데 있어서 byte array 를 return 하는 것이 쓰입니다.
@GetMapping(value = "/image")
public @ResponseBody byte[] getImage() throws IOException {
InputStream in = getClass()
.getResourceAsStream("/com/baeldung/produceimage/image.jpg");
return IOUtils.toByteArray(in);
}
이렇게 하면 이미지에 대한 정보가 아무것도 없기 때문에 client 에서는 이미지임을 알 수 없습니다. 이러한 문제를 방지하기 위해서, @GetMapping
annotation에 produces 값을 넣어줍니다.
@GetMapping(
value = "/get-image-with-media-type",
produces = MediaType.IMAGE_JPEG_VALUE
)
public @ResponseBody byte[] getImageWithMediaType() throws IOException {
InputStream in = getClass()
.getResourceAsStream("/com/baeldung/produceimage/image.jpg");
return IOUtils.toByteArray(in);
}
이렇게 produces 값에 MediaType.IMAGE_JPEG_VALUE
를 지정하면 return 되는 값을 이미지로 처리해야 함을 알려줄 수 있습니다.
이제, 브라우저는 이 return 값이 이미지임을 알고 이미지로 올바르게 처리해 줍니다.
Raw file 을 return 하기 위한 produces
produces
는 여러가지 값을 가질 수 있습니다. 전체 목록은 여기에 있습니다.
return 하고자 하는 타입에 맞게 적절한 값을 넣어주면 됩니다.
그래서, 만약 우리가 파일 자체를 return 하고 싶다면 APPLICATION_OCTET_STREAM_VALUE
를 사용합면 됩니다.
@GetMapping(
value = "/get-file",
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
)
public @ResponseBody byte[] getFile() throws IOException {
InputStream in = getClass()
.getResourceAsStream("/com/baeldung/produceimage/data.txt");
return IOUtils.toByteArray(in);
}
그렇지 않다면, Byte array 대신에 ByteArrayResource
를 사용해도 됩니다.
@GetMapping(
value = "/get-file-via-byte-array-resource",
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
)
public @ResponseBody Resource getFileViaByteArrayResource() throws IOException, URISyntaxException {
Path path = Paths.get(getClass().getResource("/com/baeldung/produceimage/data.txt").toURI());
ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));
return resource;
}
Resource
클래스는 Spring이 제공하는 높은 수준의 abstract class입니다. 이 클래스는 다양한 소스로부터 리소스를 다루는 데 도움을 줍니다.
InputStream 을 통한 Resource의 사용은 다음과 같은 이점이 있습니다.
- 리소스에 대한 추가적인 메타데이터를 제공한다.
- Spring 의 다른 abstract 들과 유연하게 연결지을 수 있다.
- mock 하기 쉽다.
Leave a comment