자체 호스팅 (온프레미스) GitLab과 외부 서비스 (Slack, Notion 등) 간의 연동 서비스
참고: 이 프로젝트는 자체 호스팅 GitLab 서버 (사내 인프라에 설치된 GitLab CE/EE)를 위한 것입니다. GitLab.com (SaaS)이 아닌, 내부 GitLab 인스턴스를 외부 협업 도구와 연결합니다.
- Slack → GitLab:
/issue커맨드로 이슈 생성 - GitLab → Slack: 이슈 상태 변경 알림
- 상태 조회:
/issue status #123으로 이슈 상태 확인
- Notion 연동
내부 네트워크 외부 서비스
┌───────────────────────┐ ┌───────────────────┐
│ │ │ │
│ ┌─────────────────┐ │ Webhook/API │ ┌─────────────┐ │
│ │ GitLab 서버 │◄─┼───────────────────┼──│ Slack │ │
│ │ (자체 호스팅) │ │ │ │ │ │
│ └────────┬────────┘ │ │ └──────┬──────┘ │
│ │ │ │ │ │
│ │ Webhook │ │ Slash │ │
│ ▼ │ │ Command │ │
│ ┌─────────────────┐ │ 터널/프록시 │ │ │
│ │ Integration │◄─┼───────────────────┼─────────┘ │
│ │ Server │──┼───────────────────┼──────────────────►│
│ │ (FastAPI) │ │ (Cloudflare, │ │
│ └─────────────────┘ │ Tailscale 등) │ │
│ │ │ │
└───────────────────────┘ └───────────────────┘
핵심 포인트:
- GitLab 서버는 내부 네트워크에서 실행 (인터넷에서 직접 접근 불가)
- Integration 서버가 내부 GitLab과 외부 서비스를 연결하는 다리 역할
- 터널 (Cloudflare Tunnel, Tailscale 등) 또는 리버스 프록시를 통해 외부 접근
- 내부 서버에서 흔히 사용하는 자체 서명 SSL 인증서 지원
- Python 3.10+
- uv (패키지 관리자)
# 저장소 클론
git clone <repository-url>
cd gitlab-integrations
# 환경 설정 (가상환경 생성 + 패키지 설치 + .env 파일 생성)
./scripts/setup.sh
# .env 파일 편집
vi .env- Slack API 페이지 접속
- Create New App 클릭
- From scratch 선택
- App 이름 입력 (예:
GitLab Issue Bot) - 워크스페이스 선택 후 Create App
- 좌측 메뉴에서 OAuth & Permissions 클릭
- Scopes 섹션에서 Bot Token Scopes에 다음 권한 추가:
| Scope | 용도 |
|---|---|
chat:write |
채널에 메시지 전송 |
chat:write.public |
봇이 참여하지 않은 public 채널에 메시지 전송 |
commands |
Slash 커맨드 사용 |
- 좌측 메뉴에서 Slash Commands 클릭
- Create New Command 클릭
- 다음 정보 입력:
| 필드 | 값 |
|---|---|
| Command | /issue |
| Request URL | https://<your-domain>/slack/commands |
| Short Description | GitLab 이슈 생성 및 조회 |
| Usage Hint | [status #번호] |
- Save 클릭
⚠️ 주의: Request URL은 Integration Server의 외부 접근 가능한 URL입니다. GitLab 서버 URL이 아닙니다!예시:
- ✅
https://your-app.company.com/slack/commands- ❌
https://gitlab.company.com/slack/commands
⚠️ 이 설정을 하지 않으면 Modal에서 "연결하는 데 문제가 발생했습니다" 에러가 발생합니다.
- 좌측 메뉴에서 Interactivity & Shortcuts 클릭
- Interactivity 토글을 On으로 변경
- Request URL 입력:
https://<your-domain>/slack/interactions - Save Changes 클릭
⚠️ 주의: Step 3과 마찬가지로 Integration Server의 외부 URL을 입력합니다. Shortcuts, Select Menus 설정은 필요 없습니다.
- 좌측 메뉴에서 OAuth & Permissions 클릭
- Install to Workspace 클릭
- 권한 요청 확인 후 허용
- 생성된 Bot User OAuth Token 복사 (
xoxb-로 시작)
- 좌측 메뉴에서 Basic Information 클릭
- App Credentials 섹션에서 Signing Secret 복사
- Slack에서 알림 받을 채널 우클릭
- 채널 세부정보 보기 클릭
- 하단의 채널 ID 복사 (
C로 시작하는 문자열)
- GitLab 접속 → 우측 상단 프로필 아이콘 → Preferences
- 좌측 메뉴에서 Access Tokens 클릭
- Add new token 클릭
- 다음 정보 입력:
| 필드 | 값 |
|---|---|
| Token name | gitlab-integrations |
| Expiration date | 적절한 만료일 선택 |
| Scopes | api (전체 API 접근) |
- Create personal access token 클릭
- 생성된 토큰 복사 (이 화면을 벗어나면 다시 볼 수 없음)
- 연동할 GitLab 프로젝트 페이지 접속
- 프로젝트 이름 아래에 Project ID 표시됨
- 또는 Settings → General에서 확인
- GitLab 프로젝트 → Settings → Webhooks
- Add new webhook 클릭
- 다음 정보 입력:
| 필드 | 값 |
|---|---|
| URL | https://<your-domain>/gitlab/webhook |
| Secret token | .env의 GITLAB_WEBHOOK_SECRET과 동일한 값 |
| Trigger | ✅ Issues events |
| SSL verification | 환경에 맞게 선택 |
- Add webhook 클릭
Secret token 생성 방법
# 방법 1: openssl 사용 openssl rand -hex 32 # 방법 2: Python 사용 python -c "import secrets; print(secrets.token_hex(32))"
.env 파일을 열고 다음 값들을 입력:
# GitLab 설정
GITLAB_URL=https://gitlab.your-company.com # GitLab 서버 주소
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx # Personal Access Token
GITLAB_PROJECT_ID=123 # 프로젝트 ID
GITLAB_WEBHOOK_SECRET=your-secret-token # Webhook 검증용 (GitLab Webhook 설정과 동일하게)
# Slack 설정
SLACK_BOT_TOKEN=xoxb-xxxx-xxxx-xxxx # Bot User OAuth Token
SLACK_SIGNING_SECRET=xxxxxxxxxxxxxxxxxxxxxxx # Signing Secret
SLACK_CHANNEL_ID=C0123456789 # 알림 채널 ID
# 서버 설정
HOST=0.0.0.0
PORT=8000# 기본 실행 (.env의 HOST, PORT 사용)
./scripts/run.sh
# 다른 포트로 실행
./scripts/run.sh --port 9000
# 호스트와 포트 지정
./scripts/run.sh --host 0.0.0.0 --port 9000source .venv/bin/activate
python -m gitlab_integrations.main --port 9000docker-compose up -d
# 로그 확인
docker-compose logs -fSlack에서 /issue 입력 → 모달 팝업에서 정보 입력 → 생성하기
/issue
모달 필드:
- Title: 이슈 제목 (필수)
- Description: 상세 설명 (선택)
- Labels: GitLab 기존 라벨에서 선택 (선택, 다중 선택 가능)
참고: 라벨 목록은 GitLab 프로젝트에서 동적으로 불러옵니다. 기존에 생성된 라벨만 드롭다운에 표시됩니다.
/issue status 123
/issue status #123
원인: Slack이 Integration Server에 요청을 보내지 못함
확인 사항:
-
Slash Commands의 Request URL 확인
- Slack API Dashboard → Slash Commands →
/issue선택 - Request URL이
https://<your-domain>/slack/commands로 설정되어 있는지 확인 ⚠️ GitLab URL이 아닌 Integration Server URL이어야 함
- Slack API Dashboard → Slash Commands →
-
서버 실행 여부 확인
curl https://<your-domain>/health # {"status": "healthy"} 응답 확인
-
서버 로그 확인
- 요청이 오지 않으면: URL 설정 문제
- 401 에러: Signing Secret 불일치
- 502 에러: 서버 미실행
원인: Interactivity 설정 누락
해결:
- Slack API Dashboard → Interactivity & Shortcuts
- Interactivity 토글이 On인지 확인
- Request URL이
https://<your-domain>/slack/interactions로 설정되어 있는지 확인 - Save Changes 클릭
원인: Webhook URL이 잘못 설정됨 (GitLab 서버 자체를 가리킴)
확인:
❌ https://gitlab.company.com/gitlab/webhook (GitLab URL)
✅ https://your-app.domain.com/gitlab/webhook (Integration Server URL)
✅ http://localhost:9000/gitlab/webhook (같은 서버인 경우)
원인: Integration Server가 실행 중이 아님
해결:
# 서버 실행
source .venv/bin/activate
python -m gitlab_integrations.main --port 9000원인: GitLab 서버가 self-signed 인증서 사용
해결: 이미 코드에서 ssl_verify=False로 처리됨. GitLab Webhook 설정에서도 Enable SSL verification 체크 해제
증상: 이슈 생성 시 SSL 에러 발생
SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate'))
원인: GitLab 서버가 self-signed 인증서 사용
해결: src/gitlab_integrations/gitlab/api.py에서 ssl_verify=False 확인
gl = gitlab.Gitlab(
settings.gitlab_url,
private_token=settings.gitlab_token,
ssl_verify=False, # self-signed 인증서 허용
)GITLAB_TOKEN이 유효한지 확인- 토큰에
apiscope가 있는지 확인 GITLAB_URL이 올바른지 확인 (끝에/없이)
해결:
sudo apt install python3.10-venv원인: Python 버전 호환성
해결: 이미 pyproject.toml에서 requires-python = ">=3.10"으로 설정됨
혼동하기 쉬운 URL 설정을 정리합니다:
| 설정 위치 | URL 종류 | 예시 |
|---|---|---|
.env의 GITLAB_URL |
GitLab 서버 주소 | https://gitlab.company.com |
| GitLab Webhook URL | Integration Server 주소 | http://localhost:9000/gitlab/webhook |
| Slack Slash Commands | Integration Server 주소 (외부) | https://your-app.domain.com/slack/commands |
| Slack Interactivity | Integration Server 주소 (외부) | https://your-app.domain.com/slack/interactions |
핵심:
.env의GITLAB_URL만 GitLab 서버 주소- 나머지는 모두 Integration Server 주소
./scripts/test.sh
./scripts/test.sh --cov # 커버리지 포함ruff check --fix .
ruff format .