[자작 NAS] 시놀로지 포토 탈출기: Immich 구축부터 내부망 대용량 사진 이전까지 완벽 가이드

시놀로지 포토의 느린 로딩과 용량 한계에 지치셨나요? 쾌적한 구글 포토급 오픈소스 갤러리 'Immich(이믹)' 구축부터, 수백 기가의 기존 NAS 사진을 멈춤 없이 로컬망으로 초고속 이전하는 방법까지 초보자 눈높이에서 완벽하게 정리했습니다.

[자작 NAS] 시놀로지 포토 탈출기: Immich 구축부터 내부망 대용량 사진 이전까지 완벽 가이드

스마트폰 사진 용량이 200GB를 넘어가면 아이폰 용량 경고가 뜨고, 기존 시놀로지 포토(Synology Photos)는 점점 느려집니다. 구글 포토처럼 빠르고 똑똑하면서도 내 하드디스크에 안전하게 보관할 수 있는 오픈소스 사진 플랫폼 Immich(이믹)를 세팅하고, 기존 NAS의 사진을 초고속으로 이전하는 방법을 정리합니다.


1. 왜 Synology Photos를 두고 Immich로 넘어갈까?

  • 압도적인 속도와 편의성: 시놀로지 포토는 사진이 수만 장 넘어가면 썸네일 로딩이 버벅입니다. 반면 Immich는 최신 웹 기술과 데이터베이스를 써서 구글 포토 수준으로 스크롤이 부드럽습니다.
  • 똑똑한 AI 검색 (머신러닝): 시놀로지 포토는 태그나 인물 분류 정도만 지원하지만, Immich는 "빨간 모자를 쓴 강아지", "생일 케이크"처럼 문장으로 검색해도 사진을 정확히 찾아냅니다.
  • 라이브 포토 완벽 지원: 아이폰 특유의 라이브 포토(사진+짧은 동영상) 재생이 웹과 앱 모두에서 자연스럽습니다.
  • 가족 공유의 편리함: 가족 구성원별 계정을 분리하면서도 원하는 앨범만 쉽게 합쳐서 볼 수 있습니다.

2. 200GB 사진을 옮기는데 왜 350~400GB 용량이 필요할까?

"내 사진이 200GB인데, 왜 서버 디스크는 350~400GB가 남아있어야 할까요?"

Immich는 원본 사진만 덜렁 저장하는 단순 외장하드가 아니기 때문입니다. 업로드가 들어오면 뒷단에서 다음과 같은 파일들을 추가로 만듭니다.

  1. 초고속 썸네일 생성 (작은 사진, 큰 사진): 휴대폰이나 브라우저에서 버벅거리지 않고 바로바로 뜨도록 모든 사진의 가벼운 압축본(WebP 규격)을 따로 만듭니다.
  2. 동영상 트랜스코딩 (인코딩 파일): 아이폰의 고화질 비디오나 4K 영상을 웹 브라우저가 버벅임 없이 바로 스트리밍할 수 있도록 웹용 영상 파일(.mp4)을 추가로 변환해 둡니다.
  3. 얼굴 인식 및 AI 벡터 데이터: 사진 속 인물 얼굴, 사물 검색용 AI 인덱스 데이터가 데이터베이스(PostgreSQL)에 차곡차곡 쌓입니다.

따라서 원본 사진 크기의 약 1.3배 ~ 1.5배는 여유 공간이 있어야 서버가 디스크 부족으로 멈추지 않고 쾌적하게 동작합니다.


3. [준비] 새로운 NAS에 저장 폴더 만들기

Immich가 사용할 폴더를 새로운 NAS의 넉넉한 하드 공간에 미리 만들어 줍니다.

  1. 시놀로지 DSM에 로그인한 뒤 File Station을 엽니다.
  2. 용량이 넉넉한 볼륨(예: volume1)으로 이동합니다.
  3. docker 폴더 아래에 immich 폴더를 만들고, 그 안에 다음 3개 폴더를 생성합니다.
  • immich-uploads : 원본 사진과 비디오가 저장될 메인 공간
  • immich-model-cache : AI 얼굴 인식 및 검색 모델이 들어갈 공간
  • immich-postgres-data : 사진 정보(메타데이터)를 기록할 DB 공간

4. Portainer로 Immich 설치하기

4-1. Stack 생성

  1. Portainer 웹 UI 접속 → StacksAdd stack 클릭
  2. 이름(Name)에 immich 입력
  3. 아래의 docker-compose.yml 내용을 그대로 붙여넣습니다. 본인의 환경에 맞춰 볼륨 경로(/volume1/docker/immich/...)만 수정해 주세요.
services:
  immich:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    ports:
      - '2283:2283'
    volumes:
      - /volume1/docker/immich/immich-uploads:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    environment:
      - DB_HOSTNAME=database
      - DB_USERNAME=${SERVICE_USER_POSTGRES}
      - DB_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
      - DB_DATABASE_NAME=${DB_DATABASE_NAME:-immich}
      - REDIS_HOSTNAME=redis
      - TZ=${TZ:-Asia/Seoul}
    depends_on:
      redis:
        condition: service_healthy
      database:
        condition: service_healthy
    restart: always

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    volumes:
      - /volume1/docker/immich/immich-model-cache:/cache
    environment:
      - TZ=${TZ:-Asia/Seoul}
    restart: always

  redis:
    container_name: immich_redis
    image: redis:7.4-alpine
    healthcheck:
      test:
        - CMD
        - redis-cli
        - PING
      interval: 5s
      timeout: 10s
      retries: 20
    restart: always

  database:
    container_name: immich_postgres
    image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0
    environment:
      POSTGRES_USER: ${SERVICE_USER_POSTGRES}
      POSTGRES_PASSWORD: ${SERVICE_PASSWORD_POSTGRES}
      POSTGRES_DB: ${DB_DATABASE_NAME:-immich}
      POSTGRES_INITDB_ARGS: --data-checksums
      DB_STORAGE_TYPE: ${DB_STORAGE_TYPE:-SSD}
    volumes:
      - /volume1/docker/immich/immich-postgres-data:/var/lib/postgresql/data
    healthcheck:
      test:
        - CMD-SHELL
        - pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}
      interval: 5s
      timeout: 20s
      retries: 10
    restart: always

4-2. 환경 변수(Environment variables) 입력

화면 아래쪽 Environment variables에 아래 내용을 추가합니다. 비밀번호는 꼭 원하는 문자로 변경하세요.

IMMICH_VERSION=release
TZ=Asia/Seoul
SERVICE_USER_POSTGRES=immich_user
SERVICE_PASSWORD_POSTGRES=여기에_원하는_복잡한_비밀번호_입력
DB_DATABASE_NAME=immich
DB_STORAGE_TYPE=SSD

모두 입력했다면 하단의 Deploy the stack 버튼을 누릅니다. 잠시 후 4개의 컨테이너가 정상적으로 실행됩니다.


5. Nginx Proxy Manager (NPM) 외부 접속 설정

외부에서 나만의 도메인(예: immich.yourdomain.com)으로 접속하기 위해 프록시 설정을 진행합니다. 대용량 동영상 업로드 시 오류가 나지 않도록 세부 옵션을 꼼꼼히 챙겨야 합니다.

  1. Details 탭:
  • Scheme: http
  • Forward Hostname / IP: <새로운_NAS의_내부IP> (예: 192.168.x.x)
  • Forward Port: 2283
  • Cache Assets: 끄기 (OFF) (사진 동기화 오류 방지)
  • Websockets Support: 켜기 (ON) (실시간 상태 갱신 필수)
  1. SSL 탭:
  • 발급받은 인증서 선택 후 Force SSL, HTTP/2 Support, HSTS Enabled 모두 켜기
  1. Advanced 탭 (중요):
  • 대용량 업로드 시 413 용량 초과 에러나 시간 초과로 끊기는 것을 막기 위해 아래 코드를 빈칸에 그대로 붙여넣습니다.
# 업로드 파일 크기 무제한
client_max_body_size 0;

# 긴 업로드 시간 타임아웃 연장
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;

# 웹소켓 연결 보장
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";


6. 초기 세팅 & 전송용 API Key 생성

  1. 웹 브라우저에서 본인의 주소([https://immich.yourdomain.com](https://immich.yourdomain.com))로 접속하여 초기 관리자 계정을 만듭니다.
  2. 초기 설정 화면 중 "지도 기능은 외부 타일 서비스에 의존합니다"라는 안내가 나오면 Yes를 누릅니다. (아이폰 사진의 GPS 위치를 지도 화면에 예쁘게 띄워주는 기능입니다.)
  3. 우측 상단 프로필 아이콘 클릭 → Account SettingsAPI Keys로 이동합니다.
  4. New API Key를 눌러 새 키를 발급받고 메모장에 복사해 둡니다.

7. 구형 NAS에서 신규 Immich NAS로 초고속 다이렉트 전송

내 PC로 수백 기가의 사진을 일일이 내려받았다가 다시 올릴 필요가 없습니다. 두 대의 NAS가 같은 공유기(로컬 네트워크)에 연결되어 있다면, 집 안 내부망(LAN)을 통해 원본 사진을 초고속으로 직접 전송할 수 있습니다.

7-1. 기존 NAS의 사진 백업 경로 확인하기

  1. 기존 사진이 보관된 구형 NAS에 SSH로 접속합니다.
  2. 터미널에서 내 사진 백업 폴더의 실제 경로를 확인합니다.
  • 개인 백업 경로 예시: /volume1/homes/<사용자계정>/Photos/MobileBackup/iPhone
  • 공유 공간 경로 예시: /volume1/photo/MobileBackup

7-2. 백그라운드 초고속 전송 실행

기존 NAS 터미널에 아래 명령어를 띄어쓰기 훼손 없이 입력합니다. < >로 묶인 부분만 본인 환경에 맞게 변경하세요.

docker run -d \
  --name immich-sync \
  -v "<기존NAS_사진_절대경로>":/import:ro \
  -e IMMICH_INSTANCE_URL="http://<새로운NAS_내부IP>:2283/api" \
  -e IMMICH_API_KEY="<발급받은_API키>" \
  ghcr.io/immich-app/immich-cli:latest \
  upload --skip-hash --recursive /import

명령어 속 핵심 옵션 설명:http://<새로운NAS_내부IP>:2283/api : 외부 도메인 대신 공유기 내부망으로 쏘기 때문에, 업로드 용량 제한이나 프록시 에러 없이 최고 속도(기가비트)로 들어갑니다.--skip-hash : 사진이 수만 장일 때 구형 NAS가 파일 해시를 계산하느라 멈추는 병목 현상을 건너뛰고 즉각 전송을 시작합니다.-d : 백그라운드 실행입니다. SSH 터미널 창을 꺼도 두 NAS가 알아서 전송을 끝까지 마칩니다.

7-3. 진행 상태 및 정상 작동(멈춤) 여부 확인하기

대용량 전송 시 화면에 아무 변화가 없으면 "서버가 뻗은 건가?"하고 불안할 수 있습니다. 이때는 아래 두 가지 명령어로 상태를 정확히 체크할 수 있습니다.

  • 실시간 전송 상황 보기 (로그 확인):
docker logs -f immich-sync

(사진들이 올라가는 프로그레스 바가 보입니다. 화면에서 빠져나오려면 언제든 Ctrl + C를 누르면 됩니다. 빠져나와도 전송은 멈추지 않습니다.)

  • 진짜 멈춘 건지, 일하는 중인지 확인하기 (시스템 자원 확인):
    로그가 멈춰있을 때 서버가 뻗은 것인지 확인하려면 아래 명령어를 입력합니다.
docker stats immich-sync

(마찬가지로 확인 후 빠져나올 때는 Ctrl + C를 누릅니다.)

  • CPU % / MEM USAGE: 수치가 0%에 멈춰있지 않고 계속 오르내린다면, NAS가 수만 장의 파일을 열심히 읽고 정리하는 정상 상태입니다.
  • NET I/O: 이 수치가 계속 올라가고 있다면 새로운 NAS로 데이터가 콸콸 전송되고 있다는 뜻입니다.
  • 완료 후 임시 컨테이너 지우기:
    업로드가 모두 끝나면 아래 명령어로 1회성 전송 컨테이너를 깔끔하게 지워줍니다.
docker rm immich-sync