13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] Docker on NAS

  • [홈서버] Docker on NAS로 Plex 미디어 서버 구축 가이드

    [홈서버] Docker on NAS로 Plex 미디어 서버 구축 가이드

    [홈서버] Docker on NAS로 Plex 미디어 서버 구축 가이드

    집에 NAS(Network Attached Storage, 네트워크 저장소) 한 대 두고 영화나 드라마, 가족 사진까지 한 번에 정리하고 싶다는 생각, 한 번쯤 해보셨을 겁니다. 저도 홈랩(Home Lab, 집에서 운영하는 개인 실험실) 굴리면서 가장 먼저 손댄 게 바로 Docker on NAS 환경이었거든요. 처음엔 “그냥 NAS 앱스토어에서 설치하면 되는 거 아닌가?” 싶었는데, 실제로 써보니까 업데이트 관리나 볼륨(volume, 데이터 저장 경로) 분리, 백업, 마이그레이션까지 생각하면 컨테이너(container, 격리된 실행 환경)로 올리는 쪽이 훨씬 편하더라고요.

    특히 Plex는 미디어 서버 입문용으로 정말 많이 선택되는데, 처음 세팅할 때는 라이브러리 경로, 권한, 네트워크 설정에서 헷갈리기 쉽습니다. 저도 처음엔 스캔이 안 돼서 한참 헤맸고, 나중엔 파일명 규칙 때문에 메타데이터까지 꼬였었네요. 이번 글에서는 제가 직접 해보며 정리한 Docker on NAS 기반 Plex 미디어 서버 구축 흐름을, 너무 복잡하지 않게 실전 위주로 풀어보겠습니다.

    Docker on NAS 기반 Plex 미디어 서버 아키텍처 개요 이미지

    NAS, Docker, Plex, 클라이언트 기기 간 연결 구조를 한눈에 보여주는 개요 이미지입니다.

    1. 왜 Docker on NAS로 Plex를 올리냐는 질문부터

    쉽게 말해 Docker on NAS는 “NAS 위에 앱을 깔되, 운영체제와 적당히 분리해서 관리하는 방식”입니다. 이 방식의 장점은 생각보다 큽니다. NAS 제조사 전용 패키지보다 유연하고, 나중에 다른 장비로 옮길 때도 편하거든요. 제가 예전에 패키지 방식으로만 쓰다가 장비 교체할 때 설정 백업이 꼬여서 고생했었는데, 컨테이너로 분리하고 나서는 훨씬 수월했습니다.

    • 설정과 데이터를 분리하기 쉽습니다.
    • 업데이트 롤백이 상대적으로 단순합니다.
    • 다른 서비스와 격리되어 충돌 위험이 줄어듭니다.
    • 재배포가 쉬워 홈랩 운영이 깔끔해집니다.

    반대로 단점도 있습니다. 권한 매핑(user/group mapping), 네트워크 모드, 저장 경로를 이해하지 못하면 설치는 됐는데 실제로는 아무것도 안 돌아가는 상황이 생깁니다. 여기서 중요한 포인트! 컨테이너는 만능이 아니라, 구조를 이해하고 쓰면 편하고 모르고 쓰면 더 복잡해지는 도구입니다.

    2. Plex와 컨테이너 개념, 여기서 한 번 정리하고 가겠습니다

    Plex는 미디어 파일을 스캔해서 라이브러리를 만들고, TV나 모바일, 웹 브라우저에서 재생할 수 있게 해주는 플랫폼입니다. 쉽게 말해 “내가 가진 파일로 직접 넷플릭스 비슷한 개인 미디어 서버를 만드는 느낌”에 가깝습니다.

    여기서 자주 나오는 용어를 헷갈리지 않게 정리해보면 이렇습니다.

    용어 영문 쉽게 설명하면
    컨테이너 Container 앱을 격리해서 돌리는 작은 실행 단위
    이미지 Image 컨테이너를 만들기 위한 실행 템플릿
    볼륨 Volume / Bind Mount 설정 파일과 미디어를 연결하는 실제 저장 경로
    트랜스코딩 Transcoding 재생 기기에 맞게 영상 형식을 변환하는 작업
    호스트 네트워크 Host Network 컨테이너가 NAS 네트워크를 직접 사용하는 방식

    처음엔 이게 뭔가 싶었는데, 실제로 써보니까 핵심은 딱 두 가지더라고요. 설정 파일은 따로 보존하고, 미디어 폴더는 읽기 쉬운 경로로 명확히 연결하는 것. 이 두 가지만 잡아도 절반은 끝납니다.

    3. 구축 전에 준비할 것: 폴더 구조와 권한 설계

    실전 들어가기 전에 먼저 폴더 구조를 잡겠습니다. 저는 NAS에서 애플리케이션 설정과 실제 미디어 데이터를 분리하는 편입니다. 나중에 백업하거나 다른 장비로 옮길 때 진짜 편하거든요.

    1. 애플리케이션 설정용 폴더를 만듭니다.
    2. 영화, 드라마, 음악 등 미디어 폴더를 구분합니다.
    3. Plex가 읽을 수 있는 권한을 확인합니다.
    4. 트랜스코딩용 임시 폴더를 별도로 둡니다.

    예시 구조는 아래처럼 잡으면 무난합니다.

    /volume1/docker/plex/config
    /volume1/docker/plex/transcode
    /volume1/media/movies
    /volume1/media/tv
    /volume1/media/music

    만약 NAS 경로가 다르면 본인 환경에 맞게 바꾸시면 됩니다. 중요한 건 이름보다 역할 분리입니다. 제가 예전에 config랑 media를 한 폴더에 뒤섞어놨다가 백업 정책이 꼬여서 한 번 크게 정리한 적이 있었습니다. 그 뒤로는 무조건 분리합니다.

    권한은 왜 중요할까요?

    Plex 컨테이너가 미디어 폴더를 읽지 못하면 라이브러리 스캔 자체가 실패합니다. 웹 화면은 멀쩡하게 뜨는데 파일이 안 보이는 경우가 딱 이 케이스입니다. NAS 제조사 UI에서 공유 폴더 권한을 주거나, Linux 계열 셸이 가능하면 소유자와 그룹을 정리해두세요.

    4. Docker Compose로 Plex 컨테이너 배포하기

    이제 본격적으로 올려보겠습니다. 저는 단일 실행 명령보다 Docker Compose를 선호합니다. 이유는 간단한데요. 나중에 다시 봐도 구조가 남고, 수정도 쉽고, 백업 문서처럼 쓸 수 있거든요.

    services:
      plex:
        image: lscr.io/linuxserver/plex:latest
        container_name: plex
        network_mode: host
        environment:
          - PUID=1000
          - PGID=1000
          - TZ=Asia/Seoul
          - VERSION=docker
        volumes:
          - /volume1/docker/plex/config:/config
          - /volume1/docker/plex/transcode:/transcode
          - /volume1/media/movies:/movies
          - /volume1/media/tv:/tv
          - /volume1/media/music:/music
        restart: unless-stopped

    몇 가지 설명을 붙이면 좋겠습니다.

    • network_mode: host는 Plex에서 자주 쓰는 방식입니다. 기기 탐색(discovery)이나 스트리밍 연결에서 편한 경우가 많습니다.
    • PUID / PGID는 파일 권한 맞출 때 중요합니다.
    • /config는 Plex 설정과 라이브러리 정보가 저장되는 핵심 경로입니다.
    • /transcode는 변환 작업 중 임시 파일을 두는 공간입니다.

    실행은 아래처럼 하면 됩니다.

    docker compose up -d

    실행 후에는 로그를 확인해보세요.

    docker compose logs -f plex

    여기서 에러 없이 올라오고, NAS IP 기준으로 Plex 웹 초기 설정 화면이 열리면 일단 절반은 성공입니다. 드디어 됐다! 싶은 순간이 여기더라고요.

    Docker on NAS에서 Plex 컨테이너 볼륨과 네트워크 구성 이미지

    컨테이너 볼륨 연결과 호스트 네트워크 구성을 이해하기 쉽게 보여주는 설정 이미지입니다.

    5. Plex 초기 설정과 라이브러리 구성, 여기서 품질이 갈립니다

    Plex 웹 UI에 들어가면 서버 이름을 정하고 라이브러리를 추가하게 됩니다. 여기서 대충 해도 돌아가긴 하는데, 나중에 정리가 엉망이 되기 쉽습니다. 제가 직접 해보니 폴더 구조와 파일명 규칙이 정말 중요하더라고요.

    라이브러리 등록 팁

    1. 영화와 TV 시리즈는 라이브러리를 분리합니다.
    2. 각 라이브러리에 맞는 루트 폴더만 지정합니다.
    3. 폴더명과 파일명은 가능한 일관되게 유지합니다.
    4. 한글 파일명만으로 안 풀릴 때는 영문 원제 병기를 고려합니다.

    예를 들면 영화는 /movies, 시리즈는 /tv 식으로 나누는 편이 좋습니다. 한 폴더에 다 몰아넣으면 스캐너가 헷갈릴 수 있거든요. 처음엔 귀찮아 보여도 나중에 메타데이터가 깔끔하게 붙는 걸 보면 왜 이렇게 하는지 이해가 되실 겁니다.

    트랜스코딩 최적화는 어떻게 볼까요?

    모든 환경에서 무조건 트랜스코딩이 필요한 건 아닙니다. 클라이언트가 원본을 직접 재생(Direct Play, 원본 그대로 재생)할 수 있으면 서버 부담이 줄어듭니다. 그래서 저는 무조건 성능 튜닝부터 하기보다, 먼저 원본 파일 형식과 클라이언트 재생 능력을 확인하는 쪽을 권합니다.

    • 가능하면 자주 쓰는 기기에서 직접 재생되는 파일 형식을 늘립니다.
    • 트랜스코딩 임시 폴더는 여유 공간이 있는 저장소에 둡니다.
    • 동시 재생 사용자가 많으면 CPU 사용률을 함께 봅니다.
    • 하드웨어 가속(Hardware Acceleration, 하드웨어 기반 인코딩/디코딩)은 지원 환경에서만 검토합니다.

    여기서 중요한 포인트! 성능 최적화는 설정 몇 줄보다도 내가 어떤 파일을 어떤 기기에서 주로 재생하느냐가 더 크게 좌우합니다.

    6. ⚠️ 실제로 많이 겪는 문제와 해결법

    이 섹션은 이론보다 실전입니다. 저도 여기서 삽질 좀 했습니다. 특히 Plex와 컨테이너 조합은 설치보다 트러블슈팅이 더 중요합니다.

    문제 1. 웹은 열리는데 미디어가 안 보입니다

    대부분 권한 문제이거나, 라이브러리 경로를 컨테이너 내부 기준으로 잘못 넣은 경우입니다.

    • NAS 폴더 권한을 다시 확인합니다.
    • Compose의 마운트 경로와 Plex 라이브러리 경로가 일치하는지 봅니다.
    • 예: 호스트의 /volume1/media/movies를 컨테이너에서 /movies로 마운트했다면, Plex에는 /movies를 등록해야 합니다.

    문제 2. 메타데이터가 엉뚱하게 붙습니다

    파일명 규칙 문제일 가능성이 큽니다. 시리즈 시즌 표기나 연도 표기가 빠져 있으면 인식이 흔들립니다. 저도 예전에 파일명 뒤에 릴리즈 그룹명이 너무 길게 붙어서 매칭이 꼬였던 적이 있었습니다.

    • 영화는 제목과 연도를 분리합니다.
    • 시리즈는 시즌/에피소드 표기를 일관되게 맞춥니다.
    • 폴더를 장르별이 아니라 콘텐츠 타입별로 나눕니다.

    문제 3. 재생은 되는데 버벅입니다

    이건 저장소 속도, 네트워크, 클라이언트 코덱 지원, 트랜스코딩 부하가 복합적으로 엮입니다. 그래서 저는 한 번에 모든 걸 바꾸지 않고 아래 순서로 확인합니다.

    1. 같은 파일을 다른 기기에서 재생해봅니다.
    2. 서버 자원 사용률을 확인합니다.
    3. 직접 재생인지 트랜스코딩인지 Plex 대시보드에서 확인합니다.
    4. 트랜스코딩 폴더 위치와 여유 공간을 봅니다.

    문제 4. 업데이트 후 설정이 꼬일까 걱정됩니다

    그래서 /config 백업이 중요합니다. 이 경로만 잘 보존해도 복구 난도가 확 내려갑니다. 실제로 써보니까 컨테이너 자체보다 설정 데이터가 더 중요하더라고요.

    7. 결과 검증: 제대로 구성됐는지 확인하는 체크리스트

    세팅이 끝났다면 감으로 끝내지 말고 검증을 해보세요. 홈랩은 “되는 것처럼 보이는데 사실 안 되는 상태”가 은근 많습니다.

    1. Plex 웹 UI에 정상 로그인되는지 확인합니다.
    2. 영화/TV/음악 라이브러리가 각각 보이는지 확인합니다.
    3. 썸네일과 메타데이터가 정상적으로 붙는지 확인합니다.
    4. 같은 네트워크의 TV, 모바일, 브라우저에서 각각 재생 테스트를 해봅니다.
    5. 컨테이너 재시작 후에도 설정이 유지되는지 봅니다.

    추가로 저는 아래 명령으로 컨테이너 상태를 꼭 확인합니다.

    docker ps
    docker inspect plex
    docker compose logs --tail=100 plex

    이렇게 보면 실행 상태, 볼륨 마운트, 최근 오류를 빠르게 점검할 수 있습니다. 문제 생겼을 때 가장 먼저 봐야 하는 건 화려한 대시보드보다도 로그인데요. 이건 정말 경험상 그렇습니다.

    Plex 미디어 서버 결과 검증 대시보드 이미지

    라이브러리 인식, 재생 상태, 서버 동작 여부를 확인하는 결과 화면 예시입니다.

    8. 운영 최적화 팁: 오래 편하게 쓰려면

    여기부터는 구축 이후 이야기입니다. 한 번 올리고 끝이 아니라, 계속 편하게 쓰려면 운영 습관이 중요합니다.

    운영 항목 권장 방향 이유
    설정 백업 /config 정기 백업 복구 시간을 크게 줄입니다
    폴더 구조 영화/시리즈/음악 분리 메타데이터 인식 안정성
    업데이트 무작정 자동화보다 확인 후 적용 갑작스러운 변경 리스크 감소
    모니터링 로그와 저장공간 주기 확인 장애 조기 발견

    혹시 이런 경험 있으신가요? 평소엔 멀쩡했는데 어느 날 라이브러리 갱신이 멈추거나, 새 파일이 안 뜨는 경우요. 대체로 원인은 복잡하지 않더라고요. 저장 공간 부족, 권한 변경, 경로 오타, 또는 업데이트 후 재시작 누락 같은 기본적인 이슈가 많습니다. 그래서 저는 화려한 자동화보다 단순하고 추적 가능한 운영 방식을 더 선호합니다.

    9. 정리와 FAQ: Docker on NAS로 Plex를 시작하려는 분께

    Docker on NAS 환경에서 Plex를 운영하는 핵심은 대단한 튜닝이 아니라, 경로 분리, 권한 정리, 로그 확인입니다. 저도 처음엔 컨테이너만 올리면 끝일 줄 알았는데, 실제로는 운영 구조를 깔끔하게 만드는 쪽이 훨씬 중요하더라고요. 근데 한 번 구조를 잡아두면 정말 편합니다. 장비를 바꾸거나 다른 미디어 서버 도구를 시험해볼 때도 훨씬 유연해지거든요.

    다음 단계로는 리버스 프록시(Reverse Proxy, 역방향 프록시) 붙이기, HTTPS 적용, 자동 백업, 그리고 다른 컨테이너 서비스와의 연동까지 가보셔도 좋습니다. 이전 글에서 Docker 기초를 다뤘다면 그 흐름으로 이어 보셔도 좋고, 다음 글에서는 NAS 홈랩 운영 관점에서 백업 전략도 다뤄볼 예정입니다.

    자주 묻는 질문

    • Q. NAS 기본 앱으로 설치하면 안 되나요?
      A. 됩니다. 다만 이식성과 관리 편의성을 생각하면 컨테이너 방식이 장기적으로 유리한 경우가 많습니다.
    • Q. Docker Compose가 꼭 필요할까요?
      A. 필수는 아니지만, 재현성과 문서화 측면에서 추천합니다.
    • Q. Plex가 꼭 정답인가요?
      A. 아닙니다. 하지만 입문 난이도와 생태계 면에서 여전히 많이 선택되는 편입니다.
    Docker on NAS와 일반 설치 방식 비교 요약 이미지

    운영 방식의 차이와 선택 포인트를 한 장으로 정리한 요약 이미지입니다.

    정리하면 이렇습니다. Plex를 NAS에 올릴 때는 설치 자체보다 구조가 중요하고, 구조를 잡을 때는 Docker on NAS 방식이 꽤 강력합니다. 처음 세팅만 조금 공들여두면 이후 운영은 훨씬 편해집니다. 저도 여러 번 갈아엎고 나서야 이 결론에 도달했는데, 지금은 새 장비로 옮길 때도 부담이 많이 줄었네요. 이 글이 같은 삽질을 줄이는 데 도움이 되었으면 좋겠습니다.

  • [NAS] Immich NAS 성능 벤치마크와 최적화

    [NAS] Immich NAS 성능 벤치마크와 최적화

    [NAS] Immich NAS 성능 벤치마크와 최적화

    사진이 몇 만 장을 넘어가면, 그때부터는 단순히 저장만 하는 NAS(Network Attached Storage, 네트워크 저장소)로는 답이 잘 안 나오더라고요. 특히 Immich NAS 성능 이슈는 썸네일 생성, 머신러닝(Machine Learning, 기계학습) 분석, 모바일 업로드가 한꺼번에 몰릴 때 바로 체감됩니다. 저도 홈랩에서 Docker on NAS 환경으로 Immich를 굴려보면서 “왜 평소엔 멀쩡한데 오늘만 이렇게 느리지?” 같은 상황을 꽤 겪었습니다. 이번 글은 숫자를 지어내는 벤치마크가 아니라, 실제로 재현 가능한 측정 기준과 최적화 포인트를 정리한 글입니다.

    특히 Synology Docker 환경이나 TrueNAS 계열에서 Immich를 올려 쓰는 분들이라면, CPU만 볼 게 아니라 저장소 I/O(Input/Output, 입출력), 썸네일 작업 큐, PostgreSQL(포스트그레스큐엘, 데이터베이스) 설정까지 같이 봐야 합니다. 여기서 중요한 포인트! Immich 벤치마크는 단순 속도 테스트가 아니라 병목 구간을 찾는 과정이라는 점입니다.

    Immich NAS 성능 구성을 보여주는 전체 아키텍처 다이어그램

    Immich, PostgreSQL, Redis, 업로드 클라이언트, NAS 스토리지 경로가 한눈에 보이는 전체 구성도입니다.

    1. 왜 Immich NAS 성능이 생각보다 중요할까요?

    쉽게 말해 Immich는 그냥 사진을 쌓아두는 앱이 아닙니다. 업로드가 들어오면 메타데이터(metadata, 부가정보)를 정리하고, 썸네일(thumbnail, 미리보기 이미지)을 만들고, 검색을 위한 인덱스(index, 색인)를 쌓고, 경우에 따라 머신러닝 모델이 얼굴이나 장면 분석도 수행합니다. 그러니까 저장소 하나만 빠르다고 끝이 아니고, CPU, 메모리, 디스크, 컨테이너 배치가 같이 맞아야 하더라고요.

    제가 직접 해보니 초반엔 “NAS에 Docker만 올리면 되겠지”라고 생각했었는데, 실제로 써보니까 다음 세 가지가 체감 성능을 많이 갈랐습니다.

    • 대량 초기 인덱싱: 처음 라이브러리를 스캔할 때 CPU와 저장소 부하가 크게 올라갑니다.
    • 동시 업로드: 휴대폰 여러 대가 동시에 백업하면 I/O 대기 시간이 늘어납니다.
    • 썸네일/트랜스코딩: 작은 파일이 아주 많이 만들어져서 HDD 기반 볼륨은 생각보다 불리할 수 있습니다.

    혹시 이런 경험 있으신가요? 업로드는 끝났는데 앱에서 사진이 늦게 보이거나, 검색 결과가 한참 뒤에 반영되는 경우요. 이런 게 바로 사진 관리 솔루션으로서 Immich NAS 성능 문제로 이어집니다.

    2. Immich 벤치마크를 볼 때 기준을 먼저 정해야 합니다

    Benchmark(벤치마크, 성능 측정)라고 하면 숫자부터 보고 싶어지는데요, 사실 환경마다 차이가 너무 커서 절대 수치만 보면 오해하기 쉽습니다. CPU 세대, SSD 캐시 여부, 데이터셋 크기, 파일당 평균 용량, 컨테이너 리소스 제한이 다 다르거든요. 그래서 저는 아래처럼 작업 단위 기준으로 보는 걸 추천합니다.

    측정 항목 왜 중요한가 병목 힌트
    초기 라이브러리 스캔 시간 대량 사진 등록 시 전체 체감 속도에 직결 CPU 또는 디스크 I/O
    업로드 후 사진 표시 지연 모바일 백업 만족도와 직접 연결 썸네일 큐 적체, DB 응답 지연
    검색 반영 속도 메타데이터 처리 성능 확인 가능 DB, 인덱싱 작업 병목
    백그라운드 작업 중 CPU 점유 다른 NAS 서비스와 공존 가능성 판단 ML 작업, 트랜스코딩 부하
    스토리지 사용 패턴 썸네일/DB 경로 최적화 판단 작은 파일 쓰기 지연

    즉, Immich NAS 성능을 제대로 보려면 “몇 초 나왔냐”보다 “어떤 작업에서 느려졌냐”가 더 중요합니다. 저도 처음엔 이게 뭔가 싶었는데, 병목을 구간별로 나눠서 보니 훨씬 명확해지더라고요.

    3. Docker on NAS 환경에서 먼저 확인할 구성

    실전 들어가기 전에, 구성부터 정리하겠습니다. Synology Docker나 일반 리눅스 NAS, 그리고 TrueNAS 계열처럼 컨테이너 앱으로 Immich를 운영하는 경우에도 핵심은 비슷합니다.

    1. 사진 원본 라이브러리 경로와 데이터베이스 저장 경로를 구분합니다.
    2. 가능하면 PostgreSQL 데이터 디렉터리는 SSD 계층에 둡니다.
    3. 업로드 원본과 썸네일 캐시는 같은 풀(pool, 저장소 집합)에 둘지 분리할지 미리 결정합니다.
    4. 백그라운드 작업 시간대를 정합니다. 가족 사진 업로드가 많은 시간과 겹치면 체감이 확 떨어집니다.

    제가 홈랩에서 삽질 좀 했습니다 ㅎㅎ 원본 사진은 대용량 HDD 어레이(array, 디스크 묶음)에 두고, DB랑 캐시까지 같은 볼륨에 몰아뒀더니 작은 파일 I/O가 몰릴 때 응답성이 확 나빠졌습니다. 이후 DB와 캐시 계층을 더 빠른 스토리지로 분리하니 체감이 꽤 좋아졌습니다.

    예시 docker-compose.yml

    services:
      immich-server:
        image: ghcr.io/immich-app/immich-server:release
        container_name: immich_server
        depends_on:
          - redis
          - database
        environment:
          DB_HOSTNAME: database
          DB_USERNAME: immich
          DB_PASSWORD: change_me
          DB_DATABASE_NAME: immich
          REDIS_HOSTNAME: redis
        ports:
          - "2283:2283"
        volumes:
          - /mnt/nas/photo-library:/usr/src/app/upload
          - /etc/localtime:/etc/localtime:ro
        restart: unless-stopped
    
      immich-machine-learning:
        image: ghcr.io/immich-app/immich-machine-learning:release
        container_name: immich_ml
        volumes:
          - /mnt/fast/immich-model-cache:/cache
        restart: unless-stopped
    
      redis:
        image: redis:7
        container_name: immich_redis
        restart: unless-stopped
    
      database:
        image: tensorchord/pgvecto-rs:pg14-v0.2.0
        container_name: immich_db
        environment:
          POSTGRES_USER: immich
          POSTGRES_PASSWORD: change_me
          POSTGRES_DB: immich
        volumes:
          - /mnt/fast/postgres-immich:/var/lib/postgresql/data
        restart: unless-stopped

    버전은 예시일 뿐이고, 실제 배포 전에는 사용 중인 Immich 공식 문서와 현재 이미지 태그를 반드시 다시 확인하셔야 합니다. 중요한 건 구조입니다. 업로드 경로, 모델 캐시, 데이터베이스 경로를 어떻게 나누느냐가 성능에 직접 영향을 줍니다.

    Immich NAS 성능 최적화를 위한 스토리지 마운트 분리 구성 이미지

    업로드 볼륨, 데이터베이스 볼륨, 모델 캐시 볼륨을 서로 다른 스토리지 계층에 배치하는 구성 예시입니다.

    4. Immich 벤치마크를 위한 측정 절차

    이제 본격적으로 측정해보겠습니다. 여기서 제가 추천하는 방식은 동일 데이터셋으로 세 번 반복입니다. 첫 번째는 캐시가 비어 있는 상태, 두 번째는 일부 캐시가 쌓인 상태, 세 번째는 설정 변경 후 비교용입니다.

    1. 컨테이너 상태와 리소스 점유를 먼저 확인합니다.
    2. 테스트용 사진 세트를 준비합니다. 가능하면 파일 크기와 개수가 섞여 있어야 합니다.
    3. 업로드 직후부터 라이브러리 반영 완료 시점까지 시간을 기록합니다.
    4. CPU, 메모리, 디스크 I/O, 컨테이너 로그를 함께 봅니다.
    5. 설정을 하나만 바꾼 뒤 다시 측정합니다. 한 번에 여러 개 바꾸면 원인 파악이 안 됩니다.

    기본 확인 명령어

    docker ps
    
    docker stats
    
    docker logs -f immich_server
    
    docker logs -f immich_db
    
    df -h
    
    iostat -x 1

    여기서 iostat는 디스크 대기 시간을 보기 좋습니다. 만약 NAS 운영체제에서 직접 설치가 어렵다면, 제공되는 모니터링 도구로 대체해도 됩니다. Synology에서는 리소스 모니터(resource monitor), TrueNAS 계열에서는 대시보드와 풀 I/O 그래프를 같이 보면 감이 옵니다.

    업로드 테스트 예시

    time rsync -avh ./sample-photos/ /mnt/nas/photo-library/import-test/
    
    find /mnt/nas/photo-library/import-test -type f | wc -l

    실제로 써보니까 업로드 자체보다, 그 뒤에 이어지는 백그라운드 잡(background job, 백그라운드 작업)이 더 오래 걸리는 경우가 많았습니다. 그래서 저는 업로드 종료 시점과 앱에서 사진이 정상 탐색되는 시점을 따로 적어뒀습니다.

    5. 제가 자주 본 병목 구간과 최적화 포인트

    Immich NAS 성능을 끌어올릴 때는 무작정 CPU를 올리는 것보다 병목별 대응이 더 효과적입니다.

    • DB가 느린 경우: PostgreSQL 데이터 경로를 더 빠른 스토리지로 이동해보세요. Synology Docker나 TrueNAS Docker 환경이라면 기본 스토리지 계층을 확인하고 SSD 풀로 분리하는 걸 추천합니다.
    • 썸네일 생성이 밀리는 경우: 원본 사진 경로는 HDD여도, 캐시와 DB는 SSD 계층이 유리합니다.
    • 컨테이너 간 I/O 경쟁: Immich 외에 미디어 서버, 백업 작업, 다운로드 작업이 동시에 돌면 NAS 전체 응답성이 떨어집니다.
    • 메모리 부족: 스왑(swap, 디스크 기반 가상 메모리)이 발생하면 체감 성능이 급격히 무너집니다.

    저도 처음엔 CPU 사용률만 보고 있었는데, 근데 여기서 함정이 있더라고요. CPU는 40~50% 정도인데도 체감은 엄청 느릴 수 있습니다. 이런 경우는 대체로 디스크 대기나 작은 파일 쓰기 병목이었습니다.

    튜닝 전후를 비교할 때 체크할 것

    항목 튜닝 전 튜닝 후 기대 변화
    업로드 후 썸네일 반영 지연이 길고 들쭉날쭉 반영 속도가 더 일정해짐
    DB 응답 검색/스크롤 시 버벅임 목록 탐색이 부드러워짐
    동시 작업 시 NAS 반응성 다른 서비스도 같이 느려짐 영향 범위가 줄어듦
    백그라운드 작업 완료 시간 예측이 어려움 대체로 패턴이 안정적

    6. ⚠️ 트러블슈팅: 실제로 많이 겪는 문제

    이 섹션은 진짜 경험담 위주입니다. 저도 처음엔 헷갈렸는데, 아래 문제들은 꽤 자주 만났습니다.

    1) 볼륨 권한 문제로 업로드는 되는데 후처리가 꼬이는 경우

    컨테이너 내부 사용자 권한과 NAS 실제 디렉터리 권한이 안 맞으면 생기는 문제입니다. 파일은 생기는데 일부 작업이 실패하거나, 썸네일 생성 로그에 에러가 남을 수 있습니다.

    ls -al /mnt/nas/photo-library
    id
    
    docker exec -it immich_server sh

    해결 포인트: 컨테이너에서 접근하는 UID/GID와 NAS 공유 폴더 권한을 맞추는 겁니다.

    2) 데이터베이스를 느린 HDD 볼륨에 둔 경우

    사진 원본은 순차 읽기 비중이 커서 HDD도 어느 정도 버티는데, DB는 작은 쓰기와 랜덤 접근이 잦거든요. 그래서 같은 HDD 풀에 몰아두면 검색 반영과 라이브러리 응답성이 같이 떨어질 수 있습니다.

    해결 포인트: PostgreSQL 경로를 더 빠른 SSD 계층으로 옮기고, 원본 라이브러리와 분리해보세요. 특히 Synology Docker나 TrueNAS Docker 환경에서는 별도 SSD 볼륨을 준비해두는 것이 중요합니다.

    3) 머신러닝 작업이 몰리면서 NAS 전체가 답답해지는 경우

    얼굴 인식이나 장면 분석이 동시에 많이 돌면 CPU 자원을 꽤 씁니다. 이럴 때는 백업 작업, 미디어 인덱싱 작업과 시간이 겹치지 않게 분산하는 게 좋습니다.

    해결 포인트: 초기 분석은 야간으로 미루고, 낮에는 업로드 위주로 운영해보세요.

    Immich NAS 성능 벤치마크 결과를 확인하는 모니터링 대시보드 이미지

    업로드 이후 백그라운드 작업 큐가 쌓이고, CPU와 디스크 사용량이 함께 움직이는 모습을 보여주는 대시보드 예시입니다.

    7. 검증: 어떤 결과가 나오면 최적화가 잘 된 걸까요?

    여기서 중요한 건 절대 점수보다 일관성입니다. 제가 직접 해보니 최적화가 잘 된 환경은 다음 특징이 있었습니다.

    • 업로드 후 사진 표시까지 걸리는 시간이 들쭉날쭉하지 않습니다.
    • 대량 업로드 중에도 웹 인터페이스 탐색이 완전히 무너지지 않습니다.
    • 검색과 스크롤이 이전보다 자연스럽게 유지됩니다.
    • 백그라운드 작업이 끝나는 패턴이 예측 가능해집니다.

    즉, Immich 벤치마크의 핵심은 “최고 속도”보다 “실사용 중 안정성”입니다. 숫자 하나만 보고 판단하면 실제 사용감과 어긋날 때가 많습니다.

    가능하다면 아래처럼 간단한 기록표를 만들어 두세요.

    # 예시 기록 항목
    # 테스트 날짜
    # 사진 수 / 총 용량
    # 원본 저장소 위치
    # DB 저장소 위치
    # 업로드 완료 시각
    # 라이브러리 반영 완료 시각
    # 썸네일 생성 완료 체감 시각
    # CPU / 메모리 / I/O 특이사항

    이렇게 해두면 Synology Docker 환경과 다른 NAS 환경을 비교할 때도 훨씬 객관적으로 볼 수 있습니다. 다음 글에서는 모니터링 스택까지 붙여서 좀 더 자동화된 방식으로 다뤄볼 예정입니다.

    8. 정리 + 자주 묻는 질문

    정리해보면, 사진 관리 솔루션으로서 Immich는 정말 매력적입니다. 다만 NAS 위에서 잘 돌리려면 애플리케이션만 보는 게 아니라 스토리지 구조와 컨테이너 배치까지 같이 봐야 하더라고요. 저도 처음엔 단순히 이미지 올리고 끝인 줄 알았는데, 실제로는 Docker on NAS 환경 설계가 성능의 절반 이상을 좌우했습니다. 드디어 됐다! 싶은 순간은, 업로드와 탐색이 동시에 자연스럽게 돌아갈 때 오더군요.

    • Q. CPU가 높지 않은데도 느린 이유는 뭔가요?
      A. 디스크 I/O나 DB 응답 지연일 가능성이 큽니다. 작은 파일 쓰기가 많은 구간을 의심해보세요.
    • Q. 사진 원본도 SSD에 둬야 하나요?
      A. 꼭 그렇진 않습니다. 다만 DB와 캐시 계층은 더 빠른 스토리지가 체감에 유리합니다.
    • Q. TrueNAS Docker로 검색해도 되나요?
      A. 검색 키워드로는 많이 쓰지만, 실제 운영 방식은 NAS 플랫폼 버전에 따라 앱 또는 컨테이너 구성 방식이 다를 수 있으니 현재 환경 기준으로 확인하시는 게 좋습니다.
    • Q. Immich NAS 성능 최적화에서 가장 먼저 할 일은?
      A. 원본, DB, 캐시 경로를 분리해서 병목 위치를 확인하는 겁니다.
    Immich NAS 성능 최적화 전후를 요약한 인포그래픽

    병목 구간, 저장소 배치, 체크리스트를 한 장으로 요약한 인포그래픽입니다.

    이전 글에서 NAS 볼륨 설계와 백업 전략을 다뤘다면, 이번 글은 그 위에 Immich를 얹었을 때의 실제 운영 포인트에 더 가깝습니다. 다음 글에서는 로그와 모니터링을 붙여서, 어떤 지표를 보면 병목이 바로 보이는지 이어서 정리해보겠습니다. Immich NAS 성능 문제로 답답하셨다면, 오늘은 숫자보다 구조부터 다시 보시는 걸 추천드립니다.