[캡스톤디자인] 이미지 저장을 위한 NFS 서버 구축

Dev_Sanizzang·2023년 6월 5일
0

캡스톤디자인

목록 보기
8/15

📕 개요

현재 club-service의 모임 생성 API를 보면 사실 이미지 저장을 위한 로직이 없다... 그래서 이번 포스팅에서는 이미지 저장을 위해 내가 선택한 방법과 이미지 저장 코드 구현 과정을 담아 보겠다.

🤔 어떻게 이미지를 저장할까..?

  1. 클라우드 스토리지 서비스 사용: 대부분의 클라우드 제공업체는 파일 저장 및 관리를 위한 스토리지 서비스를 제공한다. 이를 활용하여 이미지를 저장할 수 있다.

💡 대표적인 클라우드 스토리지 서비스
Amazon S3, Google Cloud Storage, Microsoft Azure Storage

  1. DB에 이미지 저장하기: 일반적으로 이미지를 DB에 저장하는 것은 권장되지 않는다고 한다. 이미지 파일은 일반적으로 큰 용량을 가지며, DB에 직접 저장하면 DB의 용량이 빠르게 증가할 수 있다. 이는 DB의 성능에 영향을 줄 수 있고, 이미지 파일을 DB에서 가져오는 데 시간이 오래걸릴 수 있다.
    또한 DB에 이미지를 저장하는 것은 확장성에 제한을 가할 수 있다. 이미지 파일의 용량이 커지면 DB 서버의 용량을 계속 확장해야 할 수 있다.

  2. NFS 사용하기: NFS(Network File System)는 네트워크를 통해 파일 시스템을 공유하고 엑세스하는 프로토콜이다. 다른 시스템에서 NFS를 사용하여 이미지를 저장하고 액세스할 수 있다.

현재 진행하고 있는 프로젝트는 AbleCloud에 재직중이신 멘토님이 계셔서 클라우드 서비스를 AbleCloud를 사용하고 있다. 멘토님께 여쭤본 결과 AbleCloud에서는 따로 스토리지 서비스를 제공하지 않는다고 하셨다. 고로 NFS를 사용하여 이미지 저장을 하는 것으로 결정하였다.

🖥 NFS 서버 구현

NFS 서버 구현 같은 경우 아래 유튜브와 블로그를 참고하였다.

[2020 개정판] 이것이 리눅스다(CentOS 8)14장-01교시 NFS 서버- nfs 서버 설치와 운영
[Linux] NFS 서버 개념 & 구축(설치)

먼저 NFS란 Linux(Unix) 컴퓨터끼리 저장 공간을 공유할 수 있도록 해 주는 시스템이다.

다른 컴퓨터에서 어떻게 사용하냐면 디렉터리를 하나 생성하고 해당 디렉터리를 마운트 시킨다.

그러면 Client가 해당 디렉터리에 파일을 저장하면 NFS 서버의 디렉터리에 저장하는 것이다.

NFS 설치 및 설정 (서버)

1. 파일 설치

공유 디렉토리 설정

/share: 공유할 디렉터리
10.1.1.*(rw,sync): 접속 허용 IP (옵션)

3. 공유할 디렉토리 생성 및 권한 부여

일반사용자도 사용할 수 있도록 권한을 설정해준다.

4. NFS 서비스 열기

systemctl restart nfs-server: nfs 서비스 시작
systemctl enable nfs-server: nfs 상시 가동 설정

5. 방화벽 끄기

현재 내부 네트워크에서 사용하기 때문에 보안상 유연하다.

공유 폴더 확인

현재 서버에서 공유되어 있는 폴더들을 확인할 수 있다.

NFS 설치 및 설정 (클라이언트)

NFS 설치

서버와 동일

공유 폴더 확인

해당 NFS에서 공유한 폴더를 확인할 수 있다.

NFS 공유 디렉토리를 마운트 할 디렉토리 생성

서버 공유 디렉토리, 클라이언트 개인 디렉토리 마운트

마운트 결과 확인

클라이언트에서 마운트된 디렉토리로 파일을 저장하면 서버 공유 디렉토리에 저장됨을 확인할 수 있다.

프론트에서 이미지는 어떻게 사용할까?

내가 생각한 바로는 2가지가 있다.

  1. 백엔드단에서 이미지가 저장되어 있는 디렉토리에 접근해서 직접 전달
  2. NFS 서버에 웹서버를 설치하여 url로 접근

나는 이 중 2번 방법을 채택하였다.

NFS 서버에 웹 서버 설치

테스트

접근이 잘 됨을 볼 수 있다.

club-service 코드 수정

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;
...
  1. 이미지 파일을 받기 위해서 기존 @RequestBody로 받아오는 것에서 @ModelAttribute로 받아오는 것으로 변경
  2. RequestDTO에 MultipartFile 필드 추가

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 서버구축를 해봤다. 아직 수정해야되거나 추가해야되는 부분이 많은 것 같다. 프로젝트에 부족한 점이 무엇인지 계속 파악하고 개선해 나가야겠다.

profile
기록을 통해 성장합니다.

0개의 댓글