스프링부트에서 정적 파일인 이미지를 어떻게 보여주는지 다시한번 구글링해보았다.
여러가지 방법이 있었던것 같은데 나는 정적인 이미지 파일이니까 해당 파일이 있는 위치에서 바로 불러오고 싶었다.
그래서 한번 찾아보았다..
@GetMapping("/{imageName}")
public ResponseEntity<byte[]> getImage(@PathVariable String imageName) throws IOException {
// 여기서는 예를 들어 images 디렉토리에서 이미지를 로드합니다
Resource imgFile = new ClassPathResource("static/images/" + imageName);
InputStream in = imgFile.getInputStream();
byte[] imageBytes = StreamUtils.copyToByteArray(in);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG); // 이미지 타입에 따라 MediaType 설정
headers.setContentLength(imageBytes.length);
return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
}
이 코드를 사용하면 바로 해당 위치의 파일 바이트를 복사해서 보여주는 기능을 할 수 있다.!!
우선 위의 코드들을 상세히 살펴보도록 해보자.
@GetMapping("/{imageName}")
public ResponseEntity<byte[]> getImage(@PathVariable String imageName) throws IOException
위의 코드는 기본적인 선언문이다. 그럼 throws IOException 하는 이유가 무엇일까?
throws IOException를 사용하는 이유
위 코드에서 throws IOException을 선언하는 이유는 이미지 파일을 읽는 과정에서 발생할 수 있는 예외(오류)를 처리하기 위해서입니다.
1. IOException이 발생할 수 있는 상황
아래 코드를 보면 이미지 파일을 불러오는 과정에서 IOException이 발생할 가능성이 있습니다.
Resource imgFile = new ClassPathResource("static/images/" + imageName);
InputStream in = imgFile.getInputStream(); // IOException 가능
byte[] imageBytes = StreamUtils.copyToByteArray(in);
- getInputStream() 메서드는 파일을 찾을 수 없거나 접근할 수 없는 경우 IOException을 던짐
- 예: 파일이 존재하지 않음 (FileNotFoundException 포함)
- 예: 파일을 읽을 권한이 없음
- 예: 파일이 손상되어 읽을 수 없음
2. throws IOException를 선언하지 않으면?
- 예외가 발생하면 컴파일 오류가 발생합니다.
- IOException은 Checked Exception이기 때문에, 반드시 처리해야 합니다.
✅ 해결 방법
- throws IOException을 선언하여 예외를 호출한 곳에서 처리하도록 위임
- try-catch로 감싸서 예외를 직접 처리
@GetMapping("/{imageName}")
public ResponseEntity<byte[]> getImage(@PathVariable String imageName) {
try {
Resource imgFile = new ClassPathResource("static/images/" + imageName);
InputStream in = imgFile.getInputStream();
byte[] imageBytes = StreamUtils.copyToByteArray(in);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
headers.setContentLength(imageBytes.length);
return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND); // 404 에러 반환
}
}
- try-catch를 사용하면 파일을 찾을 수 없을 때 404 오류를 반환할 수 있음
- throws IOException 없이도 정상적으로 동작
그럼 다음 이미지를 보여주기 위한 코드를 살펴보자 .
Resource imgFile = new ClassPathResource("static/images/" + imageName);
✅ ClassPathResource("static/images/" + imageName)
- Spring Boot 프로젝트 내부의 static/images/ 디렉토리에서 파일을 찾음
- 예: imageName = "sample.jpg" → "static/images/sample.jpg" 파일을 찾음
- ClassPathResource는 resources 폴더 내의 정적 파일을 불러오는 역할을 합니다.
❗ 한계점
- ClassPathResource는 JAR 파일로 패키징되면 내부 파일을 수정할 수 없음
- 즉, 실행 중에는 새로운 이미지를 저장할 수 없습니다.
- 동적으로 업로드한 이미지는 보통 ClassPathResource가 아닌, 외부 디렉토리(예: /uploads/)에서 불러오는 것이 좋습니다.
그리고 다음 코드는
InputStream in = imgFile.getInputStream();
byte[] imageBytes = StreamUtils.copyToByteArray(in);
✅ InputStream in = imgFile.getInputStream();
- ClassPathResource에서 찾은 이미지 파일을 읽을 준비를 합니다.
✅ StreamUtils.copyToByteArray(in);
- 이미지 파일을 바이트 배열 (byte[]) 로 변환
- HTTP 응답으로 보내기 위해 파일을 이진 데이터 (Binary) 로 변환하는 과정
그리고 마지막 리턴값의 내용은
return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
✅ new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
- ResponseEntity<byte[]> 타입으로 바이트 데이터를 HTTP 응답으로 반환
- HttpStatus.OK (200) → 요청이 성공했음을 의미
위와 같은 구조대로 이루어진다.
근데 좀더 개선해야할 점을 찾아보자면,
개선할 점
1️⃣ JAR 패키징 후에도 사용 가능하도록 ClassPathResource 대신 파일 시스템을 사용
File imgFile = new File("/uploads/" + imageName);
InputStream in = new FileInputStream(imgFile);
- 이렇게 하면 외부 폴더에서 이미지를 관리 가능 (업로드도 가능)
- /uploads/ 폴더를 Nginx 같은 웹 서버와 연동하여 정적 파일로 제공하는 것이 더 효율적
2️⃣ 이미지 타입 자동 감지 현재 MediaType.IMAGE_JPEG로 고정되어 있는데, 이미지 확장자에 따라 타입을 자동 설정할 수 있음.
String contentType = Files.probeContentType(imgFile.toPath());
headers.setContentType(MediaType.parseMediaType(contentType));
- 이렇게 하면 PNG, JPG, GIF 등 다양한 포맷을 자동 감지하여 설정 가능
이렇게 한번 이미지를 보여주는 방식을 알아보았다 . 혹시 좀 더 자세하거나 구체적이며 효율적인 코드가 있으면 언제든 댓글 부탁!!!!
'개발 > Springboot' 카테고리의 다른 글
Springboot _ JWT (0) | 2025.02.08 |
---|---|
Springboot nginx wegsacket ssl 연결 통신 후 [WebSocket Error]java.net.ProtocolException: Expected HTTP 101 response but was '400 ' 에러해결법 (2) | 2024.10.14 |
vscode_ SpringBoot 프로젝트 만들기 (0) | 2024.08.20 |
Springboot -SSE ( 로컬에서는 실시간 o / https nginx 서버에서는 실시간 x) (0) | 2024.06.23 |
springboot https 적용기 (0) | 2024.06.05 |