Immich에서 Windows PC를 외부 워커로 붙여 트랜스코딩 작업하기
- Authors

- 이름
- 이융희
- Social
- [email protected]
Immich는 Google Photos 대안으로 자주 언급되는 대표적인 셀프호스팅 사진·영상 관리 오픈소스입니다. 저희는 시놀로지 나스(Synology NAS)에 Immich를 설치하여 사용중인데요, 아무래도 나스가 파일 저장 및 백업 등의 작업에는 특화되어 있지만 미디어 트랜스코딩과 같은 작업에는 좋은 성능을 내지 못하기 때문에 대량의 트랜스코딩 작업을 맡기면 한 달이 넘는 시간 동안 자산들을 변환하는 일이 생기기도 합니다.
시놀로지 나스가 아니더라도 소규모 사무실이나 홈랩에서 이러한 셀프호스트 앱을 사용하는 경우 24시간 서버를 켜 두어야 하는 특성 상 고성능 워크스테이션을 활용하기보다는 저전력 특화 서버를 사용하는 경우가 대부분일 겁니다. 일반적인 서버들 역시 대부분 그래픽 연산 능력은 부족한 편입니다.

저희는 이번에 Immich의 외부 라이브러리를 통해 마운트한 수많은 사진과 영상들의 폴더 구조를 크게 개편하였습니다. Immich가 직접 관리하는 업로드 라이브러리는 DB와 저장 구조를 함께 관리하는 영역이라 정합성을 유지하기가 상대적으로 쉽습니다. 파일 이동도 앱 내에서 할 수 있고, 그러면 DB도 자동으로 따라갑니다. 반면 외부 라이브러리는 경로 기반으로 파일을 인식하므로, 폴더 구조를 외부에서 바꾸면 재스캔 과정에서 기존 자산과의 연결이 끊기고 새 자산처럼 잡힐 수 있습니다. 특히 기존에 달아둔 메타데이터나 매핑은 그대로 이어지지 않을 수 있습니다.(나중에 업데이트를 통해 이 부분도 지원이 되면 좋겠네요)
이렇게 되면 기존에 트랜스코딩한 변환 영상들과 실제 파일의 매칭이 깨지기 때문에 모두 다시 스캔하고 트랜스코딩을 해야합니다. 저희는 트랜스코딩할 영상 자산만 7,000개가 넘었기 때문에 정말 엄청난 일이었죠.

실제로 해당 작업을 시작한 이후 나스의 CPU 사용량은 24시간 내내 100% 근처를 찍었고, Immich가 아닌 다른 작업을 하는데도 속도가 느려지거나 응답이 없는 상황에 이르렀습니다. 이런 상태로 한 달 넘게 업무나 대고객 서비스를 제공하기에는 어려움이 있습니다.
다행히 Immich는 여러 인스턴스를 병렬로 붙이거나 API, 백그라운드 작업을 분리해 운용할 수 있게 설계되어 있습니다.(관련 내용: Immich 공식 스케일링 가이드) 머신러닝도 작업도 여러 원격 컨테이너로 분리할 수 있고, 트랜스코딩이나 외부 자산 스캔 등을 포함한 작업들 역시 분리가 가능합니다.
저희가 할 구성은 구조적으로는 microservices 워커를 분리하는 것이며, 그 중 체감 효과가 가장 큰 작업이 트랜스코딩입니다. 이를 활용하여 대량 작업 시 Immich가 설치된 메인 서버가 아닌 다른 기기의 자원을 사용하여 빠르게 작업을 수행하는 방법에 대해 알아보겠습니다.
Immich의 마이크로서비스 워커 분리 작업하기
오늘 포스트에서 설명할 과정은 정확한 모든 과정을 웹에서 찾기가 쉽지 않습니다. 이 구성이 한 번에 설명되지 않는 이유는 공식 문서가 각 층위를 나눠 설명하기 때문입니다.
Immich의 스케일링 문서는 여러 인스턴스가 같은 Postgres, 같은 Redis, 같은 파일 마운트를 공유해야 한다는 원칙만 제시하고, 실제 구현은 환경마다 너무 달라 구체 절차를 따로 적지 않습니다. 반면 외부 라이브러리 문서는 파일이 같은 머신에 있다는 전제를 깔고 설명합니다. 외부 라이브러리의 메타데이터나 읽기전용 동작, 사이드카 메타데이터 같은 내용도 기능 문서와 FAQ, XMP 문서에 나뉘어 있어 한 페이지에서 전체 그림을 잡기 어렵습니다. 오늘 포스트는 그러한 과정을 한 번에 정리하여 설명합니다.
나스의 프로젝트 변경 및 빌드
먼저 시놀로지 나스의 컨테이너 매니저(Container Manager) 앱의 프로젝트 메뉴에서 immich 프로젝트를 선택한 후 세부사항을 눌러봅니다. 그리고 편집을 위해 우선 우측 상단의 [중지]를 누르고, 프로젝트 중지가 끝나면 YAML 구성 탭으로 이동합니다. 이곳으로 가 보시면 YAML 파일의 내용을 보고 편집할 수 있을 겁니다. 아래 내용들을 추가합니다.
...
services:
immich-server:
...
environment:
IMMICH_WORKERS_INCLUDE: "api"
...
redis:
...
ports:
- "6379:6379"
...
database:
...
ports:
- "55432:5432" # Synology NAS 기준으로 기본 5432 포트는 이미 내부 포트로 사용중
...
위 변경 내용은 기존 Immich의 호스트 서버에서 api 모드, 즉 웹서버 접속과 DB 운용 등의 작업만 하도록 설정하는 내용입니다. 이후 아래에서 데스크탑 PC 쪽에 microservices 워커를 포함할 것입니다. 또한 원격 서버에서 DB에 바로 접속할 수 있도록 DB의 접속 포트를 외부에 여는 작업을 하는데, 내부망에서만 사용할 거라면 큰 문제 없지만 아예 다른 네트워크에서 접속하도록 포트포워딩을 하는 데에는 주의가 필요합니다.
이렇게 편집하고 나서는 [저장 및 빌드]를 눌러 해당 내용을 저장하고 다시 빌드해 줍니다.(빌드 과정은 변경된 .yml 파일의 내용을 반영하기 위해 필요합니다)
프로젝트가 다시 빌드되고 immich가 시작된 다음 접속해 보면, 이제 관리 페이지의 작업 대기열 메뉴에서는 진행중인 트랜스코딩 작업이 없는 것으로 나올 겁니다.
Docker Desktop으로 PC 에서 Immich 워커 실행
이제 트랜스코딩 작업을 위탁할 고성능 데스크탑 PC에서 도커 앱을 사용하기 위한 Docker Desktop을 설치할 겁니다.
위 경로에서 Windows용 Docker Desktop을 내려받아 설치할 수 있습니다. 관련하여 설치를 진행하고 나면 이제 Windows의 PowerShell에서 docker 명령어를 사용할 수 있게 됩니다.
PC의 특정 폴더에 접속하여 먼저 compose.yml 파일과 .env 파일(파일명 없이 확장자만 .env로 작성하면 됩니다)을 만들어주어야 합니다. 이 두가지가 Immich 트랜스코딩 작업을 하도록 하는 앱 설치 및 실행의 핵심적인 내용을 담고있습니다.
참고로 아래 내용을 편집하기 전에 나스에서 사용중인 계정의 uid와 gid를 알아야 합니다. 해당 방법을 모른다면 아래 매뉴얼을 참고하여 먼저 확인한 후 진행하는 게 좋습니다.
↳시놀로지 나스에서 UID, GID 확인하기
이번 가이드에서는 나스의 경로를 CIFS 볼륨으로 잡습니다만, 좀 더 정석으로 가려면 WSL2 Ubuntu를 설치해서 거기에 마운트를 하고 연결하는 것이 권장됩니다.(도커 자체가 마운트 성능과 파일 변경 이벤트 처리 부분에서 Windows 파일시스템보다 리눅스 쪽을 선호합니다)
Ubuntu를 사용하지 않는 이유는 이것이 단발적인 작업 성격이 강하고, 이를 위해 WSL2 배포판 설치, 마운트 관리, 경로 관리까지 추가하면 운영 복잡도가 너무 커지기 때문입니다.
name: immich-remote-worker
services:
immich-microservices:
container_name: immich_remote_microservices
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
env_file:
- .env
environment:
IMMICH_WORKERS_EXCLUDE: "api"
volumes:
- immich-library:/data # 만약 예전에 Immich를 구성했다면 나스 쪽 경로가 "/usr/src/app/upload" 등 다른 것으로 되어있을 수 있으니, 거기에 맞추어 변경
- photo-lib:/mnt/media/exphotos # 만약 추가로 필요한 볼륨 연결이 있다면 여기에 입력
restart: always
healthcheck:
disable: false
immich-machine-learning:
container_name: immich_remote_ml
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
env_file:
- .env
restart: always
volumes:
immich-library:
driver_opts:
type: cifs
o: "username=${NAS_USER},password=${NAS_PASS},uid=${NAS_UID},gid=${NAS_GID},vers=3.0"
device: "//[나스 내부 아이피]/immich-app/library" # NAS의 실제 경로를 여기에 입력합니다
photo-lib:
driver_opts:
type: cifs
o: "username=${NAS_USER},password=${NAS_PASS},uid=${NAS_UID},gid=${NAS_GID},vers=3.0,ro"
device: "//[나스 내부 아이피]/photo" # NAS의 실제 경로를 여기에 입력합니다
TZ=Asia/Seoul
IMMICH_VERSION=release
DB_HOSTNAME=나스의 내부망 기준 아이피 주소
DB_PORT=55432
DB_USERNAME=postgres
DB_PASSWORD=immich DB의 암호
DB_DATABASE_NAME=immich
REDIS_HOSTNAME=나스의 내부망 기준 아이피 주소
REDIS_PORT=6379
IMMICH_WORKERS_INCLUDE=microservices
NAS_USER=나스에서 사용중인 아이디
NAS_PASS="나스 아이디에 해당하는 패스워드"
NAS_GID=해당 아이디의 GID
NAS_UID=해당 아이디의 UID
NOTE
Windows의 네트워크 드라이브 연결 기능으로 마운트한 경로(X:, Y:\ 등의 드라이브 문자열 경로)를 사용할 경우 깊은 경로에 대한 인식이 정상적으로 되지 않을 가능성이 높기 때문에 저희는 UNC 기반의 경로 연결을 해야합니다.
이유는 컨테이너가 보는 호스트와 사용자가 Windows 탐색기에서 보는 호스트가 같지 않기 때문입니다. 도커의 bind mount는 클라이언트가 아니라 도커 데몬이 돌아가는 호스트 기준으로 생성되고, Docker Desktop의 데몬은 Windows 본체가 아니라 내부 리눅스 VM에서 실행됩니다.
게다가 Windows의 드라이브 매핑 문자는 로그온 세션별로 관리되므로, 관리자 권한이나 서비스, 다른 보안 컨텍스트에서는 같은 Y:, Z:\ 드라이브가 그대로 보장되지 않습니다. 반면 CIFS 기반 볼륨은 도커가 동작하는 리눅스 쪽에서 나스 공유를 직접 마운트하므로 컨테이너 입장에서 일관적으로 볼 수 있습니다. Immich의 FAQ도 Windows 환경에서는 호스트 마운트 대신 도커 안에서 CIFS/SMB 볼륨을 직접 마운트하는 예시를 따로 안내합니다.
이 파일들을 생성했다면, 이제 PowerShell을 켭니다. PowerShell은 Windows의 시작 버튼을 누르고 [PowerShell]을 입력하면 나타나는 앱을 클릭하여 실행할 수 있습니다.
만약 C:\docker\Immich-ms 라는 폴더에 해당 .env 파일과 compose.yml 파일이 저장되어 있다면, 아래 코드를 입력하여 해당 폴더로 이동한 후 해당 앱 컨테이너를 생성 및 백그라운드에서 시작합니다.
cd "C:\docker\Immich-ms"
docker compose up -d
이렇게 하면 도커가 알아서 이미지를 내려받고 설정에 따라 빌드를 하고 실행까지 해줍니다.
PS C:\Docker\immich-remote-worker> docker compose up -d
[+] up 8/8
✔ Network immich-remote-worker_default Created 0.1s
✔ Container immich_remote_microservices Started 0.7s
✔ Container immich_remote_ml Started
여기까지 되었으면 실행이 완료된 것입니다.
docker compose logs -f immich-microservices
이제 위 명령어를 입력하여 생성한 서비스의 로그를 확인해 봅니다.
[Nest] 7 - 03/21/2026, 4:42:24 PM LOG [Microservices:WebsocketRepository] Initialized websocket server
...
[Nest] 7 - 03/21/2026, 4:46:48 PM LOG [Microservices:NestApplication] Nest application successfully started
[Nest] 7 - 03/21/2026, 4:46:48 PM LOG [Microservices:Bootstrap] Immich Microservices is running [v2.6.1] [production]
이처럼 로그에서 running 이라는 내용을 봤다면 실제 마이크로서비스가 시작된 것입니다.
[Nest] 7 - 03/21/2026, 4:48:30 PM LOG [Microservices:MediaService] Transcoding video XXXX without hardware acceleration
[Nest] 7 - 03/21/2026, 4:49:18 PM LOG [Microservices:MediaService] Successfully encoded XXXX
이처럼 실제로 트랜스코딩이 시작되었다는 로그 및 끝났다는 로그가 지속적으로 나타난다면 데스크탑 PC에서 정상적으로 트랜스코딩 작업을 한다는 의미입니다. 이대로 PC를 켜 두시면 작업을 백그라운드에서 진행합니다.(PowerShell은 닫아도 됩니다)
더불어 나스가 아닌 고성능 데스크탑에서 트랜스코딩 작업을 하는 만큼 Immich의 동시 작업 설정을 변경해 주면 PC의 자원을 적극 활용하여 빠르게 트랜스코딩이 가능합니다.
Immich 관리 페이지의 설정 메뉴의 작업 설정 항목에서 동영상 트랜스코드 동시성 값을 6에서 8 정도로 올려주시면 동시에 여러 작업을 할 수 있게 됩니다.
더불어 동일한 설정 메뉴 아래 트랜스코딩 설정 - 인코딩 옵션 항목에서 스레드 수 값을 CPU 스레드 수에 맞게 조정하시면 CPU의 자원을 최대한 끌어당겨서 빠르게 작업이 가능합니다. 이 값은 트랜스코딩 설정이 CPU를 활용하는 설정일 경우에 특히 큰 영향을 미칩니다. GPU 가속이 활성화되었을 때는 큰 영향이 없습니다.
작업 결과 및 성능 최적화 팁

저희 작업용 워크스테이션에서 동시 트랜스코딩 개수 6개, 스레드 수 8개로 설정을 했더니 위와 같이 64개의 논리 프로세서가 거의 풀로 가동되는 것을 볼 수 있었습니다.
저희는 기존 외부 자산 폴더의 구조 변경으로 이번에 다시 트랜스코딩을 하게 되었지만, 수많은 자산을 처음에 Immich에 등록하거나 지속적으로 많은 영상이 라이브러리에 추가되는 경우에는 역시 이런 방식으로 외부 트랜스코딩 머신을 활용하는 것이 큰 도움이 될 수 있습니다. 저희의 경우 나스에서 진행하면 한 달 가량 걸리던 작업을 데스크탑 PC에 연결하여 약 18시간 만에 끝낼 수 있었습니다.
이러한 방식은 물론 트랜스코딩을 수행해줄 서버 쪽이 켜져있어야 작동하는 기능이므로 저희는 초기 트랜스코딩이 끝난 후에는 다시 나스의 컨테이너 매니저에서 YAML 파일 내용을 기존대로 변경하고 나스 쪽에서 트랜스코딩을 설정하도록 변경하였습니다만, 상시로 이렇게 운영하시는 경우에는 연산 서버가 켜져있는 동안에만 외부 자산 스캔이나 트랜스코딩 등의 작업이 진행된다는 점을 기억해 주시는 게 좋겠습니다.
나스 쪽 설정을 API only로 두지 않고 microservices까지 같이 켜 두면, 구조상 NAS와 외부 PC가 같은 작업 큐를 함께 진행하게 됩니다. 따라서 작업이 외부 PC로만 깔끔하게 오프로드되지는 않고, 나스에도 다시 일부 부하가 걸릴 수 있습니다. 대신 워커 수가 늘어나는 만큼 전체 처리량 자체는 좋아질 수 있습니다.
반대로 나스를 API only로 두면, 외부 워커가 꺼져 있는 동안에는 Immich 접속 자체는 가능하지만 백그라운드 잡은 대기 상태로 남게 됩니다.
마치며
나스는 훌륭한 저장소 및 간단한 서비스 실행 역할을 해주지만 연산 집약적인 작업에는 명확한 한계가 있습니다. Immich처럼 MSA 구조를 갖춘 서비스는 이번 가이드와 같이 외부 기기를 일시적으로나 상시로 지원군처럼 활용하는 것이 가장 현명한 운영 전략입니다.
초기 대량 트랜스코딩이나 머신러닝 작업 때문에 나스가 힘들어 보인다면 무작정 기다리기보다 고성능 PC를 일시적으로 투입해 보세요. 인프라 운용의 쾌적함이 달라집니다.
이러한 분산 환경 구성이나 나스 최적화 구축이 어려우시다면 언제든 전문가의 도움을 받으실 수 있습니다.