어바웃피싱 · 플랫폼개발팀 요청
구글챗 빌드봇 전체 채널에 오는 Cloud Build 알림이 지금은 어느 환경 빌드인지 카드를 열어야 알 수 있다. 알림 카드에 환경을 앞세워 표시하고, 실패도 빠짐없이 오게 만드는 작업이다. 아래 순서대로만 하면 된다. 중간에 판단이 필요한 것은 8번에 따로 모아 뒀다. 거기 있는 것은 정하지 말고 물어봐 주면 된다.
지금 알림은 첫 줄이 전부 ✅ Build Succeeded 라서 채팅 목록에서 전부 똑같이 보인다. 환경을 알려면 카드를 열고 트리거 이름을 읽어야 하는데, 이름 규칙이 저장소마다 다르다. platform 저장소는 운영을 release 라고 부르고 booking 저장소는 prod 라고 부른다.
여기에 더해, 채널에서 확인한 최근 알림 16건이 전부 성공이라 빌드가 실패했을 때 알림이 오는지 자체가 확인되지 않았다. 안 온다면 지금 우리는 빌드 실패를 못 보고 있는 것이다.
이 작업이 끝나면 채팅 목록만 훑어도 운영에 나간 빌드와 개발 빌드가 갈리고, 실패가 눈에 띈다. 배포 공지 채널(전사_배포공지)의 자동화도 이 구분 위에 올린다.
오늘은 론칭 컷오버 날이다. 운영(prod·release) 트리거는 오늘 건드리지 않는다. 아래 2단계까지만 오늘 하고, 3단계부터는 9/10 이후에 한다. 순서를 그렇게 짜 뒀다.
구글챗 빌드봇 전체 채널(spaces/AAAAXL2bfc8)에서 직접 읽어 확인한 내용이다. 알림을 보내는 것은 Cloud Build Alert 라는 이름의 앱이고, 카드 형태로 온다.
| 트리거 | 저장소 | 빌드 기준 | 환경(확인 필요) |
|---|---|---|---|
| platform-svc-release-build | aboutfishing-platform | 태그 (v0.2.x) | prod |
| platform-map-release-build | aboutfishing-platform | 태그 | prod |
| platform-booking-release-build | aboutfishing-platform | 태그 | prod |
| platform-test-build | aboutfishing-platform | main 브랜치 | dev 또는 test |
| platform-dev-build | aboutfishing-platform | main 브랜치 | dev |
| booking-api-prod-build | aboutfishing-booking-api | 태그 (v2.54.0) | prod |
| booking-api-stg-build | aboutfishing-booking-api | main 브랜치 | stage |
| booking-partners-stg-build | aboutfishing-booking-partners | main 브랜치 | stage |
| booking-partners-test-build | aboutfishing-booking-partners | main 브랜치 | dev 또는 test |
회색이 운영으로 보이는 것들이다. 이 표의 환경 값은 이름으로 추정한 것이라 1단계에서 실제 배포 대상을 보고 확정해야 한다. 목록에 없는 트리거가 더 있으면 같이 처리한다.
✅ Build Succeeded Project: aboutfishingproduct / Trigger: booking-api-prod-build Repository: aboutfishing-booking-api Branch: N/A Tag: v2.54.0 Build ID: edc45d6d-6cf8-4404-910e-1cd002f62686 Finished: 2026. 9. 9. AM 11:52:56 [ View Build Logs ]
고칠 점 · 첫 줄에 환경이 없다 / Project 는 하나뿐이라 매번 같은 값이다 / 태그 빌드인데 Branch: N/A 가 뜬다 / Build ID 36자는 아무도 안 읽는다 / 소요 시간이 없다 / 실패했을 때 어디서 깨졌는지가 없다.
0단계부터 5단계까지가 필수, 6·7단계는 선택이다. 각 단계마다 끝난 걸 아는 법을 적어 뒀다.
gcloud config set project aboutfishingproduct gcloud config set account hiseo@aboutfishing.kr
Cloud Build 는 빌드 상태가 바뀔 때마다 cloud-builds 라는 Pub/Sub 토픽에 메시지를 넣는다. 그걸 누가 받아서 챗으로 보내고 있는지 찾는다.
gcloud pubsub topics list-subscriptions cloud-builds gcloud pubsub subscriptions describe [위에서 나온 구독 이름] gcloud run services list gcloud functions list
구독의 pushEndpoint 에 적힌 주소가 카드를 만드는 곳이다. 둘 중 하나일 것이다.
끝난 걸 아는 법 · 카드 문구 Build Succeeded 를 검색해서 그 문자열이 있는 파일이나 코드를 찾았으면 된다.
같이 확인할 것 · 그 코드나 설정이 성공만 걸러서 보내고 있는지. status == 'SUCCESS' 같은 조건이 있으면 지금 실패 알림이 안 오고 있다는 뜻이다. 4단계에서 고친다.
이름이 아니라 빌드 구성 파일을 보고 정한다. 배포 대상(Cloud Run 서비스 이름, 네임스페이스, 버킷 등)이 운영인지 스테이지인지 개발인지 확인한다.
gcloud builds triggers list --format="table(name,filename,github.push.tag,github.push.branch)"
현황 표의 9개 각각에 prod / stage / dev 중 하나를 확정한다. test 와 dev 를 굳이 나눌 필요가 없으면 둘 다 dev 로 묶는다. 표시는 세 가지만 쓴다.
끝난 걸 아는 법 · 트리거 9개(또는 그 이상) 전부에 세 값 중 하나가 붙었고, 애매한 게 하나도 안 남았으면 된다.
Cloud Build 는 트리거에 정의했는데 빌드 구성 파일에서 안 쓰는 대체 변수가 있으면 빌드를 실패시킨다. 그래서 _ENV 를 넣기만 하고 cloudbuild.yaml 을 안 고치면 그 트리거의 빌드가 깨진다. 운영 트리거에서 이걸 처음 겪으면 안 되니까 dev 하나로 먼저 확인한다.
피하는 방법은 둘 중 하나다. ① 해당 저장소 cloudbuild.yaml 에 아래를 넣는다. ② 트리거 수정 화면의 대체 변수 영역에 있는 느슨한 적용 옵션을 켠다.
options: substitution_option: ALLOW_LOOSE
platform-dev-build 하나에만 변수를 넣고 빌드를 돌려 본다.
gcloud builds triggers export --trigger=platform-dev-build --destination=platform-dev-build.yaml # 파일을 열어 아래 두 줄을 substitutions 아래에 추가한다 # _ENV: dev # _SVC: 플랫폼 gcloud builds triggers import --source=platform-dev-build.yaml gcloud builds triggers run platform-dev-build --branch=main
끝난 걸 아는 법 · 빌드가 성공하고(실패하면 위 ALLOW_LOOSE 를 안 넣은 것이다) 채널에 평소대로 알림이 온다. 이 시점에는 카드 모양이 아직 그대로여도 정상이다.
잘못되면 · 그 트리거의 빌드만 실패한다. 운영에는 영향이 없다. 되돌리는 법은 아래 5번에 있다.
2단계가 확인되면 나머지에도 넣는다. 저장소별로 cloudbuild.yaml 의 ALLOW_LOOSE 를 먼저 반영한 뒤에 트리거를 고친다.
| 트리거 | _ENV | _SVC (카드에 표시될 이름) |
|---|---|---|
| platform-svc-release-build | prod | 플랫폼 공통 |
| platform-map-release-build | prod | 지도 |
| platform-booking-release-build | prod | 예약 |
| platform-test-build | dev | 플랫폼 |
| platform-dev-build | dev | 플랫폼 |
| booking-api-prod-build | prod | 예약 API |
| booking-api-stg-build | stage | 예약 API |
| booking-partners-stg-build | stage | 선주 |
| booking-partners-test-build | dev | 선주 |
_SVC 의 한글 이름은 예시다. 1단계에서 확인한 실제 서비스에 맞게 바꿔도 된다. 카드에 그대로 찍히는 값이라 개발을 모르는 사람이 읽을 이름으로 쓴다.
끝난 걸 아는 법 · 아래 명령으로 전부 값이 찍히는지 본다. 빈 것이 있으면 안 된다.
gcloud builds triggers list --format="table(name, substitutions._ENV, substitutions._SVC)"
운영 트리거는 태그를 밀어야 돌기 때문에 바로 확인이 어렵다. 값이 들어간 것만 위 명령으로 보고, 실제 카드는 다음 릴리즈 때 확인한다.
0단계에서 찾은 곳을 고친다. 새 카드 규격은 아래 새 카드 규격 에 필드 대응표와 JSON 예시로 적어 뒀다. 두 가지를 같이 한다.
끝난 걸 아는 법 · 실패 카드를 실제로 눈으로 본다. 빌드를 일부러 깨뜨릴 필요 없이 Pub/Sub 에 테스트 메시지를 하나 넣으면 된다.
gcloud pubsub topics publish cloud-builds \
--attribute=buildId=test-0001,status=FAILURE \
--message='{"id":"test-0001-aaaa-bbbb-cccc-000000000001","projectId":"aboutfishingproduct","status":"FAILURE","logUrl":"https://console.cloud.google.com/cloud-build/builds?project=aboutfishingproduct","startTime":"2026-09-10T02:50:00Z","finishTime":"2026-09-10T02:51:04Z","substitutions":{"TRIGGER_NAME":"booking-api-prod-build","REPO_NAME":"aboutfishing-booking-api","TAG_NAME":"v2.54.0","_ENV":"prod","_SVC":"예약 API"}}'
테스트 메시지를 보내면 실제 빌드가 도는 것이 아니라 알림만 한 건 간다. 채널에 test-0001 이 붙은 실패 카드가 뜨면 성공이다. 확인 후 그 메시지는 채널에서 지운다.
_ENV 가 비어 있으면 ⚠️ 환경 미지정 으로 표시하게 한다. 앞으로 누가 트리거를 새로 만들면서 변수를 빠뜨리면 이 표시로 바로 드러난다. 이게 없으면 몇 달 뒤에 조용히 틀린 채로 돌아간다.
끝난 걸 아는 법 · 위 테스트 메시지에서 _ENV 를 빼고 다시 보내 본다. 환경 미지정으로 떠야 한다.
지금 알림의 절반 이상이 dev·stage 다. 운영만 빌드봇 전체 에 남기고 나머지는 새 스페이스로 보낸다. 보내는 쪽에서 _ENV 값에 따라 웹훅 주소만 갈라 주면 된다.
새 스페이스와 웹훅 주소는 요청자가 만들어 전달한다. 만들지 여부는 8번을 보고 정한다.
릴리즈 한 번에 svc·map·booking 세 건이 따로 뜬다. 챗 웹훅 주소 뒤에 스레드 키를 붙이면 같은 태그끼리 한 스레드로 묶인다.
[웹훅 주소]&threadKey=[저장소]-[태그]&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD
끝난 걸 아는 법 · 다음 릴리즈에서 세 건이 한 스레드 안에 붙어서 온다.
| _ENV 값 | 카드에 찍히는 것 |
|---|---|
| prod | 🟥 PROD |
| stage | 🟨 STAGE |
| dev | ⬜ DEV |
| 없거나 그 밖의 값 | ⚠️ 환경 미지정 |
구글챗 카드는 글자 색을 바꿀 수 없어서 이모지로 구분한다. 채팅 목록 미리보기에 카드 제목이 뜨므로 배지는 반드시 제목 맨 앞에 둔다.
왼쪽이 카드에서 보이는 자리, 오른쪽이 Pub/Sub 메시지에서 읽을 값이다.
| 카드 자리 | 예시 | 어디서 읽나 |
|---|---|---|
| 제목 · 배지 | 🟥 PROD | substitutions._ENV → 위 배지 표 |
| 제목 · 서비스 | 예약 API | substitutions._SVC. 없으면 substitutions.REPO_NAME |
| 제목 · 버전 | v2.54.0 | substitutions.TAG_NAME. 없으면 BRANCH_NAME + 공백 + SHORT_SHA |
| 제목 · 실패 표시 | — 빌드 실패 | status 가 SUCCESS 가 아닐 때만 붙인다. 성공이면 아무것도 안 붙인다 |
| 부제 | 빌드 성공 · 2분 12초 · 11:52 종료 | status 한글 표기 + (finishTime − startTime) + finishTime 을 한국 시각으로 |
| 환경 | prod | substitutions._ENV |
| 저장소 | aboutfishing-booking-api | substitutions.REPO_NAME |
| 트리거 | booking-api-prod-build | substitutions.TRIGGER_NAME |
| 빌드 | edc45d6d | id 의 앞 8자 |
| 깨진 단계 (실패일 때만) | Step 3 (docker build) | steps[] 중 status 가 SUCCESS 가 아닌 첫 번째. 순번과 name 또는 id |
| 지금 운영 (prod 실패일 때만) | 직전 버전 그대로입니다. 이번 것은 안 나갔습니다 | 고정 문구 |
| 버튼 | 로그 보기 | logUrl |
빼는 것 · Project(프로젝트가 하나뿐이라 매번 같다) · Branch 가 없을 때의 N/A 줄(태그 빌드면 태그만 보이면 된다) · Build ID 뒷자리.
성공
🟥 PROD · 예약 API v2.54.0 빌드 성공 · 2분 12초 · 11:52 종료 환경 prod 저장소 aboutfishing-booking-api 트리거 booking-api-prod-build 빌드 edc45d6d [ 로그 보기 ]
실패
🟥 PROD · 예약 API v2.54.0 — 빌드 실패 Step 3 (docker build) 에서 실패 · 1분 04초 환경 prod 지금 운영 직전 버전 그대로입니다. 이번 것은 안 나갔습니다 저장소 aboutfishing-booking-api 트리거 booking-api-prod-build 빌드 edc45d6d [ 로그 보기 ]
개발
⬜ DEV · 플랫폼 main a1b2c3d 빌드 성공 · 1분 41초 · 11:05 종료 ...
구글챗 웹훅에 보내는 본문이다. 대괄호 부분만 위 대응표대로 채우면 된다.
{
"cardsV2": [{
"cardId": "build-status",
"card": {
"header": {
"title": "[배지] · [서비스] [버전][실패표시]",
"subtitle": "[상태] · [소요] · [종료시각] 종료"
},
"sections": [{
"widgets": [
{ "decoratedText": { "topLabel": "환경", "text": "[_ENV]" } },
{ "decoratedText": { "topLabel": "저장소", "text": "[REPO_NAME]" } },
{ "decoratedText": { "topLabel": "트리거", "text": "[TRIGGER_NAME]" } },
{ "decoratedText": { "topLabel": "빌드", "text": "[id 앞 8자]" } },
{ "buttonList": { "buttons": [
{ "text": "로그 보기", "onClick": { "openLink": { "url": "[logUrl]" } } }
]}}
]
}]
}
}]
}
실패일 때는 환경 바로 아래에 깨진 단계 와 지금 운영 두 줄을 같은 형태로 끼워 넣는다.
아래가 전부 확인되면 끝난 것이다. 요청자에게는 이 목록에 체크한 결과와 카드 스크린샷 두 장(성공·실패)만 주면 된다.
_ENV 와 _SVC 가 들어갔다 (gcloud builds triggers list 로 빈 칸 없음 확인)_ENV 를 뺀 테스트 메시지가 ⚠️ 환경 미지정 으로 뜬다Branch: N/A 줄이 더는 안 보인다| 무엇이 잘못됐나 | 어떻게 되돌리나 |
|---|---|
| 트리거에 변수를 넣었더니 빌드가 실패한다 | ALLOW_LOOSE 가 빠진 것이다. 저장소의 cloudbuild.yaml 에 넣거나, 트리거에서 방금 넣은 _ENV·_SVC 두 줄을 지우고 다시 import 한다 |
| 카드가 깨져서 온다 | 알림 보내는 쪽을 직전 버전으로 되돌린다. Cloud Run 이면 이전 리비전으로 트래픽을 돌린다 |
| 알림이 아예 안 온다 | 구독이 살아 있는지, 보내는 서비스에 오류 로그가 있는지 본다. 빌드 자체는 알림과 무관하게 정상 동작한다 |
| 알림이 두 번씩 온다 | 구독이 둘이거나 예전 것을 안 끄고 새로 붙인 것이다. 하나만 남긴다 |
이 작업은 전부 알림 쪽이다. 2단계의 대체 변수만 빌드에 닿고, 그것도 ALLOW_LOOSE 하나로 막힌다. 서비스 배포 자체에는 영향이 없다.
아래는 정하지 말고 요청자(서현일)에게 물어봐 주면 된다. 나머지는 위 순서대로 진행하면 된다.
| 번호 | 물어볼 것 | 왜 필요한가 |
|---|---|---|
| 1 | dev 와 test 를 나눌지, 둘 다 dev 로 묶을지 | 배지를 세 개로 할지 네 개로 할지가 갈린다. 넷이 되면 목록에서 구분이 흐려진다 |
| 2 | dev·stage 알림을 별도 스페이스로 뺄지 (6단계) | 뺀다면 새 스페이스와 웹훅 주소를 요청자가 만들어 준다 |
| 3 | 운영 빌드 실패 시 멘션을 걸지, 건다면 누구에게 | 지금은 성공과 실패가 같은 무게로 흘러간다 |
| 4 | _SVC 에 넣을 한글 서비스 이름 | 3단계 표의 이름은 예시다. 카드에 그대로 찍힌다 |
| 5 | 앱(안드로이드·iOS) 빌드는 어디서 도는지 | 확인된 트리거 9개는 전부 웹·서버다. 앱 빌드가 다른 시스템에서 돌고 있다면 그쪽도 같은 방식으로 맞춰야 한다 |
| 6 | 릴리즈 빌드가 끝나면 실제 서비스 반영이 자동인지 수동인지 | 빌드 성공을 배포 완료로 볼 수 있는지가 여기서 갈린다. 전사_배포공지 자동화의 전제다 |
작성 2026-09-09. 트리거 목록과 카드 형식은 구글챗 빌드봇 전체 채널에서 직접 읽어 확인한 것이고, 각 트리거의 환경 값은 이름으로 추정한 것이라 1단계에서 확정이 필요하다.