File(Image) Upload and Display
이미지 업로드, 디스플레이
이번에 미니 프로젝트를 진행하면서 게시판을 작성할 때 이미지를 첨부하여 저장하고, 전체 게시글을 제공하는 페이지와 게시글 상세페이지에서 이미지를 제공하고 싶었습니다.
클라이언트
클라이언트 단에서는 간단하게 HTTP method와 HTTP request, Type을 설정해 줬습니다.
<form th:action="@{/api/endpoint}" method="post" enctype="multipart/form-data">
<!-- 다른 컨텐츠 들-->
<div>
<label for="img" class="form-label">Upload Image</label>
<input class="form-control" type="file" id="img" name="img" accept="image/*">
</div>
</form>
th:
는 thymeleaf문법입니다.
th:action
: 서버단에서 정의한 엔드포인트를 명시하는 곳으로, 저는 위에 모든 코드를 작성하진 않았지만, 게시글을 작성하기 때문에 서버의 게시글 생성 엔드포인트를 설정해 줬습니다.method
: HTTP의 메서드를 명시하는 곳으로, 보통 생성하는 요청은 POST를 사용합니다.enctype
: 전송하는 데이터의 인코딩 속성을 명시하는 곳으로, 보통 POST에서는application/x-www-form-urlcencoded
을 주로 사용하지만, 파일(이미지)을 전송하기 때문에multipart/form-data
를 작성했습니다.accept
: 전송하는 파일의 타입을 명시하는 곳으로,type
이 file일 경우 사용되며, image를 제외한 audio, video 등이 있습니다. /(슬러시) 뒤 쪽은 확장자를 명시합니다.
서버
동적 타입의 언어를 사용하다가 정적 타입의 언어를 사용하다 보니 Django보다 상대적으로 신경 쓸 것이 많았습니다. 따라서 첨부파일을 받을 때 어떤 타입으로 매개변수를 받아야 될지 고민이었습니다.
서버단에서는 클라이언트에서 제공한 데이터를 원하는 방식으로 핸들링할 수 있으며, 저는 이미지를 저장하고 표시하는 기능을 구현하고 싶어서 매개변수를 MultipartFile
타입으로 받았습니다.
MultipartFile
타입으로 이미지를 매개변수로 받습니다.- 받은 이미지를 저장할 경로를 명시해 줍니다. (절대경로)
- (선택사항) 파일관리를 위하여 서비스 별, 일자 별로 관리하는 로직을 추가합니다.
- (선택사항) 중복된 파일 이름을 보완하기 위해 uuid를 사용하여 파일 이름에 추가합니다.
File
클래스를 활용하여 (2) ~ (4)에서 명시한 경로를 인수로 넣어 파일 객체를 생성합니다.MultipartFile
의 transferTo 메서드를 활용하여 파일 객체의 경로에 클라이언트에서 전달받은 실제 이미지를 저장합니다.- 데이터베이스에 파일 이름과 경로를 저장합니다.
추가적으로 파일 크기를 최적화하는 로직을 추가할 수 있습니다.
새로 사용한 Java API
이번 Spring Boot 미니 프로젝트에서 이미지를 업로드 기능을 다룰 때 매개변수로 MultipartFile
인터페이스를 사용했습니다.
사용 메서드로는 transferTo
를 사용하여 이미지를 경로에 저장했습니다.