13년차의 서버실

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

[태그:] Docker Compose

  • [HomeLabs] CheapSecurity vs Frigate: 홈랩 CCTV AI NVR 솔루션 실측 비교

    [HomeLabs] CheapSecurity vs Frigate: 홈랩 CCTV AI NVR 솔루션 실측 비교

    [홈랩] 홈랩 CCTV AI NVR 비교: CheapSecurity vs Frigate 실측 관점 정리

    홈랩 CCTV AI NVR 구성을 고민하시는 분들이 요즘 정말 많습니다. 저도 집에서 카메라 몇 대 붙여놓고 단순 녹화만 하다가, 사람이나 차량 같은 객체를 자동으로 잡아주는 AI NVR이 필요해졌거든요. 처음엔 ‘그냥 싼 장비 하나 사면 끝 아닌가?’ 싶었는데, 실제로 써보니까 저장 방식, RTSP(실시간 스트리밍 프로토콜), 하드웨어 가속(Hardware Acceleration), 객체 탐지(Object Detection) 안정성이 생각보다 크게 갈리더라고요. 그래서 이번 글은 CheapSecurity vs Frigate라는 비교 키워드로 많이 찾는 분들을 위해, 제가 홈랩에서 판단했던 기준과 실제 구축 흐름을 정리해보겠습니다.

    먼저 중요한 점 하나 짚고 갈게요. Frigate는 실존하는 대표적인 오픈소스 AI NVR로 널리 알려져 있지만, CheapSecurity는 제가 확인 가능한 범위에서 구체적인 실존 제품 정보가 명확하지 않았습니다. 그래서 이 글에서는 CheapSecurity를 특정 브랜드나 모델로 단정하지 않고, 저비용 홈랩 CCTV AI NVR 구성 전반을 뜻하는 비교축으로 풀어가겠습니다. 이게 할루시네이션을 피하는 가장 안전한 방식이더라고요.

    홈랩 CCTV AI NVR 전체 아키텍처를 보여주는 이미지

    홈랩 CCTV AI NVR 아키텍처 예시입니다. 카메라, RTSP 스트림, NVR, 저장소, 알림 흐름을 한눈에 보여주는 용도예요.

    왜 홈랩 CCTV AI NVR 비교가 중요한가

    쉽게 말해 CCTV는 이제 녹화만 되는 박스로 끝나지 않습니다. 홈랩에서 직접 운영하면 다음 세 가지가 바로 체감됩니다.

    • 탐지 정확도: 움직임 감지(Motion Detection)만으로는 나뭇잎, 그림자, 비 오는 날 오탐이 너무 많습니다.
    • 저장 효율: 24시간 연속 녹화는 편하지만 디스크를 꾸준히 잡아먹습니다.
    • 운영 편의성: 컨테이너(Docker Container) 기반인지, 설정 파일 중심인지에 따라 유지보수 난도가 확 달라집니다.

    제가 직접 해보니 홈랩 CCTV AI NVR에서 핵심은 단순히 ‘싼가 비싼가’가 아니었습니다. 오탐을 얼마나 줄이느냐, 스트림이 얼마나 안정적이냐, 그리고 장애가 났을 때 내가 직접 고칠 수 있느냐가 훨씬 중요했습니다. 특히 홈랩은 기업 환경처럼 전용 장비를 계속 바꿀 수 있는 구조가 아니잖아요. 이미 갖고 있는 미니 PC, NAS(Network Attached Storage), 중고 카메라를 최대한 활용해야 하니까요.

    CheapSecurity vs Frigate, 개념부터 쉽게 정리해보겠습니다

    저도 처음엔 헷갈렸는데, 여기서는 두 방향으로 이해하면 편합니다.

    1. CheapSecurity 쪽 접근: 저비용 우선입니다. 기존 카메라와 남는 서버를 최대한 재활용하고, 기능은 꼭 필요한 것부터 붙이는 방식이죠.
    2. Frigate 쪽 접근: 객체 탐지(Object Detection) 중심입니다. 단순 모션보다 사람, 차량 같은 이벤트를 기준으로 운영하기 좋습니다.
    3. 결정 포인트: 예산보다 운영 목표가 먼저입니다. ‘녹화 보관’이 목적이면 단순 구성도 충분하고, ‘이벤트 기반 알림’이 목적이면 Frigate류가 훨씬 잘 맞습니다.

    사실 보안 카메라 비교를 할 때 많은 분이 카메라 화질만 먼저 보시는데요, 실제 운영에서는 NVR이 더 중요할 때가 많습니다. 카메라가 RTSP를 안정적으로 뿌려줘도 NVR이 그걸 잘 받아먹지 못하면 녹화 구멍이 생깁니다. 반대로 카메라가 아주 고급형이 아니어도, NVR 구성이 안정적이면 실사용 만족도가 꽤 올라갑니다.

    한눈에 보는 비교 표

    항목 저비용 홈랩 구성(CheapSecurity 관점) Frigate
    주요 목적 최소 비용으로 녹화와 기본 감시 객체 탐지 중심 AI NVR 운영
    구성 난이도 케이스마다 편차 큼 초기 학습은 필요하지만 구조가 비교적 명확함
    탐지 방식 모션 감지 위주로 흐르기 쉬움 사람, 차량 등 객체 기준 운영에 유리
    확장성 개별 조합에 따라 다름 홈 어시스턴트(Home Assistant) 연동 사례가 많음
    트러블슈팅 조합형이라 원인 분리가 어려울 수 있음 설정 파일 중심이라 재현과 수정이 편한 편
    추천 대상 예산이 가장 중요한 입문자 안정적인 이벤트 감시를 원하는 사용자

    실전 구현: 제가 홈랩에서 Frigate 기준으로 잡은 기본 구조

    실제로 써보니까 가장 덜 삽질하는 시작점은 이렇습니다.

    1. 카메라는 RTSP 스트림을 안정적으로 제공하는 모델을 사용합니다.
    2. NVR은 Docker Compose로 올립니다.
    3. 녹화 저장소는 로컬 SSD나 NAS 마운트 경로로 분리합니다.
    4. 탐지용 스트림과 녹화용 스트림을 분리하면 운영이 조금 더 편해집니다.

    여기서 중요한 포인트! 홈랩 CCTV AI NVR은 CPU를 계속 갈아 넣는 구조로 가면 오래 못 버팁니다. 처음엔 ‘이 정도면 버티겠지’ 했는데, 여러 대 붙이니 팬 소음과 발열이 바로 올라오더라고요. 그래서 구성 자체를 단순하게 잡는 게 좋습니다.

    1. 디렉터리 준비

    mkdir -p ~/homelab/frigate/config
    mkdir -p ~/homelab/frigate/media
    cd ~/homelab/frigate

    설정 파일과 녹화 저장소를 분리해두면 백업이나 마이그레이션 할 때 편합니다. 저는 이걸 안 나눠놨다가 나중에 경로 정리하느라 삽질 좀 했습니다 ㅎㅎ

    2. Docker Compose 작성

    services:
      frigate:
        container_name: frigate
        restart: unless-stopped
        image: ghcr.io/blakeblackshear/frigate:stable
        privileged: true
        shm_size: "512mb"
        ports:
          - "5000:5000"
          - "8554:8554"
          - "8555:8555/tcp"
          - "8555:8555/udp"
        volumes:
          - ./config:/config
          - ./media:/media/frigate
          - /etc/localtime:/etc/localtime:ro

    버전 태그를 세세하게 고정하지 않은 이유도 있습니다. 이 글은 특정 시점의 미확인 버전을 단정하기보다, 구조와 운영 포인트에 집중하려고 했거든요.

    3. 기본 설정 파일 예시

    mqtt:
      enabled: false
    
    cameras:
      front_door:
        ffmpeg:
          inputs:
            - path: rtsp://USER:PASS@CAMERA_IP:554/stream1
              roles:
                - detect
                - record
        detect:
          enabled: true
        record:
          enabled: true
        snapshots:
          enabled: true
          timestamp: true
          bounding_box: true

    여기서는 가장 단순한 형태로만 시작하시면 됩니다. 처음부터 카메라 여러 대, 역할 분리, 알림 자동화까지 한 번에 넣으면 어디서 꼬였는지 파악이 안 됩니다. 저도 처음엔 욕심냈다가 결국 한 대만 붙여서 다시 검증했었거든요.

    홈랩 CCTV AI NVR에서 Frigate 설정과 컨테이너 구성을 설명하는 이미지

    Frigate 설정 파일, Docker Compose, 카메라 입력 흐름을 설명하는 구성 이미지가 들어갈 자리입니다.

    4. 컨테이너 실행

    docker compose up -d
    docker compose logs -f frigate

    로그를 바로 보는 습관이 중요합니다. 웹 화면만 보고 있으면 ‘왜 안 되지?’ 상태가 길어집니다. 반면 로그를 보면 RTSP 인증 실패인지, 스트림 경로 문제인지, 디렉터리 권한 문제인지 금방 감이 옵니다.

    CheapSecurity 관점에서 봤을 때의 장점과 한계

    그렇다면 저비용 중심의 구성은 무조건 별로냐? 그건 아닙니다. 오히려 홈랩 입문에서는 아주 현실적인 선택일 수 있습니다.

    • 장점: 이미 가진 장비를 재활용하기 좋습니다.
    • 장점: 작은 규모에서는 투자 부담이 적습니다.
    • 장점: 학습용으로는 충분히 재미있습니다.
    • 한계: 기능이 여기저기 흩어지면 운영 일관성이 떨어집니다.
    • 한계: 객체 탐지 품질을 안정적으로 맞추려면 결국 별도 설계가 필요합니다.

    제가 실제로 느낀 차이는 이거였습니다. 저비용 조합은 처음 시작은 빠른데, 시간이 갈수록 관리 복잡도가 올라갑니다. 반면 Frigate는 초반 설정이 조금 귀찮아도, 구조가 잡히고 나면 비교적 덜 흔들립니다. 특히 보안 카메라 비교를 많이 해보신 분일수록 공감하실 텐데요. 장비가 늘수록 ‘설정이 코드처럼 관리되느냐’가 진짜 중요해집니다.

    ⚠️ 트러블슈팅: 제가 실제로 부딪힌 문제들

    여기서부터가 진짜 실전입니다. 드디어 됐다 싶다가 다시 무너지는 구간이 꼭 오더라고요.

    1. RTSP 연결은 되는데 화면이 불안정한 경우

    대부분 카메라 스트림 프로파일이 원인인 경우가 많았습니다. 메인 스트림은 녹화용, 서브 스트림은 탐지용으로 나누는 방식이 보통 더 안정적이더라고요.

    ffprobe rtsp://USER:PASS@CAMERA_IP:554/stream1

    해결 포인트: 스트림 자체가 흔들리면 NVR을 아무리 만져도 답이 없습니다. 카메라 쪽 인코딩 설정부터 확인하세요.

    2. 저장은 되는데 이벤트 검색이 불편한 경우

    이건 모션 감지 중심 구성에서 자주 느낀 문제였습니다. 비슷한 시간대의 잡이벤트가 너무 많아져서, 막상 필요한 장면을 찾는 시간이 길어지더라고요. 그래서 객체 기반 태깅이 왜 중요한지 뒤늦게 체감했습니다.

    3. CPU 사용률이 계속 높은 경우

    처음엔 이게 뭔가 싶었는데, 탐지와 녹화를 같은 고해상도 스트림 하나로 다 처리하면 부담이 커질 수 있습니다. 특히 홈랩 미니 PC는 여유가 넉넉하지 않거든요.

    • 탐지 스트림 해상도를 낮춰봅니다.
    • 동시 카메라 수를 줄여서 먼저 검증합니다.
    • 디스크 I/O 병목도 함께 봐야 합니다.

    중요: 성능 문제를 무조건 CPU 탓으로만 보면 안 됩니다. 네트워크, 저장소, 스트림 품질이 같이 얽혀 있는 경우가 많습니다.

    4. 권한 문제로 녹화 파일이 안 쌓이는 경우

    이건 진짜 자주 겪습니다. 컨테이너는 떠 있는데 파일이 안 생기면, 경로 권한부터 보셔야 합니다.

    ls -al ~/homelab/frigate
    ls -al ~/homelab/frigate/media

    저는 예전에 NFS(Network File System) 마운트 경로로 연결했다가 권한이 꼬여서 반나절을 날린 적도 있습니다. 이런 날은 정말 허무하죠.

    홈랩 CCTV AI NVR 트러블슈팅과 로그 분석을 표현한 이미지

    로그 분석, RTSP 오류, 저장소 권한 문제 같은 트러블슈팅 장면을 보여주는 이미지 자리입니다.

    검증과 결과: 어떤 기준으로 비교해야 덜 후회하나

    실제로 써보니까 결과를 볼 때는 화려한 기능보다 아래 기준이 훨씬 중요했습니다.

    1. 이벤트 재생이 빠른가
    2. 오탐이 줄었는가
    3. 카메라 추가 시 설정이 반복 가능(repeatable)한가
    4. 문제 발생 시 로그와 설정 파일만으로 복구 가능한가

    여기서 Frigate의 강점은 꽤 분명했습니다. 객체 중심 이벤트 관리를 하려는 순간, 단순 저비용 조합보다 운영 일관성이 좋아지더라고요. 반대로 CheapSecurity식 접근, 즉 기존 자원 재활용 중심 접근은 예산을 많이 아껴야 하는 상황에서 꽤 유효했습니다. 다만 규모가 조금만 커져도 관리 체계가 필요해집니다.

    제가 정리한 결론은 이렇습니다.

    질문 추천 방향
    일단 가장 적은 비용으로 시작하고 싶은가 저비용 홈랩 조합부터 시작
    사람/차량 감지와 이벤트 탐색이 중요한가 Frigate 우선 검토
    나중에 홈 어시스턴트 연동까지 볼 생각인가 Frigate가 더 자연스러움
    운영보다 실험 자체가 목적인가 저비용 조합도 재미있음
    홈랩 CCTV AI NVR 결과 검증과 이벤트 대시보드를 보여주는 이미지

    탐지 이벤트, 썸네일, 타임라인 기반 검증 결과를 보여주는 대시보드 이미지 자리입니다.

    정리: 홈랩 CCTV AI NVR은 목적이 먼저입니다

    이번 비교를 한 문장으로 줄이면 이겁니다. CheapSecurity vs Frigate의 승부는 가격이 아니라 운영 목표에서 갈립니다. 단순 녹화와 저비용이 우선이면 가볍게 시작해도 됩니다. 하지만 나중에 사람 감지, 알림 자동화, 이벤트 검색 효율까지 보게 되면 Frigate 쪽 장점이 점점 더 크게 느껴질 가능성이 높습니다.

    혹시 이런 경험 있으신가요? 처음엔 싸게 시작했는데, 나중에 설정이 쌓이면서 오히려 시간이 더 들어가는 경우요. 저도 딱 그랬습니다. 그래서 지금은 장비 스펙보다도 운영 구조가 단순하고 재현 가능한가를 먼저 봅니다. 홈랩은 재미있어야 오래 가거든요.

    홈랩 CCTV AI NVR에서 CheapSecurity식 구성과 Frigate를 비교 요약한 이미지

    두 접근 방식의 장단점과 추천 상황을 한 장으로 요약한 인포그래픽이 들어갈 자리입니다.

    다음 단계 제안

    • 1단계: 카메라 1대로 RTSP 안정성부터 검증해보세요.
    • 2단계: 그 다음 Frigate 같은 AI NVR로 이벤트 기반 운영을 붙여보세요.
    • 3단계: 마지막에 저장 정책과 알림 정책을 다듬는 게 효율적입니다.

    다음 글에서는 홈 어시스턴트(Home Assistant)와 Frigate 연동이나, 카메라 스트림 분리 전략을 더 자세히 다뤄볼 예정입니다. 이전 글에서 다룬 Docker Compose 운영 팁도 같이 보시면 훨씬 이해가 빨라지실 겁니다.

    자주 묻는 질문 FAQ

    Q1. 홈랩 CCTV AI NVR 입문은 어떤 방향이 좋을까요?

    예산이 빡빡하면 저비용 조합으로 시작하셔도 됩니다. 다만 이벤트 기반 운영을 원하면 초반부터 Frigate를 검토하는 편이 장기적으로 편할 수 있습니다.

    Q2. 보안 카메라 비교에서 가장 먼저 봐야 할 건 뭔가요?

    해상도보다 RTSP 안정성, 스트림 설정 유연성, 그리고 NVR과의 궁합을 먼저 보시는 걸 추천드립니다.

    Q3. Frigate는 누구에게 잘 맞나요?

    단순 녹화보다 사람/차량 감지, 이벤트 검색, 자동화 연동이 중요한 분들께 잘 맞습니다.

    Q4. CheapSecurity라는 이름의 특정 제품을 찾고 있었는데요?

    제가 확인 가능한 범위에서는 특정 실존 제품으로 단정하기 어려웠습니다. 그래서 이 글에서는 저비용 홈랩 CCTV AI NVR 접근 전반을 뜻하는 비교 개념으로 다뤘습니다.

  • [홈서버] 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 방식이 꽤 강력합니다. 처음 세팅만 조금 공들여두면 이후 운영은 훨씬 편해집니다. 저도 여러 번 갈아엎고 나서야 이 결론에 도달했는데, 지금은 새 장비로 옮길 때도 부담이 많이 줄었네요. 이 글이 같은 삽질을 줄이는 데 도움이 되었으면 좋겠습니다.

  • [HomeLabs] Unifi 컨트롤러 성능 비교: Cloud Key vs Docker vs VM

    [HomeLabs] Unifi 컨트롤러 성능 비교: Cloud Key vs Docker vs VM

    [네트워크] Unifi 컨트롤러 성능 비교: Cloud Key vs Docker vs VM

    홈랩 규모가 조금만 커져도 Unifi 컨트롤러 성능 차이가 은근히 체감됩니다. 처음에는 AP 몇 대, 스위치 한두 대라서 어디에 올려도 비슷할 줄 알기 쉬운데요. 막상 써보면 대시보드가 열리는 속도, 백업이 끝나는 시간, 기기 채택 반응, 업데이트 직후 안정화 구간이 호스팅 방식마다 제법 다르게 느껴지더라고요.

    저도 처음엔 Unifi Cloud Key면 끝이라고 생각했습니다. 그런데 Docker로 옮겨 보고, 다시 VM으로 분리해 보니 관점이 꽤 바뀌었습니다. 이번 글은 특정 수치를 과장해서 보여주기보다, 홈랩에서 실제로 어떤 항목을 기준으로 비교하면 덜 헤매는지, 그리고 어떤 운영 방식이 어떤 상황에 잘 맞는지 정리한 기록에 가깝습니다.

    Unifi 컨트롤러 성능 비교를 위한 Cloud Key, Docker, VM 아키텍처 이미지

    Cloud Key, Docker, VM에 UniFi Network Application이 배치된 구조를 한눈에 보여주는 개요 이미지입니다.

    왜 Unifi 컨트롤러 성능 비교가 중요한가

    UniFi Network Application은 단순히 웹 UI만 띄우는 도구가 아닙니다. 이벤트를 모으고, 장비 상태를 저장하고, 설정을 푸시하고, 백업도 만들고, 로그도 계속 다룹니다. 쉽게 말해 네트워크 관리의 중심점 역할을 하기 때문에 컨트롤러가 느리면 화면만 답답한 게 아니라 운영 전체 템포가 같이 느려집니다.

    특히 아래 상황에서 차이가 잘 드러납니다.

    • 장비 수가 늘어나서 대시보드 로딩이 길어질 때
    • 백업 파일을 자주 만들고 복원 테스트까지 할 때
    • 원격 접속으로 설정을 바꾸는데 UI 응답이 늦을 때
    • 업데이트 전후로 기기 재연결이 몰릴 때
    • 다른 서비스와 같은 서버 자원을 나눠 쓸 때

    여기서 중요한 포인트가 하나 있습니다. 벤치마크는 단순 CPU 점수 비교가 아닙니다. 관리형 장비와 상호작용하는 서비스라서 체감 응답성과 운영 편의성까지 같이 봐야 의미가 생기거든요.

    Unifi Cloud Key, Unifi Docker, Unifi VM 개념 정리

    이 부분은 이름은 쉬운데 경계가 헷갈리기 쉽습니다. 저도 처음엔 그랬거든요. 지금 기준으로는 아래처럼 이해하면 가장 편합니다.

    1. Cloud Key: UniFi 전용 관리 장치입니다. 현재는 CloudKey+ 같은 전용 콘솔 계열이 대표적이고, 설치가 단순하며 전력 효율이 좋은 편입니다.
    2. Docker: 기존 NAS나 리눅스 서버 위에 UniFi Network Application을 컨테이너로 올리는 방식입니다. 배포와 백업, 이관이 편해서 홈랩 유저가 많이 선택합니다.
    3. VM: Proxmox VE, ESXi 같은 하이퍼바이저 위에 별도 가상머신을 두고 운영하는 방식입니다. 격리와 스냅샷, 장애 분리 측면에서 장점이 큽니다.
    항목 Cloud Key Docker VM
    초기 설치 난이도 낮음 중간 중간~높음
    운영 유연성 낮음 높음 높음
    자원 격리 전용 장비 기준 양호 호스트 공유 강함
    백업/이관 편의성 보통 매우 좋음 좋음
    업데이트 실험 보수적으로 접근 이미지 교체로 비교적 쉬움 스냅샷 활용 쉬움
    홈랩 확장성 장비 의존 매우 좋음 좋음

    제 경험상 소규모 구성에서는 Cloud Key가 정말 편합니다. 반대로 홈서버를 이미 굴리고 있다면 Unifi Docker가 손에 익기 시작하고요. 여러 서비스와 운영 표준을 맞추고 싶다면 Unifi VM이 더 안정적으로 느껴질 때가 있습니다.

    Unifi 컨트롤러 성능 벤치마크 기준은 이렇게 잡는 게 덜 헷갈립니다

    많이 하는 실수가 있습니다. 로그인 화면 열리는 시간만 보고 결론 내리는 거예요. 그런데 실제 운영에서는 그걸로 부족합니다. 제가 직접 돌려보니 아래 다섯 가지는 꼭 봐야 비교가 되더라고요.

    1. 초기 기동 시간: 서비스 재시작 후 웹 UI가 실제로 접속 가능한 시점
    2. 대시보드 응답성: 로그인 후 주요 화면 전환 체감
    3. 백업 생성 시간: 설정 백업이 완료되기까지 걸리는 흐름
    4. 복원 후 안정화: 백업 복원 후 장비가 정상 표시되기까지 걸리는 시간
    5. 자원 점유 추이: CPU, 메모리, 디스크 I/O가 몰리는 구간 확인

    여기서는 숫자를 억지로 만들 필요가 없습니다. 오히려 같은 장비 수, 같은 설정, 같은 시간대, 같은 네트워크 조건에서 반복 가능한 비교 절차를 만드는 게 더 중요합니다. 결국 benchmark도 운영에 도움이 되어야 의미가 있으니까요.

    테스트 조건을 맞출 때 체크할 것

    • 동일한 사이트 설정과 비슷한 수의 장비를 사용합니다.
    • 자동 백업 주기나 DPI(Deep Packet Inspection, 심층 패킷 분석) 같은 부가 기능은 동일하게 맞춥니다.
    • 호스트에 다른 작업이 몰리는 시간은 피합니다.
    • 가능하면 같은 브라우저, 같은 클라이언트에서 접근합니다.
    • 한 번만 보지 말고 최소 여러 차례 반복합니다.
    Unifi 컨트롤러 성능 벤치마크 측정 흐름 다이어그램

    기동 시간, 로그인 응답, 백업 생성, 복원 안정화, 리소스 모니터링 순서를 정리한 벤치마크 흐름 이미지입니다.

    실전 구현: Docker와 VM에서 비교 환경 만들기

    Cloud Key는 전용 장비라 설치 과정 자체가 단순한 편입니다. 그래서 실전 비교는 Docker와 VM 쪽에서 재현 가능한 구조를 만들어두는 게 좋습니다. 저는 보통 동일한 백업 파일을 기준으로 각 환경을 맞춘 뒤, 그다음에 응답성과 운영 편의성을 비교합니다.

    1. Docker 환경 준비

    아래 예시는 Docker Compose 기준입니다. 최근 많이 쓰는 LinuxServer 이미지 방식에 맞춰 외부 MongoDB를 따로 두는 형태로 잡았습니다. 여기서는 개념 전달이 목적이라 최소 예시만 넣었고, 실제 운영에서는 DB 이미지 태그를 꼭 고정해 두는 편이 안전하더라고요.

    services:
      unifi:
        image: lscr.io/linuxserver/unifi-network-application:latest
        container_name: unifi-controller
        restart: unless-stopped
        environment:
          - PUID=1000
          - PGID=1000
          - TZ=Asia/Seoul
          - MONGO_USER=unifi
          - MONGO_PASS=unifi-pass
          - MONGO_HOST=unifi-db
          - MONGO_PORT=27017
          - MONGO_DBNAME=unifi
          - MONGO_AUTHSOURCE=admin
        ports:
          - "8443:8443"
          - "3478:3478/udp"
          - "10001:10001/udp"
          - "8080:8080"
        volumes:
          - ./unifi-config:/config
        depends_on:
          - unifi-db
    
      unifi-db:
        image: mongo:4.4
        container_name: unifi-db
        restart: unless-stopped
        environment:
          - MONGO_INITDB_ROOT_USERNAME=root
          - MONGO_INITDB_ROOT_PASSWORD=change-me
        command: ["--wiredTigerCacheSizeGB", "1"]
        volumes:
          - ./unifi-db:/data/db
          - ./init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh:ro

    이 예시에서 중요한 건 두 가지입니다. 첫째, `mongo:latest`처럼 메이저 버전이 자동으로 바뀌는 태그는 피하는 게 좋습니다. 둘째, 최신 UniFi Network Application 계열은 외부 MongoDB 구성과 인증 설정이 맞지 않으면 처음부터 이상하게 느려지거나 아예 기동이 꼬일 수 있어서, 성능 비교 전에 구성 일치부터 잡아야 합니다.

    실제로 써보면 Docker 방식은 이관성과 반복 실험이 정말 좋습니다. 이미지 버전 비교, 구성 백업, 롤백이 빠르거든요. 홈랩에서는 이거 하나만으로도 체감 만족도가 꽤 큽니다.

    2. VM 환경 준비

    VM은 운영체제 레벨에서 분리되기 때문에 다른 서비스와 간섭을 줄이기 좋습니다. 저는 Proxmox VE 위에 Ubuntu Server 계열 VM을 올려서 비교했는데, 중요한 건 배포판 이름보다도 CPU, 메모리, 디스크 할당 정책이었습니다. 특히 스토리지가 느리면 VM이든 Docker든 생각보다 금방 답답해집니다.

    홈랩에서는 VM 안에 다시 Docker로 UniFi를 올리는 방식도 많이 씁니다. 엄밀히 말하면 VM과 Docker를 동시에 쓰는 구조죠. 그런데 운영 표준화 측면에서는 꽤 합리적입니다. 스냅샷도 되고, 컨테이너 이관도 되니까요.

    sudo apt update
    sudo apt install -y curl ca-certificates gnupg
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    sudo apt update
    sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

    위 명령은 VM 안에 Docker 실행 환경을 올리는 예시입니다. 즉, 이 단계 자체가 UniFi 설치 명령은 아니고, 비교 실험을 동일한 방식으로 재현하기 위한 기반 준비라고 보시면 됩니다.

    3. 측정 스크립트 예시

    응답 확인은 너무 복잡하게 갈 필요가 없습니다. 로그인 화면이 열리는지, HTTPS 관리 포트가 실제로 응답하는지부터 잡아도 큰 도움이 됩니다. 아래 스크립트는 재시작 직후 어느 쪽이 더 빨리 안정화되는지 감을 잡을 때 꽤 유용했습니다.

    #!/usr/bin/env bash
    TARGET="https://unifi.example.local:8443"
    for i in $(seq 1 30); do
      printf "[%02d] " "$i"
      curl -k -s -o /dev/null -w "code=%{http_code} connect=%{time_connect} start=%{time_starttransfer} total=%{time_total}\n" "$TARGET"
      sleep 2
    done

    여기에 `docker stats`, `top`, `iostat` 같은 툴을 같이 보면 병목 구간이 더 잘 보입니다. 숫자가 예쁘게 나온다고 끝이 아니라, 어느 순간에 CPU가 튀고 디스크가 밀리는지 같이 봐야 해석이 훨씬 정확해지더라고요.

    Unifi Docker와 Unifi VM 설정 비교 이미지

    컨테이너 구성 파일과 VM의 CPU, 메모리, 디스크 할당 개념을 함께 설명하는 설정 이미지입니다.

    주의사항과 트러블슈팅: 여기서 많이 헷갈립니다

    이 부분은 정말 중요합니다. 저도 성능 차이인 줄 알았는데 알고 보니 설정 문제였던 적이 여러 번 있었거든요. 분명 같은 데이터인데 한쪽만 유독 느리다면, 생각보다 아래 항목에서 걸리는 경우가 많습니다.

    포트와 네트워크 경로 문제

    • 8080/TCP: 장비와 애플리케이션 간 통신에 쓰입니다. 막혀 있으면 Adoption이나 재연결 흐름이 꼬일 수 있습니다.
    • 8443/TCP: 관리 GUI/API 접근에 자주 쓰는 포트입니다. 리버스 프록시를 붙일 때 인증서나 HTTPS 처리 구성이 꼬이면 UI가 불안정해질 수 있습니다.
    • 3478/UDP: STUN 기반 통신에 사용됩니다. 장비 채택과 연결 상태 확인 때 자주 체크하게 되는 포트입니다.

    처음엔 컨트롤러가 느린 줄 알았는데, 실제로는 L2 브로드캐스트가 제대로 안 닿아서 장비 발견이 지연된 적도 있었습니다. 이건 성능 문제가 아니라 연결 경로 문제죠. 그래서 Unifi 컨트롤러 성능을 보기 전에 통신 경로부터 먼저 정상화하는 게 맞습니다.

    디스크 성능이 발목 잡는 경우

    Cloud Key든 Docker든 VM이든 결국 로그와 데이터베이스 쓰기가 발생합니다. 저장소가 느리면 UI도 같이 답답해집니다. 특히 저전력 장비나 공유 스토리지를 쓸 때 체감 차이가 커요. CPU보다 디스크 I/O가 먼저 병목이 되는 경우도 생각보다 많더라고요.

    백업 복원 후 장비 상태가 바로 안 맞는 경우

    복원은 됐는데 장비가 오프라인처럼 보이거나 사이트 정보가 바로 반영되지 않는 경우가 있습니다. 이럴 땐 성능 탓부터 하지 말고 아래 순서로 보는 게 훨씬 빠릅니다.

    1. 장비가 새 컨트롤러 IP 또는 호스트명을 제대로 인식했는지 확인합니다.
    2. DNS(Domain Name System, 도메인 이름 해석)와 게이트웨이 경로를 점검합니다.
    3. 인증서 경고나 브라우저 캐시 문제를 제거합니다.
    4. 컨트롤러 재기동 후 로그를 다시 확인합니다.

    보통 비교 대상의 상태를 최대한 동일하게 맞추는 작업을 끝내고 나서야 진짜 성능 차이가 보입니다. 이 순서를 건너뛰면 숫자는 그럴듯해도 결론이 자꾸 흔들리더라고요.

    Unifi 컨트롤러 성능 결과 해석: 숫자보다 운영 감각이 더 중요합니다

    이제 결과를 어떻게 읽을지 정리해보겠습니다. 이 글에서는 특정 모델별 점수를 임의로 적지는 않겠습니다. 대신 홈랩에서 반복적으로 느끼는 경향을 기준으로 정리하면 아래 표에 가깝습니다.

    비교 포인트 Cloud Key 경향 Docker 경향 VM 경향
    설치 직후 진입 장벽 가장 낮음 낮음 중간
    호스트 자원 공유 영향 낮음 있음 관리 가능
    백업/이관 실험 제한적 매우 편함 편함
    문제 분리 난이도 단순 호스트 영향 고려 필요 OS 단위로 분리 쉬움
    장기 운영 유연성 보통 높음 높음

    제가 직접 굴려보니 결론은 꽤 명확했습니다.

    • 간단하고 안정적인 전용 운영이 목표면 Cloud Key가 편합니다.
    • 홈서버, NAS, 자동화, 백업까지 묶어서 운영할 생각이면 Docker가 실용적입니다.
    • 격리, 표준화, 스냅샷, 복구 훈련까지 챙기려면 VM이 운영자 친화적으로 느껴질 가능성이 큽니다.

    즉, Unifi 컨트롤러 성능은 단순 처리속도만이 아니라 운영 방식과 함께 봐야 합니다. 같은 웹 응답이라도 장애 대응 시간, 이관 편의성, 실험 가능성까지 포함하면 체감 순위가 달라지거든요.

    Unifi 컨트롤러 성능 결과를 보여주는 대시보드 이미지

    기동 시간, 응답 지표, CPU/메모리 추이를 그래프 형태로 보여주는 결과 요약 이미지입니다.

    Unifi 컨트롤러 성능 기준으로 어떤 환경을 고르면 좋을까

    정답은 하나가 아닙니다. 여기서 중요한 기준은 장비 수만이 아니라 현재 운영 습관입니다. 저도 돌이켜보면 장비 숫자보다 백업 습관, 장애 대응 방식, 업데이트 빈도가 선택에 더 큰 영향을 줬습니다.

    1. 처음 시작하는 경우: 전용 장비 기반의 Cloud Key가 가장 부담이 적습니다.
    2. 이미 Docker를 잘 쓰는 경우: Unifi Docker 구성이 가장 가성비 좋게 느껴질 가능성이 큽니다.
    3. 여러 서비스와 분리 운영이 필요한 경우: Unifi VM이 추후 확장과 장애 분리에 유리합니다.
    4. 백업과 복원 훈련을 자주 하는 경우: Docker 또는 VM이 훨씬 편합니다.

    지금 제 기준으로 홈랩이라면 Docker를 먼저 추천하고, 조금 더 엄격하게 운영할 때는 VM으로 분리할 것 같습니다. Cloud Key도 여전히 좋은 선택지지만, 실험을 자주 하는 사람에게는 유연성이 살짝 아쉽더라고요.

    정리와 다음 단계

    이번 글의 핵심은 간단합니다. Unifi 컨트롤러 성능을 비교할 때는 Cloud Key, Docker, VM을 단순 빠르기 경쟁으로 보지 말고 운영 편의성과 복구 가능성까지 같이 보자는 겁니다. 실제로 써보면 Docker는 반복 실험이 편하고, VM은 격리가 좋고, Cloud Key는 셋업이 단순해서 각자 강점이 분명합니다.

    혹시 지금 컨트롤러가 느리다고 느끼신다면 바로 마이그레이션부터 하지 마세요. 먼저 기동 시간, 백업 속도, 포트 상태, 디스크 I/O를 체크해보는 게 훨씬 낫습니다. 생각보다 원인은 호스팅 방식보다 주변 설정에 있는 경우가 많습니다. 저도 처음엔 성능 문제인 줄 알고 꽤 헤맸거든요.

    다음 글에서는 Unifi Docker를 실제 운영 환경에 올릴 때 볼륨 백업, 리버스 프록시, 업데이트 전략을 더 깊게 다뤄볼 예정입니다. 이전 글에서 다룬 홈랩 스토리지 구성과 함께 보면 흐름이 더 잘 잡힐 거예요. 백업 전략 관련 글도 같이 보면 마이그레이션 실수 줄이는 데 도움이 됩니다.

    Unifi Cloud Key, Docker, VM 선택 기준 요약 이미지

    용도별 추천 시나리오와 장단점을 한 장으로 정리한 비교 요약 이미지입니다.

    자주 묻는 질문

    Q1. 소규모 네트워크에서도 VM이 필요할까요?

    반드시 그렇지는 않습니다. 소규모라면 Cloud Key나 Docker로도 충분한 경우가 많습니다. 다만 다른 서비스와 충돌을 줄이고 싶다면 VM이 더 편하게 느껴질 수 있습니다.

    Q2. Docker가 항상 더 빠른가요?

    항상 그렇지는 않습니다. 호스트 자원 경쟁, 스토리지, 네트워크 구성에 따라 체감은 달라집니다. 그래서 benchmark는 환경 통제가 핵심입니다.

    Q3. 마이그레이션 전에 가장 먼저 뭘 해야 하나요?

    백업 검증입니다. 백업 파일이 만들어지는 것과 실제로 복원해서 정상 동작하는 것은 다른 문제거든요.

  • [Nas] OpenMediaVault와 Immich 연동 사례: 나만의 프라이빗 사진 클라우드 구축

    [Nas] OpenMediaVault와 Immich 연동 사례: 나만의 프라이빗 사진 클라우드 구축

    OpenMediaVault와 Immich 연동 사례: 나만의 프라이빗 사진 클라우드 구축

    안녕하세요, 13년차 인프라 엔지니어 서버실입니다. 오늘은 많은 분들이 고민하시는 사진 관리 문제, 특히 프라이빗 클라우드 구축에 대한 이야기를 해볼까 합니다. 구글 포토의 정책 변경 이후, ‘내 사진을 내 손으로 관리하고 싶다!’는 열망이 더 커진 것 같아요. 저도 처음엔 클라우드 서비스가 편해서 잘 썼는데, 역시 데이터 주권(Data Sovereignty)은 중요하더라고요. 그래서 홈랩에서 직접 OpenMediaVault(OMV)와 Immich를 연동해서 저만의 프라이빗 사진 클라우드를 구축했습니다. 나스(NAS) 환경에서 사진을 자동으로 백업하고 관리할 수 있게 된 과정을 솔직하게 공유해 드릴게요.

    그림 1: OpenMediaVault 기반 Immich 프라이빗 사진 클라우드 아키텍처

    OpenMediaVault와 Immich, 왜 이 조합일까요?

    먼저, 이 두 친구가 어떤 역할을 하는지 간단히 짚어보고 갈까요? 쉽게 말해, OpenMediaVault(OMV)는 나스(NAS, Network Attached Storage)의 뼈대 역할을 하고, Immich는 그 위에 멋진 옷을 입혀주는 사진 관리 솔루션이라고 생각하시면 됩니다.

    • OpenMediaVault (OMV): 데비안(Debian) 리눅스 기반의 무료 오픈소스 NAS 운영체제입니다. 파일 공유(SMB/NFS), RAID 관리, 플러그인 확장성, 그리고 무엇보다 도커(Docker) 컨테이너 지원이 강력해서 홈랩에서 활용도가 정말 높아요. 튼튼한 스토리지 백엔드를 제공하는 셈이죠. 제가 직접 써보니 안정성도 뛰어나고 관리도 편하더라고요.

    • Immich: 요즘 뜨는 셀프 호스팅(Self-hosted) 사진 및 비디오 백업 솔루션입니다. 구글 포토와 비슷한 사용자 경험을 제공하면서, AI 기반 얼굴 인식(Facial Recognition), 객체 감지(Object Detection), 검색 기능, 타임라인(Timeline) 뷰, 공유 앨범 등 고급 기능까지 갖추고 있어요. 모바일 앱(iOS/Android)도 있어서 자동 백업도 가능합니다. 이 정도면 ‘나만의 구글 포토’라고 불러도 손색이 없죠.

    OMV가 안정적인 스토리지 공간을 제공하고, Immich가 그 공간에 저장된 사진들을 스마트하게 관리해주니, 이보다 더 좋은 조합이 있을까요? 👍

    OMV에 도커와 Immich 설치하기: 실전 구현

    이제 본격적으로 OMV 위에 Immich를 올려볼 차례입니다. OMV에 도커와 포테이너(Portainer)가 이미 설치되어 있다고 가정할게요. (아직 설치 안 하셨다면, OMV 웹 UI에서 OMV-Extras 플러그인을 통해 쉽게 설치할 수 있습니다.)

    1. Immich용 공유 폴더 생성

    먼저 OMV에서 Immich가 사진을 저장할 공유 폴더를 만들어야 합니다. 저는 /srv/dev-disk-by-uuid-XXXX/data/immich 경로에 immich라는 공유 폴더를 만들었어요. 여기서 정말 중요한 부분이 바로 권한 설정입니다. 도커 컨테이너 내부의 프로세스가 이 폴더에 접근하고 파일을 쓸 수 있도록 적절한 권한을 부여해야 하는데, 보통 PUID와 PGID를 사용합니다. 저는 1000:1000 (기본 사용자/그룹)으로 설정했습니다.

    2. Docker Compose 파일 준비

    Immich는 여러 서비스(PostgreSQL, Redis, Microservices 등)로 구성되어 있어서 도커 컴포즈(Docker Compose)로 한 번에 배포하는 게 가장 편리합니다. Immich 공식 GitHub 저장소에서 예시 docker-compose.yaml 파일을 가져오는 게 좋아요. 저는 항상 최신 버전을 확인하고 수정해서 사용합니다.

    # OMV SSH 접속 후 작업 디렉토리 생성
    mkdir -p /srv/dev-disk-by-uuid-XXXX/config/immich
    cd /srv/dev-disk-by-uuid-XXXX/config/immich
    
    # Immich GitHub에서 docker-compose.yaml 다운로드 (최신 버전 확인 필수)
    wget https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
    wget https://github.com/immich-app/immich/releases/latest/download/.env
    

    다운로드한 .env 파일과 docker-compose.yml 파일을 열어서 몇 가지를 수정해야 합니다.

    • .env 파일 수정:
      • UPLOAD_LOCATION=./upload 부분을 OMV에서 생성한 공유 폴더 경로로 변경합니다. 예: UPLOAD_LOCATION=/data/immich/upload (컨테이너 내부 경로)
      • DB_PASSWORD, REDIS_PASSWORD 등을 강력한 비밀번호로 변경하세요.
      • TZ=Asia/Seoul 처럼 시간대를 설정합니다.
    • docker-compose.yml 파일 수정:
      • 각 서비스의 volumes 섹션에서 OMV 공유 폴더와 연결되는 부분을 확인하고 수정합니다. 특히 ./upload:/usr/src/app/upload 부분을 /srv/dev-disk-by-uuid-XXXX/data/immich:/usr/src/app/upload (호스트 경로:컨테이너 내부 경로) 형태로 맞춰줘야 합니다.
      • PUID, PGID 환경 변수를 OMV에서 설정한 사용자/그룹 ID에 맞춰주세요.

    이 부분이 사실 제가 겪었던 가장 큰 삽질의 핵심이었습니다. 😅 볼륨 마운트 경로를 잘못 지정하거나 권한이 없어서 컨테이너가 파일을 못 읽는 경우가 정말 많거든요. 항상 호스트 경로와 컨테이너 내부 경로가 정확히 매핑되는지, 그리고 해당 호스트 폴더에 컨테이너가 접근할 수 있는 권한이 있는지 꼼꼼히 확인해야 합니다.

    Immich Docker Compose 설정 파일 예시 (볼륨 및 환경 변수)

    그림 2: Immich Docker Compose 설정 파일 예시 (볼륨 및 환경 변수)

    3. Immich 서비스 실행

    파일 수정이 끝났다면, 이제 도커 컴포즈를 이용해 서비스를 실행합니다. OMV SSH 터미널에서 docker-compose.yml 파일이 있는 디렉토리로 이동한 다음 아래 명령어를 실행하세요.

    docker compose up -d
    

    -d 옵션은 백그라운드에서 컨테이너를 실행하라는 의미입니다. 컨테이너들이 모두 정상적으로 올라오는지 docker compose ps 명령어로 확인해볼 수 있습니다.

    ⚠️ 주의사항 및 트러블슈팅: 제가 겪은 삽질들

    제가 이 OpenMediaVault와 Immich 연동 구성을 하면서 가장 많이 겪었던 문제들은 역시 권한(Permissions)과 볼륨 마운트(Volume Mount)였습니다. 특히 OMV의 공유 폴더와 도커 컨테이너 간의 권한 문제가 많았어요. 홈랩에서 사진 백업을 구축할 때 이 부분을 간과하면 정말 답답하더라고요.

    1. 권한 문제 (Permission Denied): Immich 컨테이너가 OMV 공유 폴더에 사진을 저장하거나 데이터베이스 파일을 생성할 때 ‘Permission Denied’ 에러가 발생하는 경우가 많았습니다. 이럴 때는 OMV에서 해당 공유 폴더의 ACL(Access Control List) 설정을 확인하거나, SSH로 접속해서 직접 chown 명령어로 소유권을 변경해줘야 합니다. 예를 들어, sudo chown -R 1000:1000 /srv/dev-disk-by-uuid-XXXX/data/immich 이런 식으로요. PUID, PGID 값과 일치시켜주는 게 정말 중요합니다.

    2. 리소스 부족 (Resource Exhaustion): Immich는 생각보다 많은 리소스를 사용합니다. 특히 처음 사진을 인덱싱(Indexing)하고 AI 기능을 사용할 때 CPU와 RAM 사용량이 급증할 수 있어요. 저사양 NAS나 라즈베리 파이(Raspberry Pi) 같은 장비에선 버벅거릴 수 있습니다. 저는 N100 기반 미니 PC에 16GB RAM을 사용하는데, 이 정도면 충분하더라고요. 나스 환경의 사양을 고려해서 구축해야 합니다.

    3. 포트 충돌 (Port Conflict): 만약 OMV에서 다른 서비스가 Immich와 동일한 포트(기본 2283)를 사용하고 있다면 충돌이 발생할 수 있습니다. docker-compose.yml 파일에서 Immich 서버의 포트를 다른 번호로 변경해주거나, 기존 서비스의 포트를 변경해야 합니다.

    이런 문제들을 하나씩 해결해나가면서 ‘아, 역시 인프라 엔지니어는 삽질의 연속이구나’ 싶었지만, 각각을 해결할 때마다 느껴지는 성취감이 있었어요. 💡

    설치 검증 및 결과 확인 🎉

    모든 컨테이너가 정상적으로 실행되면, 웹 브라우저를 열고 http://[OMV_IP_주소]:2283으로 접속하면 됩니다. 처음 접속하면 관리자 계정을 생성하라는 화면이 나올 거예요. 계정을 만들고 로그인하면 드디어 Immich의 멋진 인터페이스를 만날 수 있습니다!

    모바일 앱을 설치해서 OMV 서버의 IP 주소와 포트를 입력하면 스마트폰 사진을 자동으로 백업할 수 있어요. 실제로 제가 갤러리 앱에서 사진 몇 장을 찍어보니 Immich 웹 UI에 바로바로 동기화되더라고요. 정말 신기하고 뿌듯했습니다. 🤩

    Immich 웹 UI 메인 화면 (사진 업로드 및 타임라인)

    그림 3: Immich 웹 UI (사진 업로드 및 타임라인)

    가족 사진, 여행 사진, 친구들과의 추억까지! 이제 모두 제 OMV 나스에 안전하게 보관되고, Immich의 강력한 기능으로 편리하게 관리할 수 있게 되었습니다. 프라이버시(Privacy) 걱정 없이, 원하는 만큼의 용량을 마음껏 쓸 수 있다는 점이 가장 큰 장점 같아요.

    마무리하며: 나만의 사진 클라우드, 그 다음은?

    OpenMediaVault와 Immich를 연동해서 나만의 프라이빗 사진 클라우드를 구축하는 과정, 어떠셨나요? 처음에는 조금 복잡하게 느껴질 수도 있지만, 한 번 구축해두면 정말 든든한 나만의 사진 보관소가 생기는 겁니다. 데이터 주권을 되찾고, 클라우드 서비스 구독료도 절약할 수 있으니 일석이조죠.

    저는 여기서 멈추지 않고, Nginx Proxy Manager 같은 리버스 프록시(Reverse Proxy)를 이용해 외부에서도 안전하게 접속할 수 있도록 설정할 계획입니다. 또, 백업 전략(Backup Strategy)도 빠뜨리지 않고 구현해야 하겠더라고요. Raid는 백업이 아니라는 점, 다들 아시죠? 😉

    여러분도 제 경험을 바탕으로 나만의 프라이빗 사진 클라우드 구축에 도전해 보시길 강력히 추천합니다. 궁금한 점이 있으시다면 언제든지 댓글로 남겨주세요! 다음에는 Nginx Proxy Manager를 활용한 외부 접속 설정에 대해 다뤄볼까 합니다. 기대해주세요!

    OMV와 Immich 연동의 주요 장점 요약 인포그래픽

    그림 4: OMV + Immich 연동의 주요 장점

  • [Cloud] Docker Compose 실전 가이드: 로컬 개발 환경 구축 및 관리

    “팀원 컴퓨터에서는 되는데 제 컴퓨터에서는 왜 안 되죠?”

    인프라 일을 13년 하면서 개발팀에서 가장 많이 들은 말 중 하나입니다. 그리고 솔직히 말씀드리면, 저도 초창기엔 이 문제로 꽤 많이 고생했거든요. 환경변수 하나 차이로 밤새 디버깅하고, OS 버전 달라서 라이브러리 충돌 나고… 생각만 해도 아찔하네요.

    그래서 오늘은 Docker Compose를 활용해서 로컬 개발 환경을 제대로 구축하는 방법을 공유하려고 합니다. “내 컴퓨터에서는 되는데”라는 말을 팀에서 영원히 추방할 수 있는 방법이에요. 실제로 제가 홈랩이랑 팀 프로젝트에서 직접 써보면서 정리한 내용이라 꽤 실용적일 거라 생각합니다.

    ▲ Docker Compose로 구성한 로컬 개발 환경의 전체 구조 — 웹 서버, 앱 서버, 데이터베이스가 하나의 네트워크로 묶이는 모습

    Docker Compose가 뭔지 먼저 짚고 넘어가요

    Docker 자체는 이미 알고 계신 분들이 많을 텐데, Docker Compose(도커 컴포즈)는 조금 다른 개념이에요. 쉽게 말해서, 여러 개의 컨테이너(Container)를 하나의 파일로 정의하고 한 번에 관리하는 도구거든요.

    예를 들어 웹 애플리케이션 하나를 띄우려면 보통 이런 것들이 필요하잖아요:

    • 프론트엔드 서버 (React, Vue 등)
    • 백엔드 API 서버 (Node.js, FastAPI 등)
    • 데이터베이스 (PostgreSQL, MySQL 등)
    • 캐시 서버 (Redis 등)

    이걸 Docker 명령어로 하나하나 실행하면… 솔직히 너무 번거롭더라고요. 컨테이너마다 네트워크 연결하고, 볼륨 설정하고, 환경변수 넣고… 저도 처음엔 그렇게 했었는데 한 달도 안 돼서 포기했어요 ㅎㅎ.

    그런데 Docker Compose를 쓰면 docker-compose.yml이라는 파일 하나에 이 모든 걸 정의하고, 명령어 한 줄로 전체를 올리고 내릴 수 있어요. 개발 생산성 측면에서 정말 게임 체인저였습니다.

    Docker Compose vs. 일반 Docker 명령어 비교

    항목 Docker 단독 사용 Docker Compose 사용
    서비스 시작 컨테이너마다 개별 명령어 실행 docker compose up 하나로 끝
    네트워크 설정 수동으로 네트워크 생성 및 연결 자동으로 네트워크 생성 및 연결
    환경 관리 각 명령어에 -e 옵션 반복 입력 yml 파일에 한 번에 정의
    팀 공유 실행 명령어 문서화 필요 yml 파일을 Git에 올리면 끝
    재현성 낮음 (사람마다 다르게 실행 가능) 높음 (동일한 환경 보장)

    시작 전 준비사항

    본격적으로 들어가기 전에 환경 세팅부터 확인해 봅시다. 요즘은 Docker Desktop을 설치하면 Docker Compose도 함께 딸려오거든요. 예전엔 따로 설치해야 했는데, 이 부분은 많이 편해졌어요.

    1. Docker Desktop 공식 사이트에서 OS에 맞는 버전 다운로드 및 설치
    2. 설치 완료 후 터미널에서 버전 확인
    # Docker 버전 확인
    docker --version
    
    # Docker Compose 버전 확인 (v2 기준)
    docker compose version

    💡 팁: 예전에는 docker-compose(하이픈 포함)로 실행했는데, 요즘 Compose V2부터는 docker compose(스페이스)로 바뀌었어요. 둘 다 동작하긴 하는데, 새 프로젝트라면 V2 방식으로 쓰는 게 좋습니다.

    실전: docker-compose.yml 파일 작성하기

    자, 이제 진짜 시작입니다. 실제 웹 애플리케이션 개발 환경을 예시로 만들어볼게요. Node.js 백엔드 + PostgreSQL 데이터베이스 + Redis 캐시 조합으로 가겠습니다. 제가 홈랩에서 사이드 프로젝트 할 때 자주 쓰는 스택이거든요.

    프로젝트 디렉토리 구조

    my-project/
    ├── docker-compose.yml       # 핵심 설정 파일
    ├── docker-compose.override.yml  # 로컬 개발용 오버라이드
    ├── .env                     # 환경변수 파일
    ├── backend/
    │   ├── Dockerfile
    │   └── src/
    └── frontend/
        ├── Dockerfile
        └── src/

    기본 docker-compose.yml 작성

    version: '3.8'
    
    services:
      # 백엔드 API 서버
      backend:
        build:
          context: ./backend
          dockerfile: Dockerfile
        container_name: myapp-backend
        ports:
          - "3000:3000"
        environment:
          - NODE_ENV=development
          - DATABASE_URL=postgresql://myuser:mypassword@db:5432/mydb
          - REDIS_URL=redis://cache:6379
        volumes:
          - ./backend:/app          # 소스 코드 마운트 (핫 리로드 가능)
          - /app/node_modules       # node_modules는 컨테이너 것 사용
        depends_on:
          db:
            condition: service_healthy  # DB 헬스체크 통과 후 시작
          cache:
            condition: service_started
        networks:
          - app-network
        restart: unless-stopped
    
      # PostgreSQL 데이터베이스
      db:
        image: postgres:15-alpine
        container_name: myapp-db
        environment:
          - POSTGRES_USER=myuser
          - POSTGRES_PASSWORD=mypassword
          - POSTGRES_DB=mydb
        volumes:
          - postgres-data:/var/lib/postgresql/data  # 데이터 영속성 보장
          - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql  # 초기화 스크립트
        ports:
          - "5432:5432"   # 로컬에서 DB 클라이언트로 직접 접속 가능
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U myuser -d mydb"]
          interval: 10s
          timeout: 5s
          retries: 5
        networks:
          - app-network
    
      # Redis 캐시 서버
      cache:
        image: redis:7-alpine
        container_name: myapp-redis
        ports:
          - "6379:6379"
        volumes:
          - redis-data:/data
        networks:
          - app-network
    
    # 볼륨(Volume) 정의: 컨테이너가 삭제돼도 데이터 유지
    volumes:
      postgres-data:
      redis-data:
    
    # 네트워크 정의: 서비스 간 내부 통신
    networks:
      app-network:
        driver: bridge

    여기서 중요한 포인트! depends_on을 쓸 때 단순히 서비스 이름만 쓰면 컨테이너가 시작된 것만 확인하고 실제로 준비가 됐는지는 모릅니다. condition: service_healthy와 healthcheck를 함께 써야 PostgreSQL이 실제로 쿼리를 받을 준비가 됐을 때 백엔드가 시작돼요. 이거 몰라서 처음에 백엔드가 DB 연결 못 한다고 에러 뜨는 삽질을 꽤 했었더라고요 ㅎㅎ.

    환경변수 파일(.env) 관리

    민감한 정보는 절대 docker-compose.yml에 직접 넣으면 안 됩니다. .env 파일을 따로 만들고 Git에는 올리지 마세요.

    # .env 파일
    POSTGRES_USER=myuser
    POSTGRES_PASSWORD=super_secret_password
    POSTGRES_DB=mydb
    NODE_ENV=development
    APP_PORT=3000
    # docker-compose.yml에서 .env 변수 참조
    services:
      db:
        environment:
          - POSTGRES_USER=${POSTGRES_USER}
          - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
          - POSTGRES_DB=${POSTGRES_DB}
    # .gitignore에 반드시 추가
    .env
    .env.local
    .env.production

    ▲ docker-compose.yml로 정의된 서비스들이 내부 네트워크(app-network)로 연결되고, 필요한 포트만 호스트에 노출되는 구조

    개발 환경 전용 오버라이드 파일

    이건 좀 꿀팁인데요. docker-compose.override.yml을 만들면 docker compose up할 때 자동으로 합쳐져서 적용됩니다. 로컬 개발에서만 필요한 설정을 분리할 수 있어서 정말 편하더라고요.

    # docker-compose.override.yml (로컬 개발 전용)
    version: '3.8'
    
    services:
      backend:
        # 개발 중엔 빌드 없이 소스 코드 직접 마운트
        command: npm run dev   # nodemon 등 핫 리로드 명령어
        environment:
          - DEBUG=true
          - LOG_LEVEL=debug
    
      # 개발 환경에서만 DB 관리 UI 추가
      adminer:
        image: adminer
        container_name: myapp-adminer
        ports:
          - "8080:8080"
        networks:
          - app-network

    자주 쓰는 Docker Compose 명령어 모음

    이제 실제로 실행해 봅시다. 제가 매일 쓰는 명령어들 위주로 정리했어요.

    # 전체 서비스 시작 (백그라운드 실행)
    docker compose up -d
    
    # 빌드 포함해서 시작 (코드 변경 후)
    docker compose up -d --build
    
    # 특정 서비스만 시작
    docker compose up -d backend
    
    # 전체 서비스 중지
    docker compose down
    
    # 중지 + 볼륨까지 삭제 (DB 초기화할 때)
    docker compose down -v
    
    # 실행 중인 서비스 상태 확인
    docker compose ps
    
    # 특정 서비스 로그 보기 (실시간)
    docker compose logs -f backend
    
    # 실행 중인 컨테이너에 접속
    docker compose exec backend sh
    
    # 데이터베이스 컨테이너에서 psql 실행
    docker compose exec db psql -U myuser -d mydb
    
    # 서비스 재시작
    docker compose restart backend

    ⚠️ 실제로 겪은 트러블슈팅 사례들

    이론은 깔끔한데, 실제로 쓰다 보면 별별 문제가 다 생기더라고요. 제가 겪었던 것들 공유합니다.

    문제 1: 포트가 이미 사용 중이라는 에러

    # 에러 메시지
    Error response from daemon: Ports are not available: 
    exposing port TCP 0.0.0.0:5432 -> 0.0.0.0:0: listen tcp 0.0.0.0:5432: 
    bind: address already in use

    로컬에 PostgreSQL이 이미 설치돼서 실행 중인 경우 자주 발생해요. 해결법은 두 가지예요:

    # 방법 1: 로컬 PostgreSQL 서비스 중지
    sudo systemctl stop postgresql   # Linux
    brew services stop postgresql    # macOS
    
    # 방법 2: docker-compose.yml에서 포트 변경
    ports:
      - "5433:5432"   # 호스트 포트를 5433으로 변경

    문제 2: 볼륨 마운트 후 node_modules 사라짐

    이거 처음 겪으면 진짜 당황스러워요. 소스 코드 볼륨 마운트하면 로컬의 node_modules(없는 경우)가 컨테이너 안의 것을 덮어씌워버리는 현상이거든요.

    # 해결법: node_modules를 별도 볼륨으로 분리
    services:
      backend:
        volumes:
          - ./backend:/app
          - /app/node_modules   # 이 한 줄이 핵심!
                                # 익명 볼륨으로 컨테이너 내부 것을 보호

    문제 3: 컨테이너 간 통신이 안 될 때

    백엔드에서 DB 접속할 때 localhost로 접속하려다가 실패하는 경우가 많아요. 컨테이너 안에서 localhost는 그 컨테이너 자신을 가리키거든요.

    # ❌ 잘못된 방법 (백엔드 컨테이너 안에서)
    DATABASE_URL=postgresql://myuser:mypassword@localhost:5432/mydb
    
    # ✅ 올바른 방법 (서비스 이름을 호스트로 사용)
    DATABASE_URL=postgresql://myuser:mypassword@db:5432/mydb
    # 'db'는 docker-compose.yml에서 정의한 서비스 이름

    같은 네트워크에 묶인 컨테이너끼리는 서비스 이름이 곧 호스트명이 됩니다. Docker의 내장 DNS가 자동으로 처리해줘요. 이거 알고 나면 진짜 편해집니다.

    문제 4: M1/M2 Mac에서 이미지 아키텍처 오류

    # 에러 메시지
    WARNING: The requested image's platform (linux/amd64) does not match 
    the detected host platform (linux/arm64/v8)
    
    # 해결법: platform 명시
    services:
      db:
        image: postgres:15-alpine
        platform: linux/amd64   # 또는 linux/arm64/v8

    요즘 Apple Silicon Mac 쓰시는 분들 많은데, arm64를 지원하는 이미지를 쓰거나 platform을 명시해주면 해결돼요. 대부분의 공식 이미지들은 멀티 아키텍처를 지원하니까 크게 걱정 안 하셔도 됩니다.

    ✅ 결과 확인: 제대로 떴는지 검증하기

    드디어 됐다! 이제 제대로 동작하는지 확인해봅시다.

    # 전체 서비스 상태 확인
    docker compose ps
    
    # 예상 출력
    NAME              IMAGE                COMMAND                  SERVICE    CREATED        STATUS                    PORTS
    myapp-backend     myapp-backend        "docker-entrypoint.s…"   backend    2 minutes ago  Up 2 minutes              0.0.0.0:3000->3000/tcp
    myapp-db          postgres:15-alpine   "docker-entrypoint.s…"   db         2 minutes ago  Up 2 minutes (healthy)    0.0.0.0:5432->5432/tcp
    myapp-redis       redis:7-alpine       "docker-entrypoint.s…"   cache      2 minutes ago  Up 2 minutes              0.0.0.0:6379->6379/tcp

    STATUS 컬럼에서 Up이면 실행 중, (healthy)면 헬스체크까지 통과한 것입니다. 🎉

    # 네트워크 확인
    docker network ls
    docker network inspect myproject_app-network
    
    # 컨테이너 간 통신 테스트
    docker compose exec backend ping db
    docker compose exec backend ping cache
    
    # 백엔드 API 응답 확인
    curl http://localhost:3000/health

    ▲ docker compose ps 명령어로 확인한 서비스 상태 — 모든 서비스가 Up 상태이고 DB는 healthy 헬스체크까지 통과한 모습

    🎉 팀 협업에서 빛나는 Docker Compose의 진짜 가치

    제가 Docker Compose를 팀 프로젝트에 도입하고 나서 가장 크게 달라진 점은 온보딩 시간이었어요. 예전엔 새 팀원이 오면 환경 세팅하는 데 하루 이상 걸리는 경우도 있었거든요. 근데 이제는 이렇게 끝납니다:

    # 새 팀원 온보딩 전체 과정
    git clone https://github.com/myteam/myproject.git
    cd myproject
    cp .env.example .env   # 환경변수 파일 복사 후 값 채우기
    docker compose up -d   # 끝!

    이 세 줄이면 끝이에요. 진짜로요. OS가 다르든, 로컬에 뭐가 설치돼 있든 상관없이 동일한 환경이 뜹니다. 개발 생산성 측면에서 이게 얼마나 큰 차이인지는 직접 경험해보시면 바로 느끼실 거예요.

    Docker Compose 활용의 주요 이점

    • ✅ 환경 일관성: “내 컴퓨터에서는 되는데” 문제 완전 해결
    • ✅ 빠른 온보딩: 새 팀원도 몇 분 안에 개발 시작 가능
    • ✅ 격리된 환경: 프로젝트별로 독립된 환경, 충돌 없음
    • ✅ 버전 관리: 인프라 설정도 코드로 관리 (Infrastructure as Code)
    • ✅ 프로덕션 근접: 로컬과 운영 환경의 차이 최소화

    ▲ Docker Compose 도입 전후 로컬 개발 환경 비교 — 온보딩 시간, 환경 일관성, 협업 효율성 측면에서의 개선 효과

    자주 묻는 질문 (FAQ)

    Q. Docker Desktop 없이 Docker Compose만 쓸 수 있나요?

    네, Linux 환경에서는 Docker Engine을 설치하고 Compose 플러그인을 별도로 설치하면 돼요. macOS나 Windows라면 Docker Desktop이 가장 간편한 방법이더라고요.

    Q. docker-compose.yml 파일을 Git에 올려도 되나요?

    네, 올려야 합니다! 이게 바로 팀 환경 공유의 핵심이거든요. 단, .env 파일은 절대 올리면 안 됩니다. .env.example 파일을 만들어서 어떤 변수가 필요한지만 공유하세요.

    Q. 프로덕션 배포에도 Docker Compose를 쓰나요?

    소규모 서비스라면 쓸 수 있어요. 하지만 스케일링이나 고가용성이 필요하다면 Kubernetes(쿠버네티스) 같은 오케스트레이션 도구를 고려해야 합니다. 이 부분은 다음 글에서 다룰 예정이에요.

    Q. 컨테이너를 내렸다 올리면 데이터가 사라지나요?

    docker compose down만 하면 볼륨은 유지돼요. 데이터까지 지우려면 docker compose down -v를 써야 하니까 주의하세요!

    마무리: 이제 로컬 개발 환경 걱정은 끝

    오늘 다룬 내용을 정리해볼게요:

    1. Docker Compose의 기본 개념과 일반 Docker 대비 장점
    2. 실전 docker-compose.yml 작성법 (서비스, 볼륨, 네트워크)
    3. 환경변수 분리와 오버라이드 파일 활용
    4. 자주 쓰는 명령어와 실제 트러블슈팅 사례

    처음 Docker Compose를 접하면 yml 파일 문법이 좀 낯설게 느껴질 수 있어요. 저도 들여쓰기 하나 틀려서 에러 뜨는 걸 수십 번은 겪었으니까요. 근데 한 번 손에 익으면 이것 없이 개발하는 게 상상이 안 될 정도로 편해집니다.

    다음 글에서는 Docker Compose로 구성한 환경을 기반으로 CI/CD 파이프라인과 연동하는 방법을 다뤄볼 예정이에요. 로컬에서 테스트한 환경을 그대로 자동화 배포에 활용하는 내용인데, 꽤 실용적인 내용이 될 것 같습니다.

    궁금한 점이나 삽질 경험 있으시면 댓글로 편하게 남겨주세요. 저도 비슷한 거 겪어봤을 확률이 높거든요 😄

  • [Nas] Synology NAS Docker 활용: 앱 설치 및 관리 완벽 가이드

    [Nas] Synology NAS Docker 활용: 앱 설치 및 관리 완벽 가이드

    안녕하세요, 13년차의 서버실 주인장입니다. 오늘은 많은 분들이 홈랩(Homelab)에서 필수적으로 활용하고 계시는 Synology NAS의 Docker 활용법에 대해 이야기해보려고 해요.

    솔직히 처음엔 저도 NAS에 Docker를 왜 써야 하나 싶었습니다. 그냥 패키지 센터에서 앱 깔면 되지 않나? 하는 생각이었죠. 그런데 막상 제가 직접 몇 가지 서비스를 올려보고 관리해보니, Docker(도커)만큼 편하고 강력한 도구가 없더라고요. 특히 Synology NAS는 훌륭한 하드웨어와 DSM(DiskStation Manager)이라는 직관적인 운영체제를 제공해서, 여기에 Docker를 얹으면 그 시너지가 정말 대단합니다. 제가 홈랩에서 이것저것 실험하면서 겪었던 삽질 경험과 해결 과정을 솔직하게 공유해볼게요. 이 글을 통해 여러분도 Synology NAS의 잠재력을 100% 끌어내셨으면 좋겠어요! 🎉

    Synology NAS가 홈 네트워크의 여러 Docker 서비스를 구동하는 모습을 시각화한 다이어그램입니다.

    Docker, 컨테이너가 뭐길래 그렇게 좋다고 할까요?

    본격적인 실전 가이드에 앞서, Docker(도커)와 컨테이너(Container) 개념을 잠깐 짚고 넘어가야겠죠? 쉽게 말해, Docker는 애플리케이션을 실행하는 데 필요한 모든 것(코드, 런타임, 시스템 도구, 라이브러리 등)을 컨테이너(Container)라는 독립적인 패키지로 묶어주는 기술입니다. 이 컨테이너는 어떤 환경에서든 동일하게 작동하도록 보장해주죠.

    기존에는 하나의 서버에 여러 앱을 설치하면, 서로 다른 앱 버전이나 라이브러리 충돌 때문에 골치 아픈 경우가 많았어요. 윈도우에서 프로그램 깔다가 “어? 이 버전은 안 맞는데?” 하는 경험 다들 있으실 겁니다. 😅 가상 머신(VM)도 좋은 대안이지만, OS를 통째로 가상화하다 보니 무겁고 자원 소모가 컸거든요.

    근데 Docker 컨테이너는 호스트 OS의 커널을 공유하면서도, 각각의 앱이 마치 독립적인 OS에서 실행되는 것처럼 격리된 환경을 제공합니다. 💡 그래서 가상 머신보다 훨씬 가볍고(Lightweight) 빠르며(Fast), 효율적(Efficient)이더라고요. Synology NAS 같은 한정된 자원의 장비에서 여러 서비스를 안정적으로 운영하고 싶다면, Docker는 거의 필수라고 할 수 있습니다.

    Synology NAS에 Docker 설치하기: 시작이 반이죠!

    Synology NAS에 Docker를 설치하는 건 정말 간단합니다. DSM(DiskStation Manager)의 패키지 센터(Package Center)를 이용하면 되거든요. 제가 처음 Synology NAS를 접했을 때, 이 패키지 센터의 편리함에 정말 놀랐던 기억이 나네요.

    1. DSM에 관리자 계정으로 로그인합니다.
    2. 패키지 센터를 엽니다.
    3. 검색창에 “Docker”를 입력하거나, “유틸리티” 카테고리에서 Docker 패키지를 찾습니다.
    4. 설치 버튼을 클릭합니다.
    5. 설치 과정이 완료되면, 메인 메뉴에 Docker(컨테이너 관리자) 아이콘이 생성된 것을 확인할 수 있습니다.

    참 쉽죠? 이렇게 설치를 마치면, 이제 웹 UI를 통해 Docker 컨테이너를 관리할 준비가 된 겁니다. Synology는 이 Docker 관리 UI를 컨테이너 관리자(Container Manager)라고 부르더라고요. 처음엔 좀 헷갈렸는데, 그냥 Docker GUI라고 생각하시면 편해요.

    Synology DSM의 컨테이너 관리자 화면입니다. 실행 중인 컨테이너들의 상태를 한눈에 볼 수 있습니다.

    실전! Docker 컨테이너 배포 및 관리 노하우

    이제 본격적으로 Docker 컨테이너를 배포하고 관리하는 방법을 알아볼까요? 저는 주로 두 가지 방법으로 컨테이너를 관리하는데요, 하나는 Synology의 컨테이너 관리자(Container Manager) UI를 이용하는 것이고, 다른 하나는 Docker Compose(도커 컴포즈)를 활용하는 방법입니다. 제가 직접 써보니, 간단한 앱은 UI로, 여러 앱을 묶어서 관리할 때는 Compose가 훨씬 편하더라고요.

    1. 컨테이너 관리자 UI로 Synology Docker 앱 설치하기 (Nginx 예시)

    Synology의 컨테이너 관리자는 마치 앱스토어처럼 이미지를 검색하고 컨테이너를 생성할 수 있게 해줍니다. Nginx(엔진엑스) 웹 서버를 예시로 들어볼게요.

    1. 컨테이너 관리자를 실행합니다.
    2. 왼쪽 메뉴에서 레지스트리(Registry)를 클릭합니다.
    3. 검색창에 “nginx”를 입력하고 검색합니다. 공식 Nginx 이미지를 선택하고 다운로드(Download) 버튼을 클릭합니다. 태그(Tag)는 latest를 선택하면 돼요.
    4. 이미지 다운로드가 완료되면, 왼쪽 메뉴의 이미지(Image) 탭으로 이동합니다. 방금 다운로드한 nginx:latest 이미지를 선택하고 실행(Run) 버튼을 클릭합니다.
    5. 컨테이너 생성 마법사가 나타납니다.
      • 일반 설정(General Settings): 컨테이너 이름(예: my-nginx)을 입력하고, 자동으로 다시 시작(Enable auto-restart)을 체크해두는 게 좋습니다.
      • 포트 설정(Port Settings): Nginx는 기본적으로 80번 포트를 사용합니다. 호스트 포트(Local Port)를 비워두면 자동으로 할당되지만, 특정 포트(예: 8080)로 지정해서 사용하고 싶으면 입력하면 돼요. 저는 보통 8080으로 매핑해서 사용합니다.
      • 볼륨 설정(Volume Settings): Nginx 설정 파일이나 웹 페이지 파일을 외부 폴더와 연결(마운트)할 수 있습니다. 예를 들어, Synology NAS의 /docker/nginx/html 폴더를 컨테이너 내부의 /usr/share/nginx/html 경로에 마운트하면, NAS 폴더에 웹 페이지를 넣으면 바로 Nginx를 통해 서비스할 수 있어요. 💡 주의! NAS 폴더에 권한이 없으면 Nginx가 시작되지 않거나 파일을 읽지 못할 수 있으니, 읽기/쓰기(Read/Write) 권한을 꼭 확인해주세요.
    6. 설정 완료 후 적용(Apply) 버튼을 누르면 컨테이너가 생성되고 바로 실행돼요.

    이제 웹 브라우저에서 http://[NAS_IP_주소]:8080으로 접속해보세요. Nginx 기본 페이지가 보인다면 성공입니다! ✅

    2. Docker Compose로 여러 서비스 한 번에 관리하기 (Watchtower 예시)

    하나의 컨테이너는 UI로 관리하기 편하지만, 여러 컨테이너가 서로 연동되거나 복잡한 설정을 해야 할 때는 Docker Compose(도커 컴포즈)가 빛을 발합니다. YAML(야믈) 파일 하나로 여러 컨테이너의 설정과 관계를 정의할 수 있거든요. 저는 주로 Watchtower(왓치타워) 같은 유틸리티 컨테이너를 Docker Compose로 배포해서 사용합니다. Watchtower는 실행 중인 Docker 컨테이너의 새 이미지가 있는지 주기적으로 확인하고 자동으로 업데이트해주는 고마운 녀석이더라고요. 매번 수동으로 업데이트하는 삽질을 줄여줍니다!

    Synology NAS에서 Docker Compose를 사용하려면 SSH로 NAS에 접속해야 합니다. SSH 접속 방법은 제 이전 글에서 다루었으니 참고해주세요! (나중에 링크 추가 예정) ➡️

    1. SSH로 NAS에 로그인합니다.
    2. 컨테이너 설정을 저장할 폴더를 만듭니다. (예: /volume1/docker/watchtower)
    3. 해당 폴더로 이동하여 docker-compose.yml 파일을 생성하고 아래 내용을 입력합니다.
    version: '3.8'
    services:
      watchtower:
        image: containrrr/watchtower
        container_name: watchtower
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
        environment:
          - TZ=Asia/Seoul # 시간대 설정 (선택 사항)
          - WATCHTOWER_CLEANUP=true # 이전 이미지 삭제
          - WATCHTOWER_SCHEDULE=0 4 * * * # 매일 새벽 4시에 실행 (Cron 표현식)
        restart: unless-stopped
    

    위 YAML 파일은 containrrr/watchtower 이미지를 사용하고, Docker 데몬과 통신하기 위해 /var/run/docker.sock을 마운트합니다. 또한, 매일 새벽 4시에 컨테이너를 업데이트하고 이전 이미지를 정리하도록 설정했어요. 환경 변수(Environment Variables)를 통해 다양한 옵션을 줄 수 있으니, Watchtower 공식 문서를 참고하시면 더 많은 기능을 활용할 수 있습니다.

    1. docker-compose.yml 파일이 있는 디렉토리에서 다음 명령어를 실행하여 컨테이너를 배포합니다.
    sudo docker compose up -d
    

    -d 옵션은 컨테이너를 백그라운드에서 실행하라는 뜻입니다. 명령어를 실행하면 Watchtower 컨테이너가 생성되고 바로 작업을 시작할 거예요. 나중에 컨테이너를 중지하고 싶다면 sudo docker compose down 명령어를 사용하면 됩니다.

    ⚠️ 삽질 경험 & 트러블슈팅: 이것만 알면 고생 끝!

    제가 Docker를 처음 다룰 때 가장 많이 겪었던 문제들은 바로 권한과 포트 충돌이었습니다. 독자분들은 저처럼 삽질하지 마시라고 몇 가지 팁을 드릴게요.

    • 볼륨 마운트(Volume Mount) 권한 문제: 컨테이너가 호스트(NAS)의 특정 폴더에 접근해야 할 때, 해당 폴더에 컨테이너가 접근할 수 있는 권한이 없으면 에러가 발생합니다. 예를 들어, Nginx가 웹 페이지를 읽지 못하거나, Plex가 미디어 파일을 스캔하지 못하는 경우가 대표적이죠.

      해결책: Synology DSM의 제어판 > 공유 폴더에서 해당 폴더의 권한 설정을 확인하고, everyone 그룹 또는 Docker 컨테이너가 사용하는 사용자(대부분 root 또는 특정 UID/GID)에게 읽기/쓰기 권한을 부여해야 합니다. 저는 보통 777 권한을 주기도 하는데, 보안상 좋지 않으니 필요한 최소한의 권한만 부여하는 게 좋아요.
    • 포트 충돌(Port Conflict): 이미 NAS에서 사용 중인 포트(예: DSM 웹 UI의 5000/5001번)를 Docker 컨테이너가 사용하려고 하면 충돌이 발생합니다.

      해결책: 컨테이너 생성 시 호스트 포트(Local Port)를 비어있는 다른 포트(예: 80 -> 8080, 443 -> 8443)로 변경하여 매핑해주면 됩니다. netstat -tulnp 명령어로 현재 사용 중인 포트를 확인할 수 있더라고요.
    • 이미지 다운로드 실패: 인터넷 연결 문제나 Docker Hub(도커 허브) 서버 문제로 이미지를 다운로드하지 못하는 경우가 있습니다.

      해결책: 인터넷 연결 상태를 확인하고, 잠시 기다렸다가 다시 시도하거나, 다른 미러 서버를 사용하는 방법을 찾아볼 수도 있습니다.

    이런 문제들을 겪으면서 “아, 진짜 왜 안 되는 거야!” 하고 답답했던 순간들이 많았는데, 결국은 대부분 설정 문제더라고요. 꼼꼼하게 확인하는 습관이 중요합니다. 💡

    ✅ 결과 확인 및 컨테이너 관리

    컨테이너가 제대로 실행되고 있는지 확인하는 것은 매우 중요합니다. Synology의 컨테이너 관리자 UI나 SSH 터미널에서 쉽게 확인할 수 있어요.

    1. 컨테이너 관리자 UI에서 확인: 왼쪽 메뉴의 컨테이너(Container) 탭을 클릭하면 현재 실행 중인 모든 컨테이너 목록과 상태를 한눈에 볼 수 있습니다. 각 컨테이너를 클릭하면 CPU, 메모리 사용량 등 자세한 정보를 확인할 수 있어요.
    2. SSH 터미널에서 확인: sudo docker ps 명령어를 사용하면 현재 실행 중인 컨테이너 목록을 확인할 수 있습니다. 모든 컨테이너(종료된 컨테이너 포함)를 보려면 sudo docker ps -a를 사용합니다. 특정 컨테이너의 로그를 확인하고 싶다면 sudo docker logs [컨테이너_이름_또는_ID] 명령어를 사용하면 되더라고요.

    이런 식으로 주기적으로 컨테이너 상태를 점검하고, 문제가 발생하면 로그를 확인하여 빠르게 대처하는 것이 중요합니다. 멘토인 제가 늘 강조하는 부분이죠! 😉

    Portainer 웹 UI 대시보드에서 Docker 컨테이너 및 스택 개요를 보여주는 스크린샷입니다.

    마무리하며: Synology NAS와 Docker, 무한한 가능성!

    오늘은 Synology NAS에 Docker를 설치하고 컨테이너를 배포, 관리하는 방법에 대해 자세히 알아봤습니다. 제가 직접 홈랩에서 13년 동안 다양한 장비를 만져보면서 느낀 건, Synology NAS와 Docker의 조합은 정말 강력하다는 겁니다. 여러분의 NAS를 단순한 파일 서버를 넘어, Plex 미디어 서버, Home Assistant 스마트 홈 허브, Nextcloud 개인 클라우드 등 무궁무진한 서비스의 허브로 탈바꿈시킬 수 있어요.

    물론 처음에는 생소하고 어려운 부분도 있을 겁니다. 저도 그랬거든요! 하지만 한 번 익숙해지면 이 편리함에서 헤어나오기 어렵습니다. 삽질은 성장의 어머니라고 하잖아요? 😅 여러분의 삽질을 줄여드리고자 이 글을 썼으니, 부디 도움이 되셨기를 바랍니다.

    다음 글에서는 Synology NAS에서 Reverse Proxy(리버스 프록시)와 Let’s Encrypt(렛츠 인크립트)를 활용하여 Docker 컨테이너에 외부에서 안전하게 접근하는 방법에 대해 다뤄볼 예정입니다. 기대해주세요! 그럼 다음 글에서 또 만나요! 👋

  • [Nas] Docker Compose로 NAS에 앱 배포 및 관리하기: Synology, TrueNAS SCALE 가이드

    [Nas] Docker Compose로 NAS에 앱 배포 및 관리하기: Synology, TrueNAS SCALE 가이드

    13년차 서버실: Docker Compose로 NAS 앱 배포 및 관리 – Synology, TrueNAS SCALE 실전 가이드

    안녕하세요! 13년차 인프라 엔지니어입니다. 오늘은 많은 분들이 궁금해하실 주제를 다뤄볼게요. 바로 Docker Compose를 활용해서 NAS(Network Attached Storage)에 다양한 애플리케이션을 배포하고 관리하는 방법인데요. Synology와 TrueNAS SCALE 환경에서 직접 경험했던 내용을 바탕으로 실전 팁을 공유해드리겠습니다. 혹시 NAS를 파일 저장소로만 쓰고 계신가요? Docker Compose와 함께라면 여러분의 NAS가 훨씬 더 똑똑한 홈랩 서버로 변신합니다! 😉

    NAS 환경에서 Docker Compose를 활용한 애플리케이션 배포 및 관리 아키텍처 개요

    왜 NAS에 Docker Compose를 써야 할까요?

    NAS를 운영하다 보면 언젠가는 ‘파일 저장소 말고 다른 기능도 쓰고 싶은데…’ 하는 생각이 들게 돼요. 개인 블로그를 운영하고 싶거나, 영화·음악 스트리밍 서버를 구축하고 싶을 때 말이죠. 예전 같으면 복잡한 설치 과정과 설정 때문에 망설였겠지만, Docker와 Docker Compose를 알게 된 후로는 정말 달라졌어요.

    Docker는 애플리케이션을 컨테이너라는 격리된 환경에 담아 실행하는 기술입니다. 덕분에 운영체제나 다른 프로그램과의 충돌 걱정 없이 원하는 앱을 쉽게 설치하고 실행할 수 있죠. 다만 여러 개의 컨테이너를 묶어서 관리하려면 일일이 명령어를 입력해야 해서 번거로울 때가 많아요. 이때 등장하는 것이 바로 Docker Compose입니다!

    쉽게 말해, Docker Compose는 YAML이라는 설정 파일을 사용해서 여러 컨테이너로 구성된 애플리케이션을 한 번에 정의하고 실행할 수 있게 해주는 도구예요. 마치 오케스트라의 지휘자처럼 여러 악기(컨테이너)들이 조화롭게 연주(실행)되도록 지휘하는 역할을 하는 거죠.

    Docker Compose를 NAS에서 사용하면 좋은 점은 다음과 같아요:

    • ✅ 간편한 배포: 복잡한 설정 과정을 YAML 파일 하나로 정의하고, 단 한 번의 명령어로 여러 컨테이너를 한 번에 띄울 수 있어요.
    • ✅ 쉬운 관리: 컨테이너의 시작, 중지, 재시작, 삭제 등을 Compose 명령어로 간단하게 관리할 수 있습니다.
    • ✅ 재현성: 동일한 YAML 설정 파일만 있으면 언제 어디서든 똑같은 환경을 구축할 수 있어요. 개발, 테스트, 운영 환경 간의 차이로 인한 문제를 줄여주거든요.
    • ✅ 포트 충돌 방지: 각 컨테이너가 사용할 포트(Port)를 명확하게 지정하여 충돌을 피할 수 있습니다.
    • ✅ 확장성: 필요에 따라 컨테이너 수를 늘리거나 줄이기가 정말 쉬워요.

    Synology와 TrueNAS SCALE, Docker Compose 활용법

    Synology DSM과 TrueNAS SCALE은 각기 다른 방식으로 Docker 환경을 제공하지만, Docker Compose를 활용하는 기본 원리는 동일합니다. 핵심은 docker-compose.yml 파일을 작성하고 실행하는 거죠.

    1. Synology NAS에서 Docker Compose 사용하기

    Synology NAS에서는 ‘Docker’ 패키지를 설치하면 Docker Compose 기능을 사용할 수 있어요. DSM의 ‘패키지 센터’에서 Docker를 검색하여 설치해주세요. 저는 보통 SSH로 NAS에 접속해서 작업하는 것을 선호하지만, DSM의 ‘텍스트 편집기’나 ‘File Station’을 이용해 YAML 파일을 작성하고 관리할 수도 있습니다.

    실행 단계:

    1. SSH 접속: Putty(Windows) 또는 터미널(macOS/Linux)을 이용해 NAS에 SSH로 접속합니다.
    2. 작업 디렉토리 생성: 원하는 위치에 애플리케이션을 위한 디렉토리를 만들어요. 예: mkdir /volume1/docker/my-app && cd /volume1/docker/my-app
    3. docker-compose.yml 파일 작성: 텍스트 편집기(vi, nano 등)를 이용해 docker-compose.yml 파일을 생성하고 내용을 작성합니다.
    4. Docker Compose 실행: docker-compose up -d 명령어를 실행하면 설정된 컨테이너들이 백그라운드(-d)에서 실행돼요.

    예시: Nginx 웹 서버와 Portainer (컨테이너 관리 도구) 배포

    Portainer는 Docker 환경을 웹 UI로 쉽게 관리할 수 있게 해주는 정말 유용한 도구예요. NAS에 Portainer를 설치해두면 컨테이너 관리가 훨씬 편해진답니다.

    
    version: '3.8'
    
    services:
      portainer:
        image: portainer/portainer-ce:latest
        container_name: portainer
        restart: unless-stopped
        security_opt:
          - no-new-privileges:true
        ports:
          - "8000:8000"
          - "9443:9443"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - portainer_data:/data
        networks:
          - portainer_net
    
      nginx:
        image: nginx:latest
        container_name: my-nginx
        restart: unless-stopped
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ./nginx.conf:/etc/nginx/nginx.conf:ro
          - ./html:/usr/share/nginx/html:ro
        depends_on:
          - portainer
        networks:
          - portainer_net
    
    volumes:
      portainer_data:
    
    networks:
      portainer_net:
        driver: bridge
    

    이 파일을 /volume1/docker/portainer-nginx/docker-compose.yml에 저장하고, 해당 디렉토리에서 docker-compose up -d를 실행하면 Portainer와 Nginx 웹 서버가 동시에 실행돼요. Portainer는 http://NAS_IP:9443 (SSL), Nginx는 http://NAS_IP로 접속할 수 있습니다.

    Synology DSM에서 Docker 패키지를 설치하는 과정

    2. TrueNAS SCALE에서 Docker Compose 사용하기 (TrueNAS SCALE Apps)

    TrueNAS SCALE은 Kubernetes 기반으로 앱을 관리하는 ‘Apps’ 기능을 제공해요. Docker Compose 파일을 직접 사용하는 방식과는 조금 다르지만, Apps 기능을 통해 원하는 애플리케이션을 쉽게 설치하고 관리할 수 있다는 점은 같습니다. TrueNAS SCALE의 Apps는 Helm chart라는 것을 사용하는데, 많은 경우 Docker Compose 파일과 유사한 구조를 가져요.

    실행 단계:

    1. Apps 메뉴 접근: TrueNAS SCALE 웹 UI에서 ‘Apps’ 메뉴로 이동합니다.
    2. Catalogs 설정: 원하는 애플리케이션을 설치하기 위해 Catalog(앱 스토어 같은 개념)를 추가해야 해요. 커뮤니티에서 제공하는 다양한 Catalog들이 있습니다.
    3. 애플리케이션 설치: Catalog에서 원하는 앱을 선택하고 설치를 진행하면 돼요. 커스텀 앱을 직접 등록하여 Docker Compose 파일처럼 관리할 수도 있습니다.

    주의사항: TrueNAS SCALE의 Apps는 Kubernetes 기반이므로, Docker Compose의 docker-compose.yml 파일을 직접 실행하는 방식과는 다릅니다. 하지만 많은 커뮤니티 앱들이 Docker Compose 구조를 따르고 있어서, YAML 파일의 내용을 이해하고 있다면 앱 설정 시 도움이 돼요. 직접 Docker Compose 파일을 적용하려면 TrueNAS CORE의 ‘iocage’ 플러그인이나 TrueNAS SCALE에서 별도의 VM을 구성해야 할 수도 있습니다. 다만 대부분의 일반 사용자는 Apps 기능으로 충분히 원하는 앱을 설치하고 관리할 수 있어요.

    TrueNAS SCALE의 Apps 메뉴에서 다양한 애플리케이션을 탐색하고 설치하는 과정

    실전 팁 & 트러블슈팅 ⚠️

    13년간 Docker를 다루면서 겪었던 문제와 팁을 공유해 드릴게요. 처음엔 이것 때문에 밤새 고생했던 기억이 있어요. ㅎㅎ

    • 포트 충돌 (Port Conflict): 가장 흔한 문제예요. docker-compose.yml 파일에서 ports 섹션에 이미 사용 중인 호스트 포트를 지정하면 컨테이너가 실행되지 않습니다. Synology NAS의 경우, DSM 자체적으로 사용하는 포트와 충돌하지 않도록 주의해야 해요. 예를 들어 80번 포트는 DSM의 웹 스테이션 등이 사용할 수 있으니, 다른 포트(예: 8080)로 변경하는 것이 훨씬 안전합니다.
    • 볼륨 마운트 경로: 컨테이너 내의 데이터가 호스트 NAS의 특정 경로에 저장되도록 volumes 설정을 잘 해야 합니다. Synology에서는 /volume1/docker/app-name 같은 경로를 주로 사용하고, TrueNAS SCALE에서는 /mnt/poolname/dataset/app-name 같은 경로를 써요. 경로가 잘못되면 데이터가 사라지거나 컨테이너가 제대로 동작하지 않을 수 있으니 주의하세요. 경로 지정 시에는 항상 절대 경로(Absolute Path)를 사용하는 게 정답이에요.
    • 권한 문제 (Permission Issues): 컨테이너가 호스트 파일 시스템에 접근할 때 권한 문제가 발생할 수 있습니다. Docker Compose 파일의 user 옵션을 설정하거나, 호스트 볼륨의 권한을 컨테이너 사용자의 권한에 맞게 조정해야 할 수 있어요.
    • Docker Compose 버전 호환성: version 필드에 명시된 Compose 파일 형식 버전과 실제 사용 중인 Docker Compose 엔진 버전 간의 호환성을 확인하세요. 최신 버전에서는 지원되지 않는 기능이 이전 버전에 있을 수 있습니다.
    • 네트워크 설정: 여러 컨테이너가 서로 통신해야 하는 경우, networks 설정을 올바르게 해야 합니다. 기본적으로는 bridge 네트워크가 사용되지만, 복잡한 구성에서는 custom network을 사용해야 할 때도 있어요.

    💡 팁: 문제가 발생했을 때, docker-compose logs 명령어로 해당 서비스의 로그를 확인하세요. 정말 많은 힌트를 얻을 수 있거든요! 저도 이 명령어로 대부분의 문제를 해결했어요.

    결과 확인 및 관리

    Docker Compose 명령어를 통해 컨테이너를 실행한 후에는 상태를 확인하는 것이 중요합니다.

    • docker-compose ps: 현재 실행 중인 컨테이너 목록과 상태를 보여줘요.
    • docker-compose logs -f : 특정 컨테이너의 실시간 로그를 확인할 수 있습니다. (Ctrl+C로 종료)
    • docker-compose down: 실행 중인 컨테이너들을 중지하고 관련된 네트워크, 볼륨 등을 삭제해요. (데이터 보존 여부는 볼륨 설정에 따라 다름)
    • docker-compose pull: Docker 이미지의 최신 버전을 다운로드합니다.
    • docker-compose up -d --build: 설정 파일을 새로 빌드하고 컨테이너를 실행해요.

    Portainer 대시보드를 통해 Synology 또는 TrueNAS SCALE에서 실행 중인 Docker 컨테이너들을 한눈에 관리하는 모습

    마무리하며

    지금까지 Docker Compose를 활용하여 Synology와 TrueNAS SCALE NAS 환경에서 애플리케이션을 배포하고 관리하는 방법에 대해 알아봤습니다. 처음에는 조금 복잡해 보일 수 있지만, 한 번 익혀두면 NAS의 활용도를 정말 무궁무진하게 높일 수 있는 강력한 도구예요.

    저도 처음엔 간단한 웹 서버 하나 띄우는 것도 버거웠는데, 지금은 여러 컨테이너를 엮어 복잡한 서비스를 구축할 수 있게 됐네요. 여러분도 오늘 알려드린 내용을 바탕으로 차근차근 시도해보신다면, 분명 여러분만의 멋진 홈랩 환경을 구축하실 수 있을 겁니다.

    다음 글에서는 Docker Compose를 활용한 Home Assistant 설치 및 연동에 대한 실전 가이드를 다룰 예정이니 많은 기대 부탁드립니다! 혹시 오늘 내용 중에 궁금한 점이 있다면 언제든지 댓글로 남겨주세요. 함께 해결해나가겠습니다. 😉

  • [NAS] TrueNAS SCALE 앱 배포: Docker 컨테이너부터 관리까지

    NAS가 단순 저장소였던 시대는 끝났습니다

    홈랩을 운영하다 보면 어느 순간 이런 생각이 드시지 않나요? “NAS에 데이터만 넣어두기엔 너무 아깝다.” 저도 처음엔 그냥 파일 서버로 쓰다가, 어느 날 Plex를 띄워보고 나서 생각이 완전히 바뀌었거든요. 그 이후로 TrueNAS SCALE 위에서 십수 개의 서비스를 돌리고 있습니다.

    근데 솔직히 말씀드리면, 처음에 TrueNAS SCALE 앱 시스템을 접했을 때 꽤 헷갈렸어요. 버전마다 배포 방식이 달라지고, 한글 자료도 많지 않아서 삽질을 꽤 했거든요. 이번 글에서는 제가 직접 겪어온 경험을 바탕으로, TrueNAS SCALE에서 앱을 배포하고 관리하는 방법을 처음부터 끝까지 정리해 드리겠습니다.

    TrueNAS SCALE 위에서 여러 컨테이너 앱이 동작하는 홈랩 전체 아키텍처. 스토리지, 네트워킹, 앱 레이어가 통합된 모습입니다.

    TrueNAS SCALE 앱 시스템이 바뀐 이유

    여기서 중요한 역사 이야기를 하나 해야 할 것 같아요. TrueNAS SCALE의 앱 시스템은 버전을 거치면서 꽤 큰 변화가 있었거든요.

    초기 버전(Angelfish, Bluefin, Cobia 등)에서는 K3s(경량 쿠버네티스)를 기반으로 앱을 운영했습니다. 쿠버네티스를 쓴다니까 좋아 보이긴 했는데, 일반 홈랩 사용자 입장에서는 진입 장벽이 꽤 높았어요. Helm 차트 구조도 이해해야 하고, 리소스 관리가 복잡하다는 불만도 많았고요.

    그래서 iXsystems는 Electric Eel(24.10) 버전부터 TrueNAS SCALE 앱 시스템을 Docker Compose 기반으로 전면 바꿨습니다. 쿠버네티스를 걷어내고 훨씬 직관적인 Docker Compose 방식을 채택한 거죠. 솔직히 처음엔 “아니 왜 바꾸는 거야”라고 생각했는데, 써보니 훨씬 낫더라고요.

    • 이전(~Dragonfish): K3s + Helm Chart 기반, TrueCharts 커뮤니티 카탈로그 의존도 높음
    • 이후(Electric Eel~): Docker Compose 기반, 공식 카탈로그 + 커스텀 컨테이너 지원

    이 글은 Electric Eel 이후의 Docker Compose 기반 앱 시스템을 중심으로 설명합니다. 혹시 구버전 사용 중이시라면 업그레이드를 먼저 하시길 권장합니다.

    시작 전 준비사항 체크

    본격적으로 TrueNAS SCALE 앱 배포에 들어가기 전에 확인해야 할 것들이 있어요. 저도 이걸 안 하고 바로 들어갔다가 중간에 막혀서 처음부터 다시 한 경험이 있거든요 😅

    1. 풀(Pool) 설정 확인: 앱 데이터를 저장할 ZFS 풀이 생성되어 있어야 합니다. 저는 SSD 별도 풀을 만들어서 앱 전용으로 씁니다.
    2. Apps 전용 풀 지정: TrueNAS SCALE에서 Apps 탭으로 이동하면, 앱 데이터를 저장할 풀을 처음 한 번 지정하게 돼 있어요. 나중에 바꾸기 귀찮으니 처음에 잘 골라두세요.
    3. 네트워크 설정: 외부에서 접근이 필요한 앱이라면, 공유기 포트 포워딩이나 Reverse Proxy(리버스 프록시) 설정도 미리 생각해두면 좋습니다.
    4. TrueNAS SCALE 버전: 앞서 말씀드린 것처럼, 가능하면 Electric Eel(24.10) 이상으로 업그레이드하고 시작하세요.

    TrueNAS SCALE 앱 카탈로그에서 첫 번째 앱 설치하기

    준비가 됐다면 이제 실전입니다! TrueNAS SCALE 웹 UI 왼쪽 메뉴에서 Apps를 클릭하세요. 처음 접속하면 앱 풀(pool)을 선택하라고 나옵니다. 앞서 준비한 풀을 선택하면 돼요.

    앱 화면으로 들어오면 Discover Apps 버튼이 보입니다. 여기서 공식 카탈로그에 등록된 앱들을 검색하고 설치할 수 있어요. Plex, Nextcloud, Jellyfin, Home Assistant 같은 인기 홈랩 앱들이 대부분 등록되어 있습니다.

    예시로 Jellyfin(미디어 서버)을 설치해볼게요.

    1. Discover Apps에서 “Jellyfin” 검색
    2. 앱 카드 클릭 → Install 버튼 클릭
    3. 설정 화면에서 주요 항목 입력:
      • Application Name: jellyfin (기본값 그대로)
      • Network Configuration: 포트 번호 설정 (기본 8096)
      • Storage Configuration: 미디어 파일이 있는 데이터셋 경로 지정
    4. Install 클릭 후 배포 완료 대기

    설치가 완료되면 앱 목록에 Jellyfin이 나타나고, http://NAS-IP:8096으로 접속할 수 있어요. 드디어 됐다! 라는 느낌이 이때 오더라고요 🎉

    TrueNAS SCALE Apps 탭의 카탈로그 화면. Discover Apps에서 원하는 앱을 검색하고 GUI로 간편하게 설치할 수 있습니다.

    Docker 컨테이너 직접 배포하기 (Custom App)

    카탈로그에 없는 앱을 써야 할 때가 있죠. 저도 특정 오픈소스 툴을 올리고 싶은데 카탈로그에 없을 때, 직접 Docker 이미지를 지정해서 배포하는 방법을 씁니다. Docker on TrueNAS를 활용하는 방식이에요.

    Discover Apps 화면 오른쪽 위를 보면 Custom App 버튼이 있습니다. 이걸 누르면 Docker Compose 방식으로 직접 컨테이너를 정의할 수 있는 화면이 나와요.

    예시로 Uptime Kuma(서비스 모니터링 앱)를 커스텀 앱으로 배포해볼게요.

    # Custom App 설정에서 사용하는 Docker Compose 예시
    services:
      uptime-kuma:
        image: louislam/uptime-kuma:latest
        container_name: uptime-kuma
        ports:
          - "3001:3001"
        volumes:
          - /mnt/pool/apps/uptime-kuma:/app/data
        restart: unless-stopped

    TrueNAS SCALE의 Custom App UI에서는 이걸 GUI 폼으로 입력할 수 있어요. 직접 YAML을 쓰는 방식도 지원되고, 폼 형태로도 입력 가능합니다.

    핵심 입력 항목들은 이렇습니다:

    항목 설명 예시
    Image Repository Docker Hub 이미지 이름 louislam/uptime-kuma
    Image Tag 버전 태그 latest 또는 1.23.x
    Container Port 컨테이너 내부 포트 3001
    Node Port 호스트에서 접근할 포트 3001
    Host Path TrueNAS 데이터셋 경로 /mnt/pool/apps/uptime-kuma
    Mount Path 컨테이너 내부 마운트 경로 /app/data

    💡 팁: 볼륨 경로는 반드시 미리 ZFS 데이터셋으로 만들어두고 마운트하는 게 좋습니다. 그냥 디렉토리 경로를 쓰면 나중에 스냅샷 관리가 안 되거든요. 이거 처음에 몰라서 나중에 다 옮긴 적이 있습니다 ㅎㅎ.

    환경 변수와 네트워크 설정 팁

    컨테이너를 배포할 때 환경 변수(Environment Variable) 설정이 필요한 경우가 많아요. 예를 들어 데이터베이스 비밀번호, API 키 같은 것들이요.

    Custom App 설정 화면에서 Environment Variables 섹션을 찾으면 Key-Value 형태로 추가할 수 있습니다.

    # 환경 변수 예시 (Nextcloud 같은 경우)
    MYSQL_DATABASE=nextcloud
    MYSQL_USER=ncuser
    MYSQL_PASSWORD=your_secure_password
    NEXTCLOUD_ADMIN_USER=admin
    NEXTCLOUD_ADMIN_PASSWORD=admin_password

    네트워크 관련해서 한 가지 더 말씀드리면, TrueNAS SCALE에서 여러 앱이 서로 통신해야 할 때(예: 웹 앱 + DB 컨테이너) 같은 Docker 네트워크에 묶어야 해요. Custom App에서 Network Configuration 섹션에서 네트워크를 지정할 수 있습니다. 이 부분은 처음엔 좀 헷갈릴 수 있는데, 같은 앱 스택이라면 동일한 사용자 정의 네트워크를 사용하면 돼요.

    ⚠️ 트러블슈팅: 자주 겪는 문제들

    13년 동안 인프라 일을 하면서 깨달은 건, 문서대로 안 되는 게 정상이라는 거예요 ㅎㅎ. TrueNAS SCALE 앱 배포하면서 자주 만나는 문제들과 해결법을 공유합니다.

    문제 1: 앱이 Deploying 상태에서 멈춤

    가장 흔한 문제예요. 배포 눌렀는데 한참 동안 Deploying 상태에서 안 바뀌는 경우.

    원인 대부분은 이미지 풀(pull) 실패입니다. 이미지 이름이 틀렸거나, NAS가 인터넷에 제대로 연결 안 됐을 때 주로 발생해요.

    # TrueNAS Shell에서 컨테이너 로그 확인
    docker logs [컨테이너_이름]
    
    # 이미지가 제대로 받아졌는지 확인
    docker images | grep [앱_이름]

    문제 2: 볼륨 마운트 권한 오류

    앱은 뜨는데 데이터를 못 쓰는 경우가 있어요. 특히 컨테이너가 특정 UID로 실행되는데, 마운트한 경로의 소유자가 다를 때 발생합니다.

    # TrueNAS Shell에서 권한 확인 및 수정
    ls -la /mnt/pool/apps/uptime-kuma
    
    # 필요하다면 소유자 변경 (999는 예시 UID, 앱마다 다름)
    chown -R 999:999 /mnt/pool/apps/uptime-kuma

    💡 팁: Docker Hub의 해당 이미지 문서에 어떤 UID로 실행되는지 나와 있는 경우가 많아요. 미리 확인하고 데이터셋 권한을 맞춰두면 삽질을 줄일 수 있습니다.

    문제 3: 포트 충돌

    “이미 사용 중인 포트”라는 오류가 뜨는 경우요. 앱들이 기본 포트가 겹칠 때 발생합니다. 예를 들어 여러 웹 앱이 다 80번 포트를 쓰려 하면 충돌이 나죠.

    해결책은 단순합니다. 앱 설치 시 Node Port를 겹치지 않게 다른 번호로 바꿔주면 돼요. 저는 개인적으로 앱별로 포트 번호를 스프레드시트에 정리해두고 쓰고 있습니다. 처음엔 귀찮아 보여도, 앱이 10개 이상 넘어가면 이게 필수예요.

    TrueNAS SCALE 앱 관리 및 업데이트

    설치하고 끝이 아니죠. 앱 관리도 중요합니다. TrueNAS SCALE에서 설치된 앱의 업데이트는 Apps 탭 → Installed 화면에서 할 수 있어요.

    업데이트 가능한 앱이 있으면 배지(badge)가 표시되고, Update All 버튼으로 한 번에 업데이트도 가능합니다. 근데 저는 한 번에 다 올리기보다는, 중요한 앱은 하나씩 올리고 확인하는 편이에요. 한 번에 다 올렸다가 뭔가 깨지면 어디서 문제가 생긴 건지 찾기 어렵거든요.

    앱 데이터 백업은 ZFS 스냅샷을 활용하는 게 최고입니다. 앱 데이터를 담은 데이터셋에 정기 스냅샷을 걸어두면, 앱이 망가졌을 때 스냅샷으로 롤백이 가능해요. 이게 TrueNAS SCALE을 쓰는 가장 큰 이유 중 하나라고 생각합니다.

    TrueNAS SCALE Apps의 Installed 탭. 실행 중인 앱 상태, 업데이트 가능 여부, 리소스 사용량을 한눈에 확인할 수 있습니다.

    ✅ 실전 구성: 제 홈랩 앱 운영 사례

    참고로 현재 제가 TrueNAS SCALE 위에서 돌리고 있는 주요 앱들을 공유할게요. 비슷한 구성을 계획하시는 분들께 도움이 될 것 같아서요.

    앱 이름 용도 설치 방법
    Jellyfin 미디어 서버 (영화, 음악) 공식 카탈로그
    Nextcloud 개인 클라우드 스토리지 공식 카탈로그
    Home Assistant 스마트홈 허브 공식 카탈로그
    Uptime Kuma 서비스 모니터링 Custom App
    Vaultwarden 비밀번호 관리자 Custom App
    Nginx Proxy Manager 리버스 프록시 + SSL Custom App

    모두 ZFS 데이터셋에 데이터를 저장하고, 매일 새벽 3시에 스냅샷이 자동으로 찍히도록 설정해뒀습니다. 덕분에 앱 업데이트 실패나 설정 꼬임 같은 상황에서도 걱정 없이 복구할 수 있어요. 실제로 Home Assistant 업데이트 후 통합 설정이 날아갔을 때 스냅샷으로 5분 만에 복구한 적도 있습니다 😅

    현재 운영 중인 홈랩의 앱 구성 요약. TrueNAS SCALE 위에서 미디어, 클라우드, 모니터링, 보안 앱들이 유기적으로 연동되는 모습입니다.

    마무리: TrueNAS SCALE 앱 배포, 이렇게 시작하세요

    오늘 다룬 내용을 간단히 정리해볼게요.

    • ✅ TrueNAS SCALE은 Electric Eel(24.10)부터 Docker Compose 기반 앱 시스템으로 전환됨
    • ✅ 공식 카탈로그 앱은 GUI로 손쉽게 설치 가능
    • ✅ 카탈로그에 없는 앱은 Custom App 기능으로 Docker 이미지 직접 지정 배포
    • ✅ 볼륨은 반드시 ZFS 데이터셋으로 분리해서 관리할 것
    • ✅ 스냅샷 정책을 함께 설정해두면 백업/복구가 정말 편함

    처음 TrueNAS SCALE 앱 시스템을 접하면 설정 항목이 많아서 막막할 수 있어요. 근데 한 번 익숙해지면 정말 편합니다. 스토리지와 앱을 같은 플랫폼에서 관리한다는 게 이렇게 편할 줄 몰랐다는 생각이 드실 거예요.

    다음 글에서는 Nginx Proxy Manager와 Let’s Encrypt를 이용한 HTTPS 설정을 다룰 예정입니다. 외부에서 도메인으로 안전하게 접근하는 방법인데, 홈랩을 한 단계 업그레이드하고 싶은 분들께 유용할 거예요. 이전 글에서 다뤘던 ZFS 데이터셋 구성과 함께 보시면 더 도움이 됩니다.

    궁금한 점이 있으면 댓글로 남겨주세요. 같이 삽질하며 발전하는 홈랩 라이프, 응원합니다! 🎉