본문으로 바로가기
2222

안녕하세요, 백엔드 개발자입니다.

지난 1편과 2편에 걸쳐, 서버의 부하를 줄이기 위한 이미지 업로드 전략과 실제 구현 방법을 알아보았습니다. 이제 S3에는 원본 이미지와 함께 리사이징된 썸네일 이미지가 잘 저장되고 있습니다.

이번 마지막 3편에서는 이렇게 업로드된 이미지들의 URL을 어떻게 관리하는 것이 효율적인지, 작지만 장기적인 유지보수성에 큰 영향을 미치는 URL 관리 패턴에 대해 이야기해 보겠습니다.

1. 일반적인 접근: 모든 URL을 DB에 저장하기

가장 직관적인 방법은 생성된 모든 이미지의 URL을 DB에 각각 저장하는 것입니다.

CREATE TABLE `resources` (
  `id` int NOT NULL AUTO_INCREMENT,
  `resource_url` varchar(255) DEFAULT NULL,
  `resource_thumbnail_url` varchar(255) DEFAULT NULL,
  /* ... */
  PRIMARY KEY (`id`)
);

이 방식은 간단하지만, 서비스가 확장되면 문제가 생길 수 있습니다. 만약 기획팀에서 "이제 150px짜리 아주 작은 썸네일도 필요해요!" 라고 요청한다면 어떻게 해야 할까요?

  1. DB resources 테이블에 resource_thumbnail_small_url 컬럼을 추가해야 합니다.
  2. multer 설정에 w150 썸네일 생성 로직을 추가해야 합니다.
  3. 기존에 업로드된 모든 이미지에 대해 w150 썸네일을 다시 생성하고, DB의 새로운 컬럼을 채워 넣는 마이그레이션 작업을 해야 합니다.

요구사항이 바뀔 때마다 DB 스키마 변경과 데이터 마이그레이션이 필요하다는 것은 유연한 구조가 아닙니다.

2. 유연한 구조: 규칙을 기반으로 URL 동적 생성하기

더 나은 방법은 DB에 하나의 기준 정보(원본 URL 또는 Key)만 저장하고, 나머지는 정해진 규칙에 따라 동적으로 생성하는 것입니다.

2편의 multer 설정에서 우리는 이미 규칙을 만들었습니다.

  • 원본 이미지는 original/ 경로에 저장된다.
  • 500px 썸네일은 w500/ 경로에 저장된다.

이 규칙을 활용하면, DB에는 원본 URL 하나만 저장하고, 썸네일이 필요할 땐 이 URL을 간단히 조작하여 만들어낼 수 있습니다.

// resource.entity.ts (또는 resource.service.ts)

// DB에는 resourceUrl 하나만 저장되어 있다고 가정
// 예: <https://s3-bucket.com/original/uuid-image.jpg>

@Entity()
export class Resource {
  @Column()
  resourceUrl: string;

  // DB에 저장되지 않는 가상 필드(getter)
  get thumbnail(): string {
    if (!this.resourceUrl) {
      return null;
    }
    return this.resourceUrl.replace('/original/', '/w500/');
  }
}

이제 클라이언트에게 데이터를 내려줄 때, thumbnail getter를 통해 동적으로 생성된 썸네일 URL을 함께 전달하면 됩니다.

3. 이 패턴의 장점

  1. DB 스키마 단순성: 썸네일 종류가 10개로 늘어나도 DB 스키마는 변경할 필요가 없습니다.
  2. 유연성과 확장성: 150px 썸네일이 새로 필요해지면, multer 설정에 w150 생성 로직만 추가하면 끝입니다. 기존 데이터나 DB를 전혀 건드릴 필요가 없습니다.
  3. 로직의 중앙화: URL 생성 규칙이 코드(Entity getter 또는 DTO 매핑 함수)에 명확하게 정의되므로, URL이 사용되는 모든 곳에서 일관성을 유지할 수 있습니다.

마치며

3편에 걸쳐 이미지 업로드 시스템을 설계하고 구현하는 과정을 알아보았습니다.

1편에서는 아키텍처 관점에서 역할을 분리했고, 2편에서는 구현 관점에서 스트리밍 파이프라인을 구성했으며, 이번 3편에서는 유지보수 관점에서 URL 관리 패턴을 적용했습니다.

좋은 시스템은 이처럼 여러 관점의 고민이 균형을 이룰 때 만들어진다고 생각합니다. 작아 보이는 URL 관리 패턴 하나가 미래의 많은 작업을 줄여줄 수 있는 것처럼, 코드의 세부적인 부분까지 장기적인 관점을 갖고 설계하는 습관이 중요합니다.

긴 시리즈 읽어주셔서 감사합니다.