[Project] 파일 업로드 방식에 대해 (feat. AWS S3)

bagt13·2022년 10월 14일
0

Project

목록 보기
17/19
post-thumbnail
post-custom-banner

회원의 프로필 이미지를 업로드하는 기능을 구현하던 도중, 이전에 사용했던 방식의 문제점을 인지하게 되었다.

서버에 파일을 저장하면 발생하는 문제

  1. 분산 환경에 적합하지 않다.

    서버에 파일을 저장하면 당연하게도 다른 서버가 존재할 경우 해당 서버에서는 파일을 사용할 수가 없기 때문이다.

  2. 성능 저하 우려가 있다.

    물론 blob으로 DB에 저장할 수도 있다. 하지만 이미지를 불러오기 위해 매번 DB에서 따로 가져와야 하며, 입출력 동안 세션이 유지되기 때문에 DBMS에 부담이 가는 등 성능상 좋은 방법이라고 할 수 없다.

따라서 실무에서는 이미지를 S3와 같은 별도의 저장소에 저장하고, DB에는 해당 이미지의 경로만을 저장하는 방식을 많이 사용한다.


S3를 이용한 이미지 업로드

+ dependency 추가

implementation 'com.amazonaws:aws-java-sdk-s3:1.12.307'

+ application.yml 작성

cloud:
  aws:
    credentials:
      accessKey: ${AWS S3 ACCESSKEY}
      secretKey: ${AWS S3 SECRETKEY}
    s3:
      bucket: ${AWS S3 BUCKET NAME}
      defaultBoard: ${AWS S3 STATIC DEFAULT BOARD IMAGE URL}
      default: ${AWS S3 STATIC DEFAULT MEMBER IMAGE URL}
    region:
      static: ${AWS REGION}
    stack:
      auto: false
config:
  domain: ${AWS S3 DOMAIN} 

파일 업로드 로직

  • yml 파일에 작성한 변수를 @Value로 받아온다

  • S3에 저장할 때 파일마다 식별자가 필요하기 때문에, UUID와 파일 이름을 합쳐 식별자를 생성한다.

  • 생성한 파일을 amazonS3.putObject() 메서드를 통해 버킷에 업로드한다.

  • amazonS3.getUrl() : 버킷에 저장된 파일의 url 경로를 반환한다.
    이 반환값을 memberImage 객체를 통해 DB에 저장하고, 필요할 때마다 가져와서 쓴다.


여기서 앞서 언급한 두 가지 방법과 비교해 두드러지는 이점을 확인할 수 있었다.

서버에 파일을 저장하지 않음으로써 다중 서버에서 파일을 사용할 수 있고, DB에는 파일의 경로만 저장하기 때문에 blob으로 저장하는 방식과 달리 성능상의 문제도 존재하지 않는다.


S3 Bucket

  • S3에는 게시글 / 회원의 기본 이미지를 저장하는 폴더(default), 게시글 폴더, 회원 폴더를 먼저 만들었다.

  • 회원이 프로필 이미지를 게시할 경우 member 폴더에 UUID + 파일명 으로 잘 업로드 된다.

이미지 파일 조회

memberImageService

  • 프로필 이미지가 존재할 경우 가져오고, 없으면 default 이미지를 반환한다.

Multipart 방식 '자체'의 문제점

multipart를 사용하면 파일이 올라가는동안 커넥션이 계속 유지되어야 한다. 이는 서버 자원 낭비이며, 성능 저하를 초래할 수 있다.

따라서 보통은 서버를 거치지 않고 프론트에서 S3에 파일을 직접 업로드하는 방식을 많이 사용한다고 한다.


그럼에도 불구하고 서버에서 업로드한 이유

  • 일단 문제점을 다소 늦게 발견했다. 내가 학습한 파일 업로드 방식이 multipart였고, 레퍼런스도 대부분 백엔드 multipart 키워드가 많았기 때문에 문제를 뒤늦게 인지했다.

  • 프로젝트 구조 상 프론트분들이 할 일이 너무 많았다. 전해 들은 이야기이지만, 작은 규모의 프로젝트는 프론트엔드 개발자의 업무 비중이 비교적 크다고 들었고, 실제로도 할 일이 굉장히 많았다고 하셨다.

문제점을 파악했으니 리팩토링을 통해 수정하거나, 다음에 프로젝트를 진행한다면 적용해보고 싶다.

profile
주니어 백엔드 개발자입니다😄
post-custom-banner

0개의 댓글