본문 바로가기

development/머신러닝 운영

EFS에 모델 구성요소 저장하고, 컨테이너에서 불러오는 구조로 전환하기

컨테이너 재빌드 없이 모델을 안정적으로 불러오기 위해, EFS에 모델 구성요소를 저장하고 Docker에서 직접 마운트하는 구조로 전환했다.


 왜 이 작업이 필요했을까?

이전까지는 모델 구성 요소들을 로컬에 저장하고, 컨테이너 안에서 로드하는 구조였다. 이 방식도 잘 작동하긴 했지만, 다음과 같은 불편함이 있었다:

  • 컨테이너를 새로 빌드하거나 다른 인스턴스에서 실행할 경우 모델을 다시 복사해야 함
  • 모델 파일 용량이 수 GB 단위라 이미지 용량도 불필요하게 커짐
  • 장기적으로 여러 서버에서 공유하려면 중앙 저장소가 필요함

그래서 Amazon EFS(Elastic File System)를 활용하기로 했다.


 EC2 인스턴스에 EFS 마운트

먼저 EFS를 EC2 인스턴스에 /mnt/efs 경로로 마운트했다. 이후 Stable Diffusion 구성 요소들을 여기에 저장:

/mnt/efs/saved_sd15/
├── unet.pth
├── vae.pth
├── text_encoder.pth
└── tokenizer/
    ├── tokenizer_config.json
    ├── vocab.json
    └── merges.txt

이 구조는 이전에 로컬에 저장했던 디렉토리 구조와 동일하게 유지해서 코드 수정 없이 그대로 가져다 쓸 수 있도록 했다.


main.py 수정 — 모델 경로만 바꿔주면 끝

기존 FastAPI 코드에서 모델 경로는 ./saved_sd15였다. 이를 EFS로 마운트된 경로로 변경:

load_dir = "/mnt/efs/saved_sd15"

그 외에는 모든 모델 로딩 로직이 동일하게 작동한다.


Docker에서 EFS 마운트하기

Docker Compose를 사용할 때는 EFS 경로를 그대로 컨테이너 내부로 마운트해주면 된다. 아래처럼 volumes 설정을 추가하면 된다:

volumes: - /mnt/efs/saved_sd15:/mnt/efs/saved_sd15

이 설정으로 인해 컨테이너 안에서도 main.py는 /mnt/efs/saved_sd15 경로에서 모델을 찾을 수 있게 된다.


구조적으로 정리하면 이런 흐름이다

[EC2 인스턴스]
   └── /mnt/efs/saved_sd15  ← EFS 마운트됨
           ├── unet.pth
           ├── vae.pth
           ├── text_encoder.pth
           └── tokenizer/

[Docker Compose]
   volumes:
     - /mnt/efs/saved_sd15:/mnt/efs/saved_sd15

[컨테이너 내부]
   main.py
     ↓
   load_dir = "/mnt/efs/saved_sd15"
     ↓
   StableDiffusionImg2ImgPipeline 조립

컨테이너는 EFS에 저장된 모델을 직접 로드하므로, 이미지 크기를 줄일 수 있고 재빌드 없이도 모델 교체가 가능해진다.


 검증 결과

  1. EFS 마운트 상태에서 컨테이너 실행
  2. API 요청 시 모델 구성 요소를 정상적으로 로드하고 이미지 생성 수행
  3. 네트워크나 외부 API 호출 없이 로컬 환경에서 완전하게 동작

정리

  1. EFS에 모델 구성 요소를 저장하면 모델 관리가 훨씬 유연해진다
  2. 컨테이너는 매번 새로 빌드할 필요 없이 모델만 교체 가능
  3. 서버 간 모델 공유도 가능해지고, 다중 인스턴스 운영도 대비할 수 있음

이번 구성은 모델을 안정적으로 운영하기 위한 인프라 기반을 다진 작업이었다.
다음 글에서는 EBS 볼륨을 얼마나 작게 잡을 수 있을지, 실제 모델 용량과 실행 환경에 필요한 최소 스토리지를 실험하며 최적 용량을 찾아가는 과정을 기록해보려 한다.

디스크 비용을 줄이면서도 안정적인 AI 인프라를 구축하고 싶은 분들께 도움이 될 수 있기를!