개요
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
| 항목 | HackMD | HedgeDoc |
|---|---|---|
| 호스팅 | 클라우드 서비스 | 셀프 호스팅 |
| 비용 | 무료/유료 플랜 | 완전 무료 |
| 데이터 소유 | 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 (브라우저 인쇄)
유사 도구 비교
| 항목 | HedgeDoc | Outline | Notion | Google 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_URL | DB 연결 문자열 | postgres://user:pass@host:5432/db |
CMD_DOMAIN | 서비스 도메인 | hedgedoc.example.com |
CMD_PROTOCOL_USESSL | HTTPS 사용 여부 | 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 지원을 위해
Upgrade와Connection헤더가 필수입니다.
주요 환경 변수
인증 관련
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_DOMAIN과 CMD_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” – 아이디어는 함께할 때 더 잘 자랍니다.
링크 하나로 협업을 시작하세요!