Taiga: 애자일 팀을 위한 오픈소스 프로젝트 관리 도구 Docker 설치 가이드




개요

Taiga는 스타트업, 소프트웨어 개발자, 디자이너를 위한 무료 오픈소스 프로젝트 관리 시스템입니다. Scrum과 Kanban 방법론을 모두 지원하며, 직관적이고 아름다운 인터페이스로 2015년 “가장 가치 있는 애자일 도구” 상을 수상했습니다. 400K+ SaaS 사용자와 200만+ Docker pulls를 기록한 검증된 플랫폼입니다.

Taiga의 핵심 철학

Taiga는 “단순함과 유연함”을 핵심 가치로, 복잡한 설정 없이도 팀이 애자일 방법론을 쉽게 적용할 수 있도록 설계되었습니다. 20개 이상의 언어를 지원하여 글로벌 팀에서도 활용할 수 있습니다.

주요 특징

기능설명
Scrum 지원백로그, 스프린트, 스프린트 태스크보드, 번다운 차트
Kanban 보드WIP 제한, 커스텀 워크플로우
Epics대규모 기능을 작은 유저 스토리로 분할
이슈 추적버그/이슈 유형, 우선순위, 심각도 커스터마이징
위키프로젝트 문서화
실시간 협업타임라인, 알림, 멘션
역할 기반 권한세밀한 접근 제어
비디오 회의 연동Jitsi, Talky.io, Whereby 통합
채팅 연동Slack 통합
다국어20+ 언어 지원

Scrum vs Kanban 기능 비교

기능Scrum 모드Kanban 모드
백로그 관리
스프린트 계획
번다운 차트
스토리 포인트
WIP 제한
연속 흐름
칸반 보드
이슈 추적

프로젝트 관리 도구 비교

기능TaigaJiraPlaneTrello
오픈소스
셀프호스팅제한적
Scrum 완전 지원
Kanban WIP 제한
번다운 차트
스토리 포인트
직관적 UI
학습 곡선낮음높음낮음매우 낮음

시스템 요구 사항

항목최소 사양권장 사양
RAM2GB4GB 이상
CPU2 코어4 코어 이상
저장소10GB30GB 이상
Docker20.10+최신 버전
Docker Compose2.0+최신 버전

Docker Compose 설치

기본 설치

1) 디렉토리 및 환경 변수 설정

mkdir -p ~/taiga && cd ~/taiga

.env 파일 생성:

# 도메인 설정
TAIGA_SITES_DOMAIN=taiga.yourdomain.com
TAIGA_SITES_SCHEME=https
TAIGA_SUBPATH=""

# Secret Key (반드시 변경!)
TAIGA_SECRET_KEY=your-super-secret-key-change-this-to-random-string

# PostgreSQL 설정
POSTGRES_DB=taiga
POSTGRES_USER=taiga
POSTGRES_PASSWORD=your_secure_db_password
POSTGRES_HOST=taiga-db

# RabbitMQ 설정
RABBITMQ_USER=taiga
RABBITMQ_PASS=your_rabbitmq_password
RABBITMQ_VHOST=taiga
RABBITMQ_ERLANG_COOKIE=your-erlang-cookie

# 이메일 설정 (선택사항)
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_USE_TLS=True
EMAIL_HOST_USER=your-email@example.com
EMAIL_HOST_PASSWORD=your-email-password
DEFAULT_FROM_EMAIL=taiga@example.com

# 사용자 등록
PUBLIC_REGISTER_ENABLED=false

2) docker-compose.yml

version: "3.8"

services:
  taiga-db:
    image: postgres:13-alpine
    container_name: taiga-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - taiga-db-data:/var/lib/postgresql/data
    networks:
      - taiga-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5

  taiga-rabbitmq:
    image: rabbitmq:3-management-alpine
    container_name: taiga-rabbitmq
    restart: unless-stopped
    environment:
      RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE}
      RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER}
      RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS}
      RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST}
    volumes:
      - taiga-rabbitmq-data:/var/lib/rabbitmq
    networks:
      - taiga-network
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "check_running"]
      interval: 10s
      timeout: 5s
      retries: 5

  taiga-back:
    image: taigaio/taiga-back:latest
    container_name: taiga-back
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_HOST: ${POSTGRES_HOST}
      TAIGA_SECRET_KEY: ${TAIGA_SECRET_KEY}
      TAIGA_SITES_SCHEME: ${TAIGA_SITES_SCHEME}
      TAIGA_SITES_DOMAIN: ${TAIGA_SITES_DOMAIN}
      TAIGA_SUBPATH: ${TAIGA_SUBPATH}
      RABBITMQ_USER: ${RABBITMQ_USER}
      RABBITMQ_PASS: ${RABBITMQ_PASS}
      EMAIL_BACKEND: ${EMAIL_BACKEND}
      EMAIL_HOST: ${EMAIL_HOST}
      EMAIL_PORT: ${EMAIL_PORT}
      EMAIL_USE_TLS: ${EMAIL_USE_TLS}
      EMAIL_HOST_USER: ${EMAIL_HOST_USER}
      EMAIL_HOST_PASSWORD: ${EMAIL_HOST_PASSWORD}
      DEFAULT_FROM_EMAIL: ${DEFAULT_FROM_EMAIL}
      PUBLIC_REGISTER_ENABLED: ${PUBLIC_REGISTER_ENABLED}
    volumes:
      - taiga-static-data:/taiga-back/static
      - taiga-media-data:/taiga-back/media
    networks:
      - taiga-network
    depends_on:
      taiga-db:
        condition: service_healthy
      taiga-rabbitmq:
        condition: service_healthy

  taiga-async:
    image: taigaio/taiga-back:latest
    container_name: taiga-async
    restart: unless-stopped
    entrypoint: ["/taiga-back/docker/async_entrypoint.sh"]
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_HOST: ${POSTGRES_HOST}
      TAIGA_SECRET_KEY: ${TAIGA_SECRET_KEY}
      TAIGA_SITES_SCHEME: ${TAIGA_SITES_SCHEME}
      TAIGA_SITES_DOMAIN: ${TAIGA_SITES_DOMAIN}
      RABBITMQ_USER: ${RABBITMQ_USER}
      RABBITMQ_PASS: ${RABBITMQ_PASS}
    volumes:
      - taiga-static-data:/taiga-back/static
      - taiga-media-data:/taiga-back/media
    networks:
      - taiga-network
    depends_on:
      - taiga-back

  taiga-front:
    image: taigaio/taiga-front:latest
    container_name: taiga-front
    restart: unless-stopped
    environment:
      TAIGA_URL: "${TAIGA_SITES_SCHEME}://${TAIGA_SITES_DOMAIN}"
      TAIGA_WEBSOCKETS_URL: "wss://${TAIGA_SITES_DOMAIN}"
      PUBLIC_REGISTER_ENABLED: ${PUBLIC_REGISTER_ENABLED}
    networks:
      - taiga-network

  taiga-events:
    image: taigaio/taiga-events:latest
    container_name: taiga-events
    restart: unless-stopped
    environment:
      RABBITMQ_USER: ${RABBITMQ_USER}
      RABBITMQ_PASS: ${RABBITMQ_PASS}
      TAIGA_SECRET_KEY: ${TAIGA_SECRET_KEY}
    networks:
      - taiga-network
    depends_on:
      - taiga-rabbitmq

  taiga-protected:
    image: taigaio/taiga-protected:latest
    container_name: taiga-protected
    restart: unless-stopped
    environment:
      MAX_AGE: 360
      SECRET_KEY: ${TAIGA_SECRET_KEY}
    networks:
      - taiga-network

  taiga-gateway:
    image: nginx:alpine
    container_name: taiga-gateway
    restart: unless-stopped
    ports:
      - "9000:80"
    volumes:
      - ./taiga.conf:/etc/nginx/conf.d/default.conf:ro
      - taiga-static-data:/taiga/static:ro
      - taiga-media-data:/taiga/media:ro
    networks:
      - taiga-network
    depends_on:
      - taiga-front
      - taiga-back
      - taiga-events

volumes:
  taiga-db-data:
  taiga-rabbitmq-data:
  taiga-static-data:
  taiga-media-data:

networks:
  taiga-network:
    driver: bridge

3) Nginx 설정 파일 (taiga.conf)

server {
    listen 80;
    server_name _;
    
    large_client_header_buffers 4 32k;
    client_max_body_size 50M;
    charset utf-8;

    # Frontend
    location / {
        proxy_pass http://taiga-front/;
        proxy_set_header Host $http_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;
    }

    # API
    location /api {
        proxy_pass http://taiga-back:8000/api;
        proxy_set_header Host $http_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;
    }

    # Admin
    location /admin {
        proxy_pass http://taiga-back:8000/admin;
        proxy_set_header Host $http_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;
    }

    # Static files
    location /static {
        alias /taiga/static;
    }

    # Media files
    location /_protected {
        internal;
        alias /taiga/media;
        add_header Content-disposition "attachment";
    }

    location /media {
        proxy_pass http://taiga-protected:8003/;
        proxy_set_header Host $http_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;
    }

    # Events (WebSocket)
    location /events {
        proxy_pass http://taiga-events:8888/events;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;
    }
}

4) 실행

docker-compose up -d

# 로그 확인
docker-compose logs -f

# 상태 확인
docker-compose ps

Traefik 리버스 프록시 설정

services:
  taiga-gateway:
    image: nginx:alpine
    container_name: taiga-gateway
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.taiga.rule=Host(`taiga.yourdomain.com`)"
      - "traefik.http.routers.taiga.entrypoints=websecure"
      - "traefik.http.routers.taiga.tls.certresolver=myresolver"
      - "traefik.http.services.taiga.loadbalancer.server.port=80"
    networks:
      - taiga-network
      - traefik-network

초기 설정

1) 관리자 계정 생성

# 슈퍼유저 생성
docker-compose exec taiga-back python manage.py createsuperuser

2) 샘플 데이터 로드 (선택사항)

docker-compose exec taiga-back python manage.py sample_data

3) 웹 접속

브라우저에서 http://localhost:9000 또는 설정한 도메인으로 접속합니다.

주요 기능 활용

Scrum 프로젝트 설정

  1. 프로젝트 생성 시 Scrum 템플릿 선택
  2. 백로그 관리: 유저 스토리 작성 및 우선순위 지정
  3. 스프린트 계획: 스토리를 스프린트에 할당
  4. 태스크보드: 스프린트 진행 상황 추적
  5. 번다운 차트: 스프린트 진행률 시각화

Kanban 프로젝트 설정

  1. 프로젝트 생성 시 Kanban 템플릿 선택
  2. 컬럼 커스터마이징: 워크플로우에 맞게 상태 정의
  3. WIP 제한 설정: 각 컬럼의 최대 작업 수 제한
  4. 카드 관리: 드래그 앤 드롭으로 상태 변경

역할 및 권한

역할권한
Product Owner백로그 관리, 우선순위 결정
Scrum Master스프린트 관리, 팀 조율
Developer태스크 수행, 상태 업데이트
Stakeholder읽기 전용 접근

통합 설정

Slack 연동

  1. Slack에서 Incoming Webhook URL 생성
  2. Taiga 프로젝트 설정 > Integrations > Slack
  3. Webhook URL 입력 및 알림 이벤트 선택

GitHub/GitLab 연동

# GitHub 연동 환경 변수 추가
GITHUB_API_CLIENT_ID=your-client-id
GITHUB_API_CLIENT_SECRET=your-client-secret

비디오 회의 연동

Taiga는 Jitsi, Talky.io, Whereby와 연동하여 화상 회의를 지원합니다.

트러블슈팅

데이터베이스 연결 실패

# DB 컨테이너 상태 확인
docker-compose logs taiga-db

# 연결 테스트
docker-compose exec taiga-db psql -U taiga -d taiga -c "SELECT 1"

정적 파일 404 오류

# 정적 파일 수집
docker-compose exec taiga-back python manage.py collectstatic --noinput

WebSocket 연결 실패

  • Nginx 설정에서 WebSocket 업그레이드 헤더 확인
  • 리버스 프록시 사용 시 WebSocket 지원 설정 필요

느린 성능

# 데이터베이스 최적화
docker-compose exec taiga-db psql -U taiga -d taiga -c "VACUUM ANALYZE;"

백업 및 복원

데이터베이스 백업

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

# 복원
cat taiga_backup.sql | docker-compose exec -T taiga-db psql -U taiga taiga

미디어 파일 백업

# 미디어 볼륨 백업
docker run --rm -v taiga_taiga-media-data:/data -v $(pwd):/backup alpine tar czf /backup/taiga_media_$(date +%Y%m%d).tar.gz /data

전체 백업 스크립트

#!/bin/bash
BACKUP_DIR="/backups/taiga/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# 데이터베이스
docker-compose exec -T taiga-db pg_dump -U taiga taiga > $BACKUP_DIR/database.sql

# 미디어 파일
docker run --rm -v taiga_taiga-media-data:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/media.tar.gz /data

# 정적 파일
docker run --rm -v taiga_taiga-static-data:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/static.tar.gz /data

echo "Backup completed: $BACKUP_DIR"

업그레이드

# 이미지 업데이트
docker-compose pull

# 재시작
docker-compose down
docker-compose up -d

# 마이그레이션
docker-compose exec taiga-back python manage.py migrate



댓글 남기기