현재 club-service의 모임 생성 API를 보면 사실 이미지 저장을 위한 로직이 없다... 그래서 이번 포스팅에서는 이미지 저장을 위해 내가 선택한 방법과 이미지 저장 코드 구현 과정을 담아 보겠다.
💡 대표적인 클라우드 스토리지 서비스
Amazon S3, Google Cloud Storage, Microsoft Azure Storage
DB에 이미지 저장하기: 일반적으로 이미지를 DB에 저장하는 것은 권장되지 않는다고 한다. 이미지 파일은 일반적으로 큰 용량을 가지며, DB에 직접 저장하면 DB의 용량이 빠르게 증가할 수 있다. 이는 DB의 성능에 영향을 줄 수 있고, 이미지 파일을 DB에서 가져오는 데 시간이 오래걸릴 수 있다.
또한 DB에 이미지를 저장하는 것은 확장성에 제한을 가할 수 있다. 이미지 파일의 용량이 커지면 DB 서버의 용량을 계속 확장해야 할 수 있다.
NFS 사용하기: NFS(Network File System)는 네트워크를 통해 파일 시스템을 공유하고 엑세스하는 프로토콜이다. 다른 시스템에서 NFS를 사용하여 이미지를 저장하고 액세스할 수 있다.
현재 진행하고 있는 프로젝트는 AbleCloud에 재직중이신 멘토님이 계셔서 클라우드 서비스를 AbleCloud를 사용하고 있다. 멘토님께 여쭤본 결과 AbleCloud에서는 따로 스토리지 서비스를 제공하지 않는다고 하셨다. 고로 NFS를 사용하여 이미지 저장을 하는 것으로 결정하였다.
NFS 서버 구현 같은 경우 아래 유튜브와 블로그를 참고하였다.
✅ [2020 개정판] 이것이 리눅스다(CentOS 8)14장-01교시 NFS 서버- nfs 서버 설치와 운영
✅ [Linux] NFS 서버 개념 & 구축(설치)
먼저 NFS란 Linux(Unix) 컴퓨터끼리 저장 공간을 공유할 수 있도록 해 주는 시스템이다.
다른 컴퓨터에서 어떻게 사용하냐면 디렉터리를 하나 생성하고 해당 디렉터리를 마운트 시킨다.
그러면 Client가 해당 디렉터리에 파일을 저장하면 NFS 서버의 디렉터리에 저장하는 것이다.
/share: 공유할 디렉터리
10.1.1.*(rw,sync): 접속 허용 IP (옵션)
일반사용자도 사용할 수 있도록 권한을 설정해준다.
systemctl restart nfs-server: nfs 서비스 시작
systemctl enable nfs-server: nfs 상시 가동 설정
현재 내부 네트워크에서 사용하기 때문에 보안상 유연하다.
현재 서버에서 공유되어 있는 폴더들을 확인할 수 있다.
서버와 동일
해당 NFS에서 공유한 폴더를 확인할 수 있다.
클라이언트에서 마운트된 디렉토리로 파일을 저장하면 서버 공유 디렉토리에 저장됨을 확인할 수 있다.
내가 생각한 바로는 2가지가 있다.
나는 이 중 2번 방법을 채택하였다.
접근이 잘 됨을 볼 수 있다.
ClubController.java
// 모임 생성
@PostMapping("/club")
public ResponseEntity<Long> createClub(@Valid @ModelAttribute RequestClub requestClub) {
return ResponseEntity.status(HttpStatus.CREATED).body(clubService.createClub(requestClub));
}
// 모임 정보 수정
@PutMapping("/club/{club-id}")
public ResponseEntity<Long> updateClub(@PathVariable("club-id") Long clubId, @Valid @ModelAttribute RequestUpdateClub requestUpdateClub) {
return ResponseEntity.status(HttpStatus.OK).body(clubService.updateClubById(clubId, requestUpdateClub));
}
RequestClub.java
@Getter
@NoArgsConstructor
public class RequestClub {
private MultipartFile multipartFile;
...
@RequestBody
로 받아오는 것에서 @ModelAttribute
로 받아오는 것으로 변경FileStore.java
@Component
public class FileStore {
@Value("${file.dir}/")
private String fileDirPath;
@Value("${file.url}/")
private String url;
// 확장자 추출
private String extractExt(String originalFileName) {
int idx = originalFileName.lastIndexOf(".");
String ext = originalFileName.substring(idx);
return ext;
}
private String createStoreFileName(String originalFileName) {
String uuid = UUID.randomUUID().toString();
String ext = extractExt(originalFileName);
String storeFileName = uuid + ext;
return storeFileName;
}
public String storeFile(MultipartFile multipartFile) throws IOException {
if (multipartFile.isEmpty()) {
return null;
}
String originalFileName = multipartFile.getOriginalFilename();
String storeFileName = createStoreFileName(originalFileName);
multipartFile.transferTo(new File(fileDirPath + storeFileName));
return url + storeFileName;
}
}
이미지를 저장하기 위한 클래스 추가
ClubServiceImpl.java
// 모임 생성
@Transactional
@Override
public Long createClub(RequestClub requestClub) {
String mainImageUrl = null;
try {
mainImageUrl = fileStore.storeFile(requestClub.getMultipartFile());
} catch (IOException e) {
e.printStackTrace();
}
return clubRepository.save(requestClub.toEntity(mainImageUrl)).getId();
}
Request로 받은 MultipartFile 값을 통해 이미지를 저장하고 DB에는 해당 이미지를 접근하기 위한 url을 저장하도록 하였다.
이렇게 이미지 저장을 위한 NFS 서버구축를 해봤다. 아직 수정해야되거나 추가해야되는 부분이 많은 것 같다. 프로젝트에 부족한 점이 무엇인지 계속 파악하고 개선해 나가야겠다.