Spring Boot 어플리케이션에서 @RestController를 이용해 클라이언트에게 데이터를 반환하는 방법은 다양하다.
이번 글에서는 주요 응답 방식 4가지를 소개한다.
1. JSON 응답 (DTO 반환)
- 가장 일반적인 REST API 응답 방식
- 데이터를 구조화하기 위해 DTO(Data Transfer Object)를 사용함
- Spring Boot에서는 @RestController 어노테이션을 적용하면 Return 객체(DTO)를 Jackson 라이브러리가 JSON 형식으로 직렬화한다.
- JSON 응답 방식은 클라이언트가 응답 데이터를 쉽게 파싱할 수 있도록 도와주며, 계층화된 구조를 표현하기에 용이함
@RestController
@RequestMapping("/api")
public class JsonResponseController {
// DTO 클래스 예제
public static class MyDTO {
private String name;
private int value;
public MyDTO(String name, int value) {
this.name = name;
this.value = value;
}
// getter, setter 생략
public String getName() { return name; }
public int getValue() { return value; }
}
@GetMapping("/json")
public ResponseEntity<MyDTO> getJsonResponse() {
MyDTO dto = new MyDTO("example", 123);
return ResponseEntity.ok(dto);
}
}
2. 텍스트나 Integer 같은 기본형 응답
- 경우에 따라 단순 문자열, 숫자 등 기본형 데이터를 반환할 필요가 있다.
- Spring Boot에서는 @RestController 어노테이션을 적용하면 Return 객체(DTO)를 Jackson 라이브러리가 JSON 형식으로 직렬화한다.
- 단, 이때 반환되는 JSON은 키-값 구조가 아니라 단순 JSON 리터럴로 표현된다.
- 예를 들어, ResponseEntity.ok(42)를 반환하면 최종적으로 클라이언트에는 JSON 숫자 리터럴 42가 전달된다.
@RestController
@RequestMapping("/api/basic")
public class BasicResponseController {
@GetMapping("/text")
public ResponseEntity<String> getTextResponse() {
return ResponseEntity.ok("This is a plain text response.");
}
@GetMapping("/integer")
public ResponseEntity<Integer> getIntegerResponse() {
return ResponseEntity.ok(42);
}
@GetMapping("/boolean")
public ResponseEntity<Boolean> getBooleanResponse() {
return ResponseEntity.ok(true);
}
@GetMapping("/double")
public ResponseEntity<Double> getDoubleResponse() {
return ResponseEntity.ok(3.14159);
}
@GetMapping("/long")
public ResponseEntity<Long> getLongResponse() {
return ResponseEntity.ok(123456789L);
}
@GetMapping("/float")
public ResponseEntity<Float> getFloatResponse() {
return ResponseEntity.ok(2.71828f);
}
}
3. 파일/이미지 응답 (byte[] 반환)
- 파일이나 이미지를 클라이언트에게 전달할 때는 바이너리 데이터 형태로 반환해야 한다.
- 파일의 내용을 byte[]로 읽어 ResponseEntity에 담아 전송하면, 클라이언트는 이를 그대로 파일이나 이미지로 처리할 수 있다.
@RestController
@RequestMapping("/api")
public class FileByteResponseController {
@GetMapping("/download-image-bytes")
public ResponseEntity<byte[]> downloadImageBytes() throws IOException {
// 예시: 로컬 파일 시스템의 이미지 파일 읽기
Path imagePath = Paths.get("path/to/your/image.png");
byte[] imageBytes = Files.readAllBytes(imagePath);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentDisposition(ContentDisposition.builder("attachment")
.filename("image.png")
.build());
return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
}
}
4. 대용량 파일 응답 (Resource 기반 스트리밍 방식)
- 대용량 파일, 특히 동영상이나 음악 파일의 경우 전체 데이터를 한 번에 메모리에 로드하는 방식(byte[] 방식)은 서버의 메모리 부담이 크고, 클라이언트에서의 응답 대기시간도 길어진다.
- Resource 기반 스트리밍 방식은 파일 데이터를 청크 단위로 읽어 HTTP 응답으로 전송하므로, 메모리에 전체 파일을 올리지 않고도 데이터를 전송할 수 있다.
- 참고로 Resource 는 인터페이스이므로 return을 할 때는 Resource 인터페이스를 구현한 객체를 사용해야 한다.
/*
아래 예제 코드는 동영상 파일 전체를 FileSystemResource를 통해 스트리밍하는 기본적인 방식
즉 전체 동영상 파일이 HTTP 응답 본문으로 전달되는 기본적인 방식이다.
실제 동영상 스트리밍 서비스에서는 HTTP Range 요청 처리나
206 Partial Content 응답 기능 같은 추가 기능 구현이 필요하다.
*/
@RestController
@RequestMapping("/api")
public class VideoStreamController {
@GetMapping("/download-video-stream")
public ResponseEntity<Resource> downloadVideoStream() {
// 동영상 파일 경로 지정 (서버 내 실제 파일 경로)
File videoFile = new File("path/to/your/video.mp4");
if (!videoFile.exists()) {
return ResponseEntity.notFound().build();
}
// FileSystemResource를 사용하여 파일 리소스를 생성
Resource resource = new FileSystemResource(videoFile);
HttpHeaders headers = new HttpHeaders();
// 동영상 파일의 MIME 타입 설정 (여기서는 mp4)
headers.setContentType(MediaType.parseMediaType("video/mp4"));
// 브라우저에서 바로 재생할 수 있도록 inline으로 설정
headers.setContentDisposition(ContentDisposition.inline()
.filename(videoFile.getName())
.build());
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
}
출처 : https://spring.io/guides/gs/rest-service https://www.baeldung.com/spring-controller-return-image-file |
'Spring' 카테고리의 다른 글
Spring IoC Container(Spring Container) (0) | 2024.07.17 |
---|---|
Bean 스코프 (0) | 2024.07.16 |
Spring, Spring Boot 차이 (0) | 2024.07.14 |
@Transactional 동작 방식 (0) | 2024.07.02 |
JDK Dynamic Proxy vs CGLIB Proxy (0) | 2024.07.02 |