무신사나 쿠팡등 쇼핑 사이트에서 여러상품의 사진이 한번에 보여지는 모습을 볼 수 있다.
따로 게시글을 작성하지는 않았지만 상품 등록기능을 마무리한 지금 나도 같은 기능을 추가해야하는 상황이다.
그래서 어떻게 하는지 구글링해보았다.
일단 이미지를 출력해주기 전에 알아야할것은 이미지가 바이트 배열(bytr[])의 생김새를 가지고 있다는 것이다.
그렇다면 InputStream은 무엇일까.
서버에 저장되어 있는 이미지를 꺼내서 출력하려면 저장소에서 프로그램까지 이미지 파일을 옮겨주어야 한다.
이때 사용되는 것이 바로 InputStream이라고 한다.
잘 관찰해보면 Stream은 0과 1로만 이루어져 있는 형태로 되어있는 추상클래스라고 하는데 보내고 있는 파일이 무엇이든지 상관없어야 하기 때문이라고한다.
이미지, 실행기 등등 파일마다 생김새는 다를테니 조금만 생각해보니 맞는말 같다.
그럼 알게된 두가지를 활용해서 이미지를 출력해보자.
public byte[] findImage(Long id) throws IOException {
String path = productImageRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Not Found"))
.getPath();
InputStream imageStream = new FileInputStream(path);
byte[] image = IOUtils.toByteArray(imageStream);
imageStream.close();
return image;
}
위가 내가 작성한 코드이다.
일단 서버컴퓨터에 저장되어있는 이미지를 꺼내기위해 DB에 저장된 이미지 id를 통해서 이미지 경로를 꺼내왔다.
그리고 파일을 프로그램을 끌어오기 위해 InputStream을 통해서 파일을 꺼내왔다.
하지만 Stream은 0과 1의 조합이기때문에 이미지를 확인할 수 없다.
그래서 IOUtils라는 라이브러리를 통해서 byte배열로 변환해 주었다.
사실 이 라이브러리를 쓰기위해서 노력했으나 Dependencies 적용이 안되서 여러시도끝에 한단계 낮은 스프링버전으로 다시 세팅했다.
이제 이미지를 프로그램에 옮기는 과정을 완료했으니 클라이언트에 요청을 받아 넘겨보도록 하자.
@GetMapping("/images/{id}")
public ResponseEntity<byte[]> imageDetails(
@PathVariable Long id
) throws IOException {
byte[] res = productService.findImage(id);
return new ResponseEntity<>(res, HttpStatus.OK);
}
위처럼 Get메소드를 통해서 id를 받고 이미지를 내려주어보았다.
이상한 글자들이 출력되었다.
추측을 해보았는데 이미지는 바이트의 배열로 바이트들을 늘여놓으면 저런 형태가 아닐까 생각한다.
헤더를 수정해주어야 할것같다고 판단하고 추가 구글링에 들어갔다.
찾은 결과는 GetMapping에 옵션을 추가해주는 것이었는데 그것이 바로 Produces이다.
Produces는 내려주는 데이터의 타입을 정의해주는 것이라고 하는데 이를 생각하면 저런 이상한 글자들이 출력되는 것이 당연하다.
그래서 아래와 같이 코드를 추가하였는데
@GetMapping(
value="/images/{id}",
produces={MediaType.IMAGE_PNG_VALUE, MediaType.IMAGE_JPEG_VALUE}
)
public ResponseEntity<byte[]> imageDetails(
@PathVariable Long id
) throws IOException {
byte[] res = productService.findImage(id);
return new ResponseEntity<>(res, HttpStatus.OK);
}
데이터의 타입이 png와 jpeg라고 선언해주었다.
사진타입을 클라이언트에서 두가지만 받을 예정이라 이정도만 추가해주었고 실행해보았다.
귀여운 돼지 사진이 잘 출력되었다.
이제 이미지 id의 리스트들만 사전에 클라이언트에 내려주면 웹에 상품 이미지들을 띄워줄 수 있을것이다.
서버에서는 명시해주어야 할것이 많으니 주의해야한다는 교훈과 함께 메소드하나를 잘 마무리 하였다.