Wiki
웹후크
저장소별 아웃바운드 알림(Discord, Slack, Teams, custom). 체크인, 체크아웃, 활동 요약에 대해 동작. 생성, 메시지 형식, 템플릿 변수, SSRF 가드.
소개
웹후크는 저장소에서 이벤트가 발생할 때마다 외부 서비스(Discord, Slack, Microsoft Teams, 또는 원하는 URL)로 아웃바운드 알림을 보냅니다. 이벤트란 체크인, 체크아웃, 또는 주기적인 활동 요약입니다. 클라이언트를 열지 않고도 팀에 상황을 알리는 가장 간단한 방법이며, 누군가 작업을 제출하면 채널에 메시지가 도착합니다.
웹후크는 데스크톱 클라이언트의 관리 패널 Webhooks 탭에서 저장소별로 구성합니다. 한 저장소에 여러 웹후크를 둘 수 있습니다(예: 팀 전체용으로 Discord에 하나, 리드용으로 비공개 Slack에 하나).
접근 권한과 역할
웹후크 관리는 저장소 관리자에게만 허용됩니다: 임의의 저장소에서의 슈퍼 관리자
(admin 역할), 또는 자신이 관리하는 저장소에서의 project_admin입니다.
다른 역할에는 이 탭이 보이지 않습니다.
웹후크 만들기
- 관리 패널을 열고 저장소를 선택한 다음 Webhooks 탭을 엽니다.
- Add Webhook을 클릭합니다.
- 필드를 입력한 다음 Create를 누릅니다.
| 필드 | 값 |
|---|---|
| Name | 나중에 구분하기 위한 레이블(예: Discord équipe). 필수. |
| URL | 대상 서비스가 제공하는 웹후크 URL. 필수. 거부되는 URL은 보안 참조. |
| Type | discord, slack, teams 또는 custom. |
| Events | checkin, checkout, activity_summary 중 하나 이상. 최소 하나는 필수. |
| Enabled | 활성화 토글(편집 시, 그리고 목록에서 표시). |
Discord 측에서 URL을 얻으려면: 채널 설정 → 연동 → 웹후크 → 새 웹후크 → 웹후크 URL 복사. Slack 측에서는 Slack 앱 설정에서 Incoming Webhook을 만듭니다. Teams 측에서는 채널에서 커넥터 → Incoming Webhook.
튜토리얼: Discord 웹후크
가장 흔한 경우입니다. "URL 얻기" 부분은 Discord 안에서 한 번만 수행합니다.
Discord 측: URL 얻기
- Discord를 열고 서버로 이동합니다. 알림을 받을 텍스트 채널을 선택(또는 생성)합니다. 예:
#uversion. - 채널 이름 위에 마우스를 올리고 톱니바퀴 아이콘("채널 편집")을 클릭합니다.
- 왼쪽 메뉴에서 연동 탭을 엽니다.
- 웹후크를 클릭한 다음 새 웹후크를 클릭합니다. Discord가 이 채널에 연결된 웹후크를 자동으로 생성합니다.
- 생성된 웹후크를 클릭해 엽니다. 이름(예:
uVersion)을 지정하고, 대상 채널이 올바른지 확인합니다. 아바타 이미지는 선택 사항입니다. - 웹후크 URL 복사를 클릭합니다. URL은 다음과 같은 형태입니다:
https://discord.com/api/webhooks/123456789/AbCdEf....
uVersion 측: URL 연결하기
- 데스크톱 클라이언트에서 관리 패널을 열고 저장소를 선택한 다음 Webhooks 탭을 엽니다.
- Add Webhook을 클릭합니다.
- Name: 본인용 레이블(예:
Discord équipe). - URL: Discord에서 복사한 URL을 붙여넣습니다.
- Type:
discord를 선택합니다(메시지를 Discord 임베드로 포맷하기 위해 필수). - Events: 원하는 이벤트를 체크합니다. 예:
checkin. - Create를 클릭합니다.
- 웹후크 행에서 Send test를 클릭합니다: 몇 초 안에 테스트 메시지가 Discord 채널에 나타나야 합니다.
테스트가 HTTP 401 또는 404로 실패하면 URL이 잘못되었거나 Discord 측에서 웹후크가
삭제된 것입니다: URL을 다시 복사하세요. 테스트가 초록색인데도 아무것도 도착하지 않으면, 올바른 채널을 보고
있는지, Discord에서 웹후크가 비활성화되지 않았는지 확인하세요.
유형과 형식
Type은 uVersion이 전송 전에 메시지를 어떻게 포맷하는지를 결정합니다. URL이 가리키는 서비스에 맞는 것을 선택하세요. 그렇지 않으면 메시지가 잘못된 형식으로 도착하거나 서비스 측에서 거부될 수 있습니다.
| Type | 전송되는 형식 |
|---|---|
discord | Discord 임베드(제목, 색상, 필드). |
slack | Slack 페이로드(메시지 블록). |
teams | Microsoft Teams 카드(MessageCard). |
custom | 직접 완전히 정의하는 JSON 본문: 사용자 지정 웹후크 참조. |
이벤트
| 이벤트 | 발생 조건… |
|---|---|
checkin | 사용자가 저장소에 커밋을 제출할 때. |
checkout | 사용자가 하나 이상의 파일을 잠글(체크아웃할) 때. |
activity_summary | 서버 스케줄러가 주기적인 활동 요약을 생성할 때(일간 / 주간). |
채널에 필요한 것만 체크하세요. 대규모 스튜디오에서 checkout은 시끄러울 수 있습니다:
많은 팀이 checkin과 activity_summary만 남깁니다.
사용자 지정 웹후크
custom 유형에서는 두 개의 추가 필드가 나타납니다: Custom Headers (JSON)
와 Custom Template (JSON). 이를 통해 JSON POST를 받는 모든 서비스를 연동할 수 있습니다.
Template
템플릿은 전송되는 JSON 본문입니다. uVersion은 이중 중괄호로 둘러싼 변수를 이벤트의 값으로 치환합니다. 예:
{"text": "{{event_type}} par {{username}} dans {{repository}}"}
사용 가능한 변수:
| 변수 | 내용 |
|---|---|
{{event_type}} | 이벤트 유형(checkin, checkout, activity_summary). |
{{repository}} | 저장소 이름. |
{{username}} | 이벤트를 일으킨 사용자. |
{{message}} | 커밋 메시지(체크인의 경우). |
{{file_count}} | 관련된 파일 수. |
{{commit_hash}} | 커밋 해시. |
{{timestamp}} | 이벤트 타임스탬프. |
Headers
요청에 첨부할 HTTP 헤더의 JSON 객체입니다. 예를 들어 인증 토큰:
{"Authorization": "Bearer VOTRE_JETON"}
기본값은 {}(헤더 없음)입니다. 전송용으로 예약된 헤더
(host, content-length, transfer-encoding, connection)
는 자동으로 제거되며 재정의할 수 없습니다.
테스트, 활성화, 삭제
목록의 각 웹후크에서는 다음 작업을 할 수 있습니다:
- Send test(비행기 아이콘): 서비스에 테스트 알림을 보내고 인라인으로 결과(초록색 체크 또는 X)를 표시합니다. 의존하기 전에 URL과 유형을 확인하는 데 유용합니다.
- 토글: 웹후크를 삭제하지 않고 활성화 / 비활성화합니다.
- Edit: 아무 필드나 수정합니다.
- Delete: 영구 삭제(확인 필요).
보안: SSRF 가드
웹후크는 HTTP 요청을 서버가 발생시키게 합니다. 악의적인 URL이 서버의 내부 네트워크를 탐색(SSRF 공격)하는 데 사용되는 것을 막기 위해, uVersion은 생성 시, 수정 시, 그리고 테스트 시에 엄격한 가드를 적용합니다:
- 스킴은
http또는https여야 합니다. 그 외의 스킴은 거부됩니다. - 호스트 이름은 DNS로 해석되며, 얻어진 모든 IP 주소가 검사됩니다. 그중 하나라도
비공개 주소를 가리키면 웹후크는 거부됩니다: 루프백, 사설 네트워크(RFC1918), 링크로컬,
브로드캐스트, CGNAT 범위
100.64.0.0/10, 클라우드 메타데이터169.254.169.254, ULA / IPv6 링크로컬, 그리고 이들의 IPv4-mapped-IPv6 등가물. - HTTP 리다이렉트는 따라가지 않습니다(따라서 내부 호스트로의 307은 가드를 우회할 수 없습니다).
- 업스트림 응답 본문은 클라이언트에 절대 반환되지 않습니다(SSRF 오라클 없음).
실제로는: 웹후크 URL은 공개 서비스(Discord, Slack, Teams, 또는
인터넷에서 도달 가능한 자체 엔드포인트)를 가리켜야 합니다. localhost, 사설 IP
(10.x, 192.168.x, 172.16-31.x) 또는 내부 서비스로의 URL은
"Webhook URL refused: …" 메시지와 함께 거부됩니다.
흔한 함정
유형이 서비스와 일치하지 않음
Discord 형식을 Slack URL로(또는 그 반대로) 보내면 형식이 깨진 메시지가 되거나 서비스 측에서 거부됩니다. Type 필드는 URL과 일치해야 합니다. 확신이 서지 않으면 Send test를 실행하세요.
이벤트가 하나도 체크되지 않음
이벤트가 없는 웹후크는 절대 발생하지 않습니다. 이벤트가 하나도 선택되지 않는 한 클라이언트는 저장을 차단합니다("At least one event is required").
내부 URL 거부됨
자신의 머신이나 LAN에 있는 서비스에 대해 테스트하면 SSRF 가드가 거부합니다. 웹후크 대상으로 사용하려면 그 서비스를 공개 URL(또는 터널)로 노출하세요.
잊혀진 비활성화 웹후크
비활성화된 웹후크는 목록에 남지만 아무것도 보내지 않습니다. 알림이 조용해졌다면 URL을 의심하기 전에 먼저 활성화 토글을 확인하세요.