[Spring Boot] 사진 업로드 기능 구현하기 Back-end , 1편
안녕하세요! 오늘은 Spring Boot와 JPA를 사용하여 사진 업로드 기능을 구현하는 방법에 대해 이야기해보려고 합니다. 파일 업로드는 웹 애플리케이션에서 자주 사용되는 기능 중 하나입니다. 이 포스트에서는 사용자로부터 받은 사진 파일을 서버에 저장하고, 해당 정보를 데이터베이스에 기록하는 과정을 설명하겠습니다.
기본 설정
먼저, application.properties
혹은 application.yml
파일에 파일을 저장할 경로를 지정합니다. 아래는 제가 실제로 지정한 경로입니다. C드라이브 아래 workspace/{프로젝트이름}/upload/ 로 설정하였습니다.
file:
path: C:/workspace/interior/upload/
Cover 엔티티
사진 정보를 데이터베이스에 저장하기 위해 Cover
엔티티를 정의합니다. 이 엔티티는 사진 파일의 URL과 Cover사진의 제목을 포함합니다.
@Entity
public class Cover {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String title;
private String coverImageUrl;
@CreationTimestamp
private Timestamp createDate;
}
DTO(Data Transfer Object) 사용
사진 업로드에 필요한 데이터를 전달하기 위해 CoverUploadDto
클래스를 사용합니다. 이 DTO는 MultipartFile
타입의 file을 포함하며, 엔티티로의 변환 메서드를 제공합니다.
@Data
public class CoverUploadDto {
private MultipartFile file;
private String title;
public Cover toEntity(String coverImageUrl) {
return Cover.builder()
.coverImageUrl(coverImageUrl)
.title(title)
.build();
}
}
사진 업로드 서비스
사진을 업로드하고 데이터베이스에 저장하는 로직을 ImageService 클래스
에 구현합니다.
@RequiredArgsConstructor
@Service
public class ImageService {
private final ImageRepository imageRepository;
@Value("${file.path}")
private String uploadFolder;
@Transactional
public void 커버사진업로드(CoverUploadDto coverUploadDto) {
UUID uuid = UUID.randomUUID();
String imageFileName = uuid + "_" + coverUploadDto.getFile().getOriginalFilename();
System.out.println("커버 이미지 파일이름:"+imageFileName);
Path imageFilePath = Paths.get(uploadFolder + imageFileName);
try {
Files.write(imageFilePath, coverUploadDto.getFile().getBytes());
} catch (Exception e) {
e.printStackTrace();
}
Cover cover = coverUploadDto.toEntity(imageFileName);
coverRepository.save(cover);
}
}
여기서 @Value("${file.path}")
는 application.properties 또는 application.yml 에 설정한 경로의 값을 매핑합니다.
이 서비스는 다음과 같은 기능을 수행합니다:
- 파일 이름 생성: UUID를 사용하여 고유한 파일 이름을 생성합니다.
- 파일 저장: 지정된 경로에 파일을 저장합니다.
- 데이터베이스 저장: Cover 엔티티를 생성하고 저장합니다.
추가적으로 UUID
, getOriginalFilename()
, Files.write
, 그리고 imageUploadDto.getFile().getBytes()
에 대해 자세하게 설명드리겠습니다.
UUID (Universally Unique Identifier)
UUID는 범용적으로 고유한 식별자를 생성하는 데 사용됩니다. 이 식별자는 128비트 길이를 가지며, 파일 이름이나 다른 객체에 대한 고유한 키로 활용될 수 있습니다. UUID를 사용하면 파일 이름이 겹칠 확률을 극도로 줄일 수 있어, 파일 업로드 시 유용합니다. 실무에서 극악의 확률로 UUID가 같게 생성될 수 있다고 하는데 _ 와 파일이름으로 파일이름을 만들면 같을 확률이 아주아주 낮은 이미지파일 이름이 만들어집니다.
getOriginalFilename()
MultipartFile 인터페이스의 getOriginalFilename() 메서드는 업로드된 파일의 원래 이름을 반환합니다. 사용자가 업로드한 파일의 이름을 얻는 데 사용됩니다. 이는 파일을 서버에 저장할 때 원본 파일 이름을 유지하거나 로깅 목적으로 사용될 수 있습니다.
String originalFileName = coverUploadDto.getFile().getOriginalFilename();
Files.write(Path path, byte[] bytes)
Java NIO 패키지의 Files.write
메서드는 주어진 경로에 바이트 배열을 파일로 저장합니다. 이 메서드는 파일 업로드 기능에서 파일을 서버의 파일 시스템에 저장할 때 사용됩니다.
Path imageFilePath = Paths.get(uploadFolder + imageFileName);
Files.write(imageFilePath, coverUploadDto.getFile().getBytes());
여기서 Paths.get(uploadFolder + imageFileName)
는 파일을 저장할 경로를 생성하고, coverUploadDto.getFile().getBytes()
는 업로드된 파일의 바이트 배열을 가져와 해당 경로에 파일로 작성합니다.
coverUploadDto.getFile().getBytes()
getBytes()
메서드는 MultipartFile
의 내용을 바이트 배열로 변환합니다. 이 배열은 파일의 실제 데이터를 나타냅니다. 파일을 서버에 저장하려면 이 바이트 배열을 사용하여 파일 시스템에 기록해야 합니다.
byte[] fileData = coverUploadDto.getFile().getBytes();
이 바이트 배열은 Files.write
메서드를 사용하여 실제 파일로 변환되어 서버의 지정된 위치에 저장됩니다.
사진 업로드 컨트롤러
마지막으로 Controller
에서 Front부분에서 전송한 데이터를 받아줍니다.
@PostMapping("/")
public String coverImageUpload(CoverUploadDto coverUploadDto) {
if(coverUploadDto.getFile().isEmpty()) {
throw new CustomValidationException("이미지가 첨부되지 않았습니다.", null);
}
imageService.커버사진업로드(coverUploadDto);
return "redirect:/";
}
결론
이 글에서는 Spring Boot와 JPA를 사용하여 사진 업로드 기능을 구현하는 방법을 살펴보았습니다. 이 기능은 웹 애플리케이션에서 다양한 형태로 활용될 수 있으며, 사용자 경험을 향상시키는 데 중요한 역할을 합니다. 다음포스팅에 Front 부분과 연결하여 실제 업로드까지 진행해보겠습니다!
2편은 아래 링크에 있습니다!