HedgeDoc – 실시간 협업 마크다운 에디터 Docker 설치 가이드




개요

HedgeDoc(구 CodiMD)는 실시간 협업이 가능한 오픈소스 마크다운 에디터입니다. Google Docs처럼 여러 사람이 동시에 같은 문서를 편집할 수 있으며, 마크다운 문법으로 빠르게 문서를 작성할 수 있습니다. 노트 공유 링크만 전달하면 바로 협업을 시작할 수 있어, 팀 문서 작성, 회의록, 기술 문서화에 매우 유용합니다.

공식 사이트: https://hedgedoc.org
GitHub: https://github.com/hedgedoc/hedgedoc
GitHub Stars: 5,000+
라이선스: AGPL-3.0


HedgeDoc란?

HedgeDoc는 HackMD에서 파생된 오픈소스 프로젝트로, 셀프 호스팅이 가능한 협업 마크다운 에디터입니다. 브라우저만 있으면 어디서든 접속해서 문서를 작성하고 공유할 수 있습니다.

핵심 철학

  • Ideas grow better together: 아이디어는 함께할 때 더 잘 자랍니다
  • 실시간 협업: 여러 명이 동시에 편집
  • 셀프 호스팅: 데이터를 자신의 서버에 보관
  • 마크다운 기반: 빠르고 깔끔한 문서 작성

HackMD vs HedgeDoc

항목HackMDHedgeDoc
호스팅클라우드 서비스셀프 호스팅
비용무료/유료 플랜완전 무료
데이터 소유HackMD 서버자체 서버
커스터마이징제한적자유로움

주요 특징

1. 실시간 협업 편집

  • 여러 사용자가 동시에 문서 편집
  • 실시간 커서 위치 표시
  • 변경 사항 즉시 동기화
  • Google Docs와 유사한 협업 경험

2. 마크다운 지원

  • 표준 마크다운 문법
  • 실시간 미리보기 (Split View)
  • 코드 구문 강조
  • 수식 지원 (LaTeX/KaTeX)
  • 체크리스트, 테이블

3. 다이어그램 및 차트

  • Mermaid: 플로우차트, 시퀀스 다이어그램
  • Chart.js: 차트 및 그래프
  • PlantUML: UML 다이어그램
  • GraphViz: DOT 언어 다이어그램

4. 슬라이드 프레젠테이션

  • reveal.js 기반 슬라이드
  • 마크다운으로 프레젠테이션 제작
  • --- 구분자로 슬라이드 분리

5. 권한 관리

권한 레벨설명
Freely누구나 편집 가능
Editable로그인 사용자만 편집
Limited소유자만 편집, 로그인 사용자 읽기
Locked소유자만 편집, 누구나 읽기
Protected소유자만 편집, 로그인 사용자 읽기
Private소유자만 접근

6. 버전 관리

  • 자동 리비전 저장
  • 이전 버전으로 복원 가능
  • 변경 이력 추적

7. 다양한 인증 지원

  • 이메일/비밀번호
  • LDAP
  • OAuth2 (Google, GitHub, GitLab 등)
  • SAML
  • Keycloak, Authelia 연동

8. 내보내기 형식

  • Markdown (.md)
  • HTML
  • Raw HTML
  • PDF (브라우저 인쇄)

유사 도구 비교

항목HedgeDocOutlineNotionGoogle Docs
유형마크다운 에디터위키/지식베이스올인원 워크스페이스문서 편집기
실시간 협업✅ 강력
마크다운✅ 네이티브부분 지원
셀프 호스팅
다이어그램✅ Mermaid 등제한적
슬라이드✅ reveal.js별도 앱
오프라인
비용무료무료프리미엄무료/유료
학습 곡선낮음낮음중간매우 낮음

언제 HedgeDoc를 선택할까?

HedgeDoc가 적합한 경우:

  • 마크다운 기반 실시간 협업이 필요할 때
  • 기술 문서, 회의록을 빠르게 작성할 때
  • 다이어그램을 문서에 포함해야 할 때
  • 마크다운 슬라이드 프레젠테이션이 필요할 때
  • 데이터 프라이버시가 중요할 때

다른 도구가 적합한 경우:

  • 구조화된 지식베이스/위키 → Outline, BookStack
  • 데이터베이스, 칸반 보드 등 필요 → Notion
  • 비기술 사용자 대상 → Google Docs
  • 로컬 마크다운 편집 → Obsidian, Typora

Docker Compose 설치

사전 요구사항

  • Docker 및 Docker Compose 설치
  • 최소 512MB RAM
  • PostgreSQL 또는 MySQL/MariaDB

기본 설치 (PostgreSQL)

1. 디렉토리 생성

bash

mkdir -p ~/docker/hedgedoc
cd ~/docker/hedgedoc

2. docker-compose.yml 작성

yaml

services:
  database:
    image: postgres:15-alpine
    container_name: hedgedoc-db
    environment:
      POSTGRES_USER: hedgedoc
      POSTGRES_PASSWORD: your_secure_password
      POSTGRES_DB: hedgedoc
    volumes:
      - ./database:/var/lib/postgresql/data
    restart: unless-stopped

  hedgedoc:
    image: quay.io/hedgedoc/hedgedoc:latest
    container_name: hedgedoc
    environment:
      # 데이터베이스 연결
      CMD_DB_URL: postgres://hedgedoc:your_secure_password@database:5432/hedgedoc
      
      # 도메인 설정 (자신의 도메인 또는 IP로 변경)
      CMD_DOMAIN: hedgedoc.example.com
      CMD_PROTOCOL_USESSL: "true"
      CMD_URL_ADDPORT: "false"
      
      # 사용자 등록 설정
      CMD_ALLOW_EMAIL_REGISTER: "true"
      CMD_ALLOW_ANONYMOUS: "false"
      CMD_ALLOW_ANONYMOUS_EDITS: "true"
      
      # 기본 권한
      CMD_DEFAULT_PERMISSION: limited
      
      # 세션
      CMD_SESSION_SECRET: your_random_session_secret_here
    volumes:
      - ./uploads:/hedgedoc/public/uploads
    ports:
      - "3000:3000"
    depends_on:
      - database
    restart: unless-stopped

3. 환경 변수 설명

변수설명예시
CMD_DB_URLDB 연결 문자열postgres://user:pass@host:5432/db
CMD_DOMAIN서비스 도메인hedgedoc.example.com
CMD_PROTOCOL_USESSLHTTPS 사용 여부true / false
CMD_ALLOW_EMAIL_REGISTER이메일 가입 허용true / false
CMD_ALLOW_ANONYMOUS익명 접근 허용true / false
CMD_DEFAULT_PERMISSION기본 노트 권한freely, editable, limited, locked
CMD_SESSION_SECRET세션 암호화 키랜덤 문자열

4. 컨테이너 실행

bash

docker compose up -d

5. 접속 확인

브라우저에서 http://서버IP:3000 접속


내부 네트워크 전용 설치 (간단 설정)

로컬 네트워크에서만 사용할 경우 간단한 설정:

yaml

services:
  database:
    image: postgres:15-alpine
    container_name: hedgedoc-db
    environment:
      POSTGRES_USER: hedgedoc
      POSTGRES_PASSWORD: hedgedoc123
      POSTGRES_DB: hedgedoc
    volumes:
      - ./database:/var/lib/postgresql/data
    restart: unless-stopped

  hedgedoc:
    image: quay.io/hedgedoc/hedgedoc:latest
    container_name: hedgedoc
    environment:
      CMD_DB_URL: postgres://hedgedoc:hedgedoc123@database:5432/hedgedoc
      CMD_DOMAIN: 192.168.1.100
      CMD_URL_ADDPORT: "true"
      CMD_PORT: "3000"
      CMD_PROTOCOL_USESSL: "false"
      CMD_ALLOW_EMAIL_REGISTER: "true"
      CMD_ALLOW_ANONYMOUS: "false"
    volumes:
      - ./uploads:/hedgedoc/public/uploads
    ports:
      - "3000:3000"
    depends_on:
      - database
    restart: unless-stopped

CMD_DOMAIN을 서버의 실제 IP 주소로 변경하세요.


리버스 프록시 연동 (Traefik)

yaml

services:
  database:
    image: postgres:15-alpine
    container_name: hedgedoc-db
    environment:
      POSTGRES_USER: hedgedoc
      POSTGRES_PASSWORD: secure_password
      POSTGRES_DB: hedgedoc
    volumes:
      - ./database:/var/lib/postgresql/data
    restart: unless-stopped
    networks:
      - hedgedoc-internal

  hedgedoc:
    image: quay.io/hedgedoc/hedgedoc:latest
    container_name: hedgedoc
    environment:
      CMD_DB_URL: postgres://hedgedoc:secure_password@database:5432/hedgedoc
      CMD_DOMAIN: docs.example.com
      CMD_PROTOCOL_USESSL: "true"
      CMD_URL_ADDPORT: "false"
      CMD_ALLOW_EMAIL_REGISTER: "false"
      CMD_ALLOW_ANONYMOUS: "false"
      CMD_SESSION_SECRET: your_session_secret
    volumes:
      - ./uploads:/hedgedoc/public/uploads
    depends_on:
      - database
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.hedgedoc.rule=Host(`docs.example.com`)"
      - "traefik.http.routers.hedgedoc.entrypoints=websecure"
      - "traefik.http.routers.hedgedoc.tls.certresolver=letsencrypt"
      - "traefik.http.services.hedgedoc.loadbalancer.server.port=3000"
    networks:
      - hedgedoc-internal
      - traefik-network

networks:
  hedgedoc-internal:
  traefik-network:
    external: true

Nginx 리버스 프록시 설정

nginx

server {
    listen 80;
    server_name docs.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name docs.example.com;

    ssl_certificate /etc/letsencrypt/live/docs.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/docs.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

⚠️ 중요: WebSocket 지원을 위해 UpgradeConnection 헤더가 필수입니다.


주요 환경 변수

인증 관련

yaml

# 이메일 등록
CMD_ALLOW_EMAIL_REGISTER: "true"

# 익명 접근
CMD_ALLOW_ANONYMOUS: "false"
CMD_ALLOW_ANONYMOUS_EDITS: "false"

# OAuth2 (GitHub 예시)
CMD_GITHUB_CLIENTID: your_client_id
CMD_GITHUB_CLIENTSECRET: your_client_secret

# LDAP
CMD_LDAP_URL: ldap://ldap.example.com
CMD_LDAP_BINDDN: cn=admin,dc=example,dc=com
CMD_LDAP_BINDCREDENTIALS: password
CMD_LDAP_SEARCHBASE: ou=users,dc=example,dc=com

보안 관련

yaml

# 세션 시크릿 (필수)
CMD_SESSION_SECRET: randomly_generated_string

# CSP (Content Security Policy)
CMD_CSP_ENABLE: "true"

# HSTS
CMD_HSTS_ENABLE: "true"

기능 관련

yaml

# 이미지 업로드 크기 제한 (bytes)
CMD_IMAGE_UPLOAD_TYPE: filesystem
CMD_MAX_UPLOAD_SIZE: 10485760

# PDF 내보내기
CMD_ALLOW_PDF_EXPORT: "true"

활용 팁

1. 슬라이드 모드

마크다운 문서를 프레젠테이션으로 변환:

markdown

---
title: 프레젠테이션 제목
---

# 첫 번째 슬라이드

내용...

---

# 두 번째 슬라이드

- 항목 1
- 항목 2

---

# 세 번째 슬라이드
```code
코드 예시
```

URL 끝에 /slide를 추가하면 슬라이드 모드로 전환됩니다.

2. Mermaid 다이어그램

markdown

```mermaid
graph TD
    A[시작] --> B{조건}
    B -->|Yes| C[처리]
    B -->|No| D[종료]
    C --> D
```

3. 수식 (LaTeX)

markdown

인라인 수식: $E = mc^2$

블록 수식:
$$
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$

4. 체크리스트

markdown

- [x] 완료된 항목
- [ ] 미완료 항목
- [ ] 또 다른 항목

5. 노트 템플릿

자주 사용하는 형식을 템플릿으로 저장하고 복사해서 사용:

markdown

# 회의록 템플릿

**일시**: YYYY-MM-DD HH:MM
**참석자**: 

## 안건

1. 

## 논의 내용

## 결정 사항

## Action Items

- [ ] @담당자 - 작업 내용 (기한: )

백업 및 복원

데이터베이스 백업

bash

# PostgreSQL 백업
docker exec hedgedoc-db pg_dump -U hedgedoc hedgedoc > backup_$(date +%Y%m%d).sql

# 복원
docker exec -i hedgedoc-db psql -U hedgedoc hedgedoc < backup_20240101.sql

업로드 파일 백업

bash

# uploads 폴더 백업
tar -czvf uploads_backup_$(date +%Y%m%d).tar.gz ./uploads

전체 백업 스크립트

bash

#!/bin/bash
BACKUP_DIR="/backup/hedgedoc"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# DB 백업
docker exec hedgedoc-db pg_dump -U hedgedoc hedgedoc > $BACKUP_DIR/db_$DATE.sql

# 파일 백업
tar -czvf $BACKUP_DIR/uploads_$DATE.tar.gz ./uploads

# 30일 이상 된 백업 삭제
find $BACKUP_DIR -type f -mtime +30 -delete

echo "Backup completed: $DATE"

트러블슈팅

1. 실시간 협업이 작동하지 않음

WebSocket 연결 문제일 가능성이 높습니다.

bash

# 로그 확인
docker logs hedgedoc

# Nginx 설정에 WebSocket 헤더 확인
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

2. 이미지 업로드 실패

bash

# uploads 폴더 권한 확인
ls -la uploads/

# 권한 수정
chmod -R 755 uploads/
chown -R 1000:1000 uploads/

3. 데이터베이스 연결 오류

bash

# DB 컨테이너 상태 확인
docker ps

# DB 로그 확인
docker logs hedgedoc-db

# 연결 테스트
docker exec -it hedgedoc-db psql -U hedgedoc -d hedgedoc

4. 로그인 후 리다이렉트 오류

CMD_DOMAINCMD_PROTOCOL_USESSL 설정이 실제 접속 URL과 일치하는지 확인:

yaml

# HTTPS로 접속하는 경우
CMD_DOMAIN: docs.example.com
CMD_PROTOCOL_USESSL: "true"
CMD_URL_ADDPORT: "false"

마무리

HedgeDoc는 “마크다운 + 실시간 협업”이라는 조합으로 기술 팀에게 최적화된 문서 협업 도구입니다. Notion이나 Google Docs보다 가볍고, 마크다운에 익숙한 개발자들에게 훨씬 자연스러운 경험을 제공합니다.

추천 대상

  • 마크다운을 선호하는 개발자/기술 팀
  • 실시간 협업 문서가 필요한 팀
  • 회의록, 기술 문서를 빠르게 작성하는 팀
  • 데이터 프라이버시를 중시하는 조직
  • 슬라이드도 마크다운으로 만들고 싶은 분

HedgeDoc의 매력

“Ideas grow better together” – 아이디어는 함께할 때 더 잘 자랍니다.

링크 하나로 협업을 시작하세요!


참고 자료




댓글 남기기