개인 프로젝트를 하면서 JPA 개념이 부족하여 이것저것 시도하면서 만들고 있다.
그중 가장 기본적인 이미지 저장법에 대해 시도해보았다..!!
이미지를 저장하는방법
첫번째 이미지를 바이너리 형태로 DB에 저장 (Lob 사용)
두번째 서버 내부에 이미지 파일을 직접 저장하는 방법
세번째 이미지 호스팅 서비스를 이용하는 방법
첫번째 두번째 방법을 시도했고 마지막으로 배포시에 가장 유명한 AWS S3를 통해 시도를 해볼생각이다!!.
이미지를 바이너리 형태로 DB에 저장 (Lob 사용)
그 전 DB 설정을 LONGBLOB 형식으로 해주기!
Entity
@Lob
@Column(name = "image_1", columnDefinition = "LONGBLOB", nullable = false)
private byte[] image1;
@Lob
@Column(name = "IMAGE_2", columnDefinition = "LONGBLOB")
private byte[] image2;
@Lob
@Column(name = "IMAGE_3", columnDefinition = "LONGBLOB")
private byte[] image3;
DTO
private MultipartFile image1; // 파일 경로를 문자열로 받음
private MultipartFile image2;
private MultipartFile image3;
public Post toEntity() throws IOException {
if (image1 == null) {
throw new IllegalArgumentException("사진 한장은 필수 입니다.");
}
return Post.builder()
.title(title)
.content(content)
.author(author)
.image1(image1 != null ? image1.getBytes() : null) // MultipartFile -> byte[] 변환
.image2(image2 != null ? image2.getBytes() : null)
.image3(image3 != null ? image3.getBytes() : null)
.build();
}
Service
public Post create(PostCreateDto dto) throws IOException {
Post entity = dto.toEntity();
return postRepository.save(entity);
}
Controller
@PostMapping("/create")
public ResponseEntity<String> create(@ModelAttribute PostCreateDto dto) throws IOException {
Post createdPost = postService.create(dto);
return ResponseEntity.ok("생성 완료 ID: " + createdPost.getPostId());
}
이제 Postman을 통해서 이미지가 잘 저장되는지 확인해보자!
200이 나오고 생성 완료!
그리고 보는것처럼 잘 들어갔다!
BLOB 형식으로 저장하면 간단하다. 하지만 이미지 크기가 크면 DB 성능에 부담이 될 수 있다 ㅠㅠ
서버 내부에 이미지 파일을 직접 저장하는 방법
ImageHandler를 통해 이미지를 서버에 저장하고 이미지 파일 이름을 DB에 저장하는 방법을 시도했다.
대략적인 구조는 이런형식이다.
- 사용자는 이미지 파일을 POST 요청으로 서버에 전송하는데 이때 데이터 타입은 multipart/form-data 형식으로 전송한다.
- 컨트롤러는 해당 요청을 받고 이때 저장할 이미지를 MultipartFile 형태로 받아와 서비스 계층에 넘긴다.
- 서비스는 먼저 전달받은 이미지를 서버 PC에 저장하는데 이때 파일 저장 과정은 ImageHandler 클래스에게 위임한다. ImageHandler는 이미지를 저장한 후 이미지가 저장된 경로를 리턴한다.
- 서비스는 이미지 저장 후 리턴받은 이미지 저장 경로를 레퍼지토리 계층에 넘겨준다.
이때 이미지 경로는 Entity 형태로 전달된다. - 레퍼지토리는 전달받은 경로를 DB에 저장한다.
먼저 DB를 BLOB --> varchar 형식으로 바꿨다.
Entity
@Column(name = "image_1", nullable = false)
private String image1;
@Column(name = "IMAGE_2")
private String image2;
@Column(name = "IMAGE_3")
private String image3;
DTO
@Data
public class PostCreateDto {
private String title;
private String content;
private String author;
private MultipartFile image1; // 파일 경로를 문자열로 받음
private MultipartFile image2;
private MultipartFile image3;
public Post toEntity(String imagePath1, String imagePath2, String imagePath3) throws IOException {
if (image1 == null) {
throw new IllegalArgumentException("사진 한장은 필수 입니다.");
}
return Post.builder()
.title(title)
.content(content)
.author(author)
.image1(imagePath1) // 파일 경로를 엔티티에 설정
.image2(imagePath2)
.image3(imagePath3)
.build();
}
ImageHandler
@Component
public class ImageHandler {
private final String uploadDir = "/Users/pearlinezero/uploads/"; // 파일이 저장될 경로
public String saveImage(MultipartFile image) throws IOException {
// 파일이 비어있으면 null을 반환
if (image.isEmpty()) {
return null;
}
// 이미지의 원래 파일 이름을 가져옴
String fileName = getOriginName(image);
// 저장할 파일 경로 생성
Path filePath = Paths.get(uploadDir + fileName);
// 업로드 디렉토리가 존재하지 않으면 생성
if (!Files.exists(Paths.get(uploadDir))) {
Files.createDirectories(Paths.get(uploadDir));
}
// 파일을 지정된 경로에 저장
Files.write(filePath, image.getBytes());
// 저장된 파일 경로를 문자열로 반환
return filePath.toString();
}
//원래 파일 이름 가져오기:
private String getOriginName(MultipartFile image){
return image.getOriginalFilename();
}
}
Service
@Transactional
public Post create(PostCreateDto dto) throws IOException {
// 이미지 경로 저장
String imagePath1 = imageHandler.saveImage(dto.getImage1());
String imagePath2 = dto.getImage2() != null ? imageHandler.saveImage(dto.getImage2()) : null;
String imagePath3 = dto.getImage3() != null ? imageHandler.saveImage(dto.getImage3()) : null;
Post entity = dto.toEntity(imagePath1, imagePath2, imagePath3);
return postRepository.save(entity);
}
Controller은 변경이 없음으로 PASS
그럼 Postman을 사용하여 확인해보자
성공!
해당 이미지가 잘 저장되었고 해당 이름도 그대로 저장
다음에는 AWS S3를 통해 이미지를 저장하는 방법을 시도해봐야겠다!!
'트러블슈팅 > SpringBoot' 카테고리의 다른 글
[Springboot & JSP]JPA 환경설정 (1) | 2024.10.12 |
---|---|
[Spring & Spriboot] Spring Security를 이용하여 이메일 인증 서비스 만들기 (2) | 2024.09.27 |
[Spring & Spriboot] Spring Security를 이용하여 회원 로그인 , 회원가입 서비스 만들기 (0) | 2024.09.27 |