Skip to content

Debugging Improvements Plan

This content is not available in your language yet.

  1. 현재 구조의 문제점 분석
  2. 개선 방안 기획
  3. Cloudflare Logpush 통합
  4. 구현 우선순위

1. GitHub Actions Workflow 구조적 문제

섹션 제목: “1. GitHub Actions Workflow 구조적 문제”

❌ 문제점 1: 인라인 스크립트 과다

섹션 제목: “❌ 문제점 1: 인라인 스크립트 과다”
  • 현재 상태: deploy.yml이 750줄로 매우 길고, 대부분의 로직이 인라인 run: 블록에 직접 작성됨
  • 영향:
    • 로컬에서 재현 불가능
    • 디버깅 시 CI 환경에만 의존
    • 코드 재사용 불가
  • 예시: D1/KV provisioning 로직이 200줄 이상의 인라인 bash 코드

❌ 문제점 2: Shell First 전략 미적용

섹션 제목: “❌ 문제점 2: Shell First 전략 미적용”
  • 현재 상태: ci.shsteps/deploy.sh가 존재하지만, deploy.yml에서 직접 사용하지 않음
  • 영향:
    • CI와 로컬 환경이 분리됨
    • 동일한 로직을 두 곳에서 유지보수해야 함
    • 로컬 재현 불가능
  • 현재 상태:
    • ACTIONS_STEP_DEBUG 설정 없음
    • Bash strict mode (set -euxo pipefail) 일관성 없음
    • tmate SSH 세션 없음
    • 로그 그룹핑 없음
  • 영향:
    • 실패 원인 파악이 매우 어려움
    • 환경 변수, 파일 상태 확인 불가
    • 실패한 VM에 접근 불가
  • 현재 상태:
    • wrangler deploy --dry-run 없음
    • Bundle 출력 저장 없음
    • Preview 환경 배포 없음
  • 영향:
    • Cloudflare에 잘못된 코드 배포 가능
    • 배포된 코드 추적 불가
    • 롤백 시점 파악 어려움

❌ 문제점 5: 버전/빌드 정보 없음

섹션 제목: “❌ 문제점 5: 버전/빌드 정보 없음”
  • 현재 상태: Worker 코드에 배포 버전, Git commit hash, 빌드 타임스탬프가 없음
  • 영향:
    • 어떤 코드가 실행 중인지 추적 불가
    • 문제 발생 시 원인 코드 버전 파악 불가
    • 배포 이력과 로그 연결 불가

❌ 문제점 6: 구조화된 로깅 부재

섹션 제목: “❌ 문제점 6: 구조화된 로깅 부재”
  • 현재 상태: console.log만 사용, 구조화된 로그 포맷 없음
  • 영향:
    • HTTP 요청 추적 어려움
    • 에러 컨텍스트 부족
    • 로그 분석 자동화 불가

❌ 문제점 7: Cloudflare Logpush 미설정

섹션 제목: “❌ 문제점 7: Cloudflare Logpush 미설정”
  • 현재 상태: Logpush 설정 없음, 로그가 Cloudflare Dashboard에만 존재
  • 영향:
    • 장기 보관 불가
    • 외부 분석 도구 연동 불가
    • 법적 추적 증거 확보 불가
  • 현재 상태: staging → production 직접 배포
  • 영향:
    • Production 배포 전 최종 검증 불가
    • 자동화된 테스트 없음
    • 승인 프로세스 없음

CI에서 실행하는 모든 로직을 로컬에서도 100% 재현 가능하게 만들기

1.1 GitHub Actions Workflow 단순화

# .github/workflows/deploy.yml (개선 후)
jobs:
deploy:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
run: .github/scripts/setup.sh
- name: Run CI Pipeline
run: .github/scripts/ci.sh
env:
CI_MODE: deploy
DEPLOY_ENV: ${{ steps.env.outputs.environment }}

1.2 통합 CI 스크립트 구조

.github/scripts/
├── ci.sh # 메인 진입점 (기존)
├── setup.sh # 환경 설정 (신규)
├── steps/
│ ├── research.sh # 기존
│ ├── seed.sh # 기존
│ └── deploy.sh # 개선 필요
└── lib/
├── debug.sh # 디버깅 유틸리티 (신규)
├── validation.sh # 검증 유틸리티 (신규)
└── logging.sh # 로깅 유틸리티 (신규)

1.3 로컬 실행 가능성 보장

Terminal window
# 로컬에서 CI와 동일하게 실행
./.github/scripts/ci.sh
# 특정 단계만 실행
CI_MODE=deploy DEPLOY_ENV=staging ./.github/scripts/ci.sh

실패 시 10배 빠르게 원인 파악

2.1 GitHub Actions 디버그 모드 활성화

.github/workflows/deploy.yml
env:
ACTIONS_STEP_DEBUG: true
ACTIONS_RUNNER_DEBUG: true

2.2 Bash Strict Mode 적용

.github/scripts/lib/debug.sh
set -euxo pipefail
# 모든 스크립트 상단에 포함
source "$(dirname "$0")/lib/debug.sh"

2.3 tmate SSH 세션 추가

.github/workflows/deploy.yml
- name: Setup tmate session (on failure)
if: failure()
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-this-repository: true

2.4 로그 그룹핑 및 환경 정보 출력

.github/scripts/lib/logging.sh
log_group() {
echo "::group::$1"
shift
"$@"
echo "::endgroup::"
}
log_env() {
log_group "Environment Variables" env | sort
}
log_files() {
log_group "File Structure" find . -type f -name "*.sh" -o -name "*.json" | head -20
}

Cloudflare에 배포하기 전에 100% 검증

3.1 Wrangler Dry-Run 검증

.github/scripts/steps/deploy.sh
echo "🔍 Running wrangler dry-run..."
wrangler deploy --dry-run --env "$DEPLOY_ENV" > bundle-info.txt 2>&1
# Bundle 정보를 Artifact로 저장
echo "📦 Saving bundle information..."
# GitHub Actions에서 artifact 업로드

3.2 Preview 환경 배포

.github/workflows/deploy.yml
- name: Deploy to Preview
run: |
wrangler deploy --env preview --minify
# Preview URL로 자동 테스트 실행
- name: Approve Production Deployment
if: github.event.inputs.environment == 'production'
# Manual approval 또는 자동 테스트 통과 후

3.3 Bundle 정보 저장

.github/scripts/steps/deploy.sh
BUNDLE_HASH=$(wrangler deploy --dry-run 2>&1 | grep -oE 'hash: [a-f0-9]+' | cut -d' ' -f2)
echo "bundle_hash=$BUNDLE_HASH" >> $GITHUB_OUTPUT

배포된 코드와 실행 로그를 완전히 추적 가능하게

4.1 빌드 정보 주입

// src/lib/build-info.ts (신규)
/**
* Build information injected at build time
* This file is generated by the build process
*/
export const BUILD_INFO = {
version: process.env.BUILD_VERSION || "unknown",
commit: process.env.GIT_COMMIT || "unknown",
timestamp: process.env.BUILD_TIMESTAMP || new Date().toISOString(),
environment: process.env.CF_ENV || "unknown",
};
// src/index.ts
import { BUILD_INFO } from "./lib/build-info";
export default {
fetch(req, env, ctx) {
// 모든 요청에 빌드 정보 로깅
console.log("deploy", {
version: BUILD_INFO.version,
commit: BUILD_INFO.commit,
timestamp: BUILD_INFO.timestamp,
environment: BUILD_INFO.environment,
});
// HTTP 요청 정보 로깅
const url = new URL(req.url);
console.log("http", {
method: req.method,
path: url.pathname,
userAgent: req.headers.get("user-agent"),
ip: req.headers.get("cf-connecting-ip"),
country: req.cf?.country,
requestId: crypto.randomUUID(),
});
// ... 기존 로직
}
};

4.2 빌드 시 정보 주입

.github/scripts/steps/deploy.sh
export BUILD_VERSION="$(date -u +%Y-%m-%dT%H%M%SZ)"
export GIT_COMMIT="${{ github.sha }}"
export BUILD_TIMESTAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
# wrangler deploy 시 환경 변수 전달
wrangler deploy --env "$DEPLOY_ENV" \
--var BUILD_VERSION="$BUILD_VERSION" \
--var GIT_COMMIT="$GIT_COMMIT" \
--var BUILD_TIMESTAMP="$BUILD_TIMESTAMP"

4.3 구조화된 로깅

// src/lib/logger.ts (신규)
interface LogContext {
requestId?: string;
userId?: string;
action?: string;
[key: string]: unknown;
}
export function log(level: "info" | "warn" | "error", message: string, context?: LogContext) {
console.log(JSON.stringify({
level,
message,
timestamp: new Date().toISOString(),
...context,
}));
}

모든 Worker 로그를 외부 저장소로 자동 푸시하여 장기 보관 및 분석

5.1 Logpush 설정 (수동)

Terminal window
# Cloudflare Dashboard 또는 API를 통해 설정
# Workers Logpush는 현재 Beta 기능이므로 API 사용 필요
# R2 Bucket에 로그 저장 설정
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/logpush/jobs" \
-H "Authorization: Bearer {api_token}" \
-H "Content-Type: application/json" \
-d '{
"name": "workers-logs",
"destination_conf": "r2://newsfork-logs/{DATE}?account-id={account_id}&access-key-id={access_key_id}&secret-access-key={secret_access_key}",
"dataset": "workers_trace_events",
"logpull_options": "fields=EventTimestampMs,Outcome,Exceptions,Logs,ScriptName"
}'

5.2 Worker 코드에서 구조화된 로그 출력

src/index.ts
export default {
fetch(req, env, ctx) {
const requestId = crypto.randomUUID();
const startTime = Date.now();
// 요청 시작 로그
console.log(JSON.stringify({
type: "request_start",
requestId,
method: req.method,
url: req.url,
timestamp: new Date().toISOString(),
build: BUILD_INFO,
}));
return ctx.waitUntil(
(async () => {
try {
const response = await app.fetch(req, env, ctx);
// 요청 완료 로그
console.log(JSON.stringify({
type: "request_end",
requestId,
status: response.status,
duration: Date.now() - startTime,
timestamp: new Date().toISOString(),
}));
return response;
} catch (error) {
// 에러 로그
console.error(JSON.stringify({
type: "request_error",
requestId,
error: error.message,
stack: error.stack,
timestamp: new Date().toISOString(),
}));
throw error;
}
})()
);
}
};

5.3 Logpush 설정 자동화

  • 기획 및 정책: docs/LOGPUSH_INTEGRATION_PLAN.md
  • 구현: provision 단계에서 staging/production일 때 provision-logpush.sh가 R2 버킷(newsfork-logs-{env}) 생성 및 Logpush Job(workers_trace_events → R2) 생성. verify 단계에서 해당 Job 존재·enabled 검사.
  • 스크립트: .github/scripts/steps/provision-logpush.sh, .github/scripts/lib/logpush-api.sh

  1. GitHub Actions 디버그 모드 활성화

    • ACTIONS_STEP_DEBUG: true 추가
    • 예상 시간: 5분
  2. Bash Strict Mode 적용

    • 모든 스크립트에 set -euxo pipefail 추가
    • 예상 시간: 30분
  3. 로그 그룹핑 추가

    • 환경 변수, 파일 구조 출력
    • 예상 시간: 1시간
  4. Worker 빌드 정보 주입

    • BUILD_INFO 생성 및 로깅
    • 예상 시간: 2시간
  1. Shell First 전략 완전 적용

    • deploy.yml 단순화
    • 모든 로직을 .github/scripts/로 이동
    • 예상 시간: 4시간
  2. Wrangler Dry-Run 검증

    • 배포 전 bundle 검증
    • 예상 시간: 2시간
  3. tmate SSH 세션 추가

    • 실패 시 SSH 접속 가능
    • 예상 시간: 30분
  1. Preview 환경 구축

    • Preview 배포 → 테스트 → Production 승인
    • 예상 시간: 4시간
  2. Cloudflare Logpush 설정

    • R2 또는 외부 저장소 연동
    • 예상 시간: 2시간 (수동 설정)
  3. 구조화된 로깅 시스템

    • JSON 로그 포맷
    • 로그 분석 도구 연동
    • 예상 시간: 4시간

  • 현재: 실패 원인 파악에 평균 2-4시간
  • 개선 후: 평균 15-30분 (80% 단축)
  • 현재: Production 배포 실패율 ~10%
  • 개선 후: ~2% (Dry-run 검증으로 사전 차단)
  • 현재: Cloudflare Dashboard만 (7일 보관)
  • 개선 후: R2 장기 보관 + 외부 분석 도구 연동