Active Storage 도메인 모델: Blob과 Attachment 이해하기

Active Storage Domain Model: Blobs and Attachments

발행일
2025년 10월 16일

핵심 요약

  • 1 Blob은 업로드된 파일의 메타데이터와 실제 파일의 저장 위치를 가리키는 포인터이며, 불변성을 가진다.
  • 2 Attachment는 애플리케이션 모델 레코드와 Blob을 연결하는 다형성 조인 테이블로, 파일의 '이름'과 '사용' 관계를 정의한다.
  • 3 Active Storage는 `attach`로 파일 업로드 및 연결을 처리하고, `detach`로 연결만 해제하거나 `purge`로 파일과 연결 모두를 삭제하는 기능을 제공한다.

도입

Active Storage는 Rails에서 파일 업로드를 관리하는 강력한 라이브러리이지만, Blob과 Attachment와 같은 핵심 용어는 종종 혼란을 야기합니다. 이 글은 Active Storage를 오랫동안 사용해왔음에도 불구하고 모델, Blob, Attachment가 어떻게 상호작용하는지 명확히 이해하지 못했던 경험을 바탕으로, Active Storage의 도메인 모델을 심층적으로 분석하여 이러한 혼란을 해소하고자 합니다. 이들의 역할을 명확히 이해하면 파일 업로드, 삭제 및 재사용에 대한 추론이 훨씬 쉬워지며, 애플리케이션이 성장함에 따라 문서 및 관련 모델을 관리하는 데 큰 도움이 됩니다.

Active Storage의 핵심 구성 요소인 Blob과 Attachment는 다음과 같이 정의됩니다.

Blob (ActiveStorage::Blob)

Blob은 업로드된 파일에 대한 메타데이터를 저장하며, 실제 파일은 AWS S3, GCS, 디스크 등 스토리지 서비스에 저장됩니다. Blob은 해당 파일이 스토리지 서비스의 어디에 위치하는지에 대한 스토리지 키와 함께 다음 메타데이터를 보관합니다.

  • 데이터베이스 테이블: active_storage_blobs

  • 주요 컬럼:

    • key: 스토리지 서비스에서 바이트를 가져오는 데 사용되는 경로/키
    • filename: 원본 파일명
    • content_type: 파일의 MIME 타입
    • byte_size: 파일 크기 (바이트 단위)
    • checksum: 파일 무결성 검사
    • metadata: JSON 형식 (이미지 크기, 분석 플래그 등)
    • service_name: Blob이 저장된 스토리지 서비스 이름
    • Timestamps

Blob은 특정하고 변경 불가능한 파일을 나타내도록 설계되었습니다. 한 번 생성된 Blob은 항상 동일한 파일 데이터를 가리켜야 합니다. 파일 내용을 변경해야 할 경우(예: 이미지 크기 조정, 워터마크 추가), 새로운 파일에 대해 완전히 새로운 Blob을 생성하고, 이전 Blob이 더 이상 필요하지 않다면 제거(purge)하는 것이 올바른 접근 방식입니다. 이러한 불변성은 애플리케이션 전반에서 Blob을 예측 가능하고 안전하게 참조할 수 있도록 합니다.

Attachment (ActiveStorage::Attachment)

Attachment는 Blob을 애플리케이션 모델에 연결하는 다형성 조인 테이블입니다. Attachment는 레코드와 Blob에 속하지만, Blob은 레코드에 직접 속하지 않습니다. 레코드에서 Blob을 가져오려면 Attachment를 거쳐야 합니다. Attachment는 하나의 모델 레코드와 명명된 슬롯(예: “avatar”, “documents”)을 하나의 Blob에 연결하는 역할을 합니다.

  • 데이터베이스 테이블: active_storage_attachments

  • 주요 컬럼:

    • name: 모델의 연결 이름 (:avatar, :files 등)
    • record_type / record_id: 연결된 모델/행
    • blob_id: 가리키는 Blob의 ID
    • Timestamp

작동 방식: User 모델의 has_one_attached :avatar 또는 Project 모델의 has_many_attached :documents와 같은 선언은 Attachment 연결을 정의합니다. user.avatar.attach(...)를 실행하면 Active Storage는 다음 세 가지 작업을 수행합니다.

  1. 업로드된 파일을 나타내는 Blob을 생성하고 메타데이터를 저장합니다.

  2. 파일을 스토리지 서비스에 업로드합니다.

  3. user 모델 레코드를 해당 Blob에 연결하는 Attachment를 생성합니다.

하나의 Blob은 여러 번(동일하거나 다른 모델에) 연결될 수 있으며, 이는 파일을 다시 업로드할 필요 없이 재사용하는 방법입니다. 각 사용은 동일한 Blob과 다른 레코드를 가리키는 별도의 Attachment 행을 생성합니다.

파일 교체 및 삭제:

  • detach: 레코드와 Blob 간의 연결(Attachment)만 삭제하고 싶을 때 사용합니다(예: user.avatar.detach). 이는 Attachment 행을 파괴하지만, 실제 파일은 그대로 유지됩니다. 다른 레코드가 해당 Blob을 여전히 사용하고 있다면 Blob은 그대로 남아있습니다.

  • purge: Attachment와 Blob 모두를 삭제하고 싶을 때 사용합니다(예: user.avatar.purge). 이는 스토리지 서비스에서 실제 파일을 제거합니다. 네트워크 호출이 발생하므로, 백그라운드 작업으로 수행하려면 purge_later 메서드를 사용합니다.

Blob으로 할 수 있는 작업

Blob은 파일 메타데이터 읽기, 바이트 다운로드, URL 생성, 콘텐츠 분석, 수동 Blob 생성 등 파일 작업을 위한 풍부한 API를 제공합니다.

  • 서명된 URL 생성: rails_blob_url(blob) 또는 <%= image_tag url_for(user.avatar) %>를 통해 안전하고 만료되는 URL을 생성합니다.

  • 메타데이터 접근: blob.filename, blob.content_type, blob.byte_size, blob.checksum, blob.metadata, blob.service_name 등을 통해 파일 정보를 얻습니다.

  • 실제 파일 데이터 읽기/다운로드: blob.download (전체 파일), blob.open (Tempfile), blob.download { |chunk| ... } (스트리밍)을 통해 파일 바이트에 접근합니다.

  • 파일 분석: blob.analyze를 통해 이미지 크기, 비디오 길이 등 특정 파일 형식의 메타데이터를 자동으로 추출합니다.

  • Blob 수동 생성: ActiveStorage::Blob.create_and_upload! 또는 ActiveStorage::Blob.create_after_upload!를 사용하여 스크립트나 백그라운드 작업에서 직접 Blob을 생성할 수 있습니다.

결론

이 글을 통해 Active Storage의 핵심 도메인 모델인 Blob과 Attachment의 역할과 상호작용 방식이 명확해졌기를 바랍니다. Blob의 불변성과 Attachment의 다형성 연결 관계를 이해함으로써, 개발자는 파일 관리 로직을 보다 효과적으로 설계하고, 데이터 무결성을 유지하며, 애플리케이션의 복잡성이 증가하더라도 파일을 안전하게 처리할 수 있습니다. 이러한 이해는 Active Storage를 활용하는 Rails 애플리케이션 개발에 있어 필수적인 기반 지식이 될 것입니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!