콘텐츠로 이동

웹 개발 패턴 & 실수 방지 가이드

비개발자가 Claude와 사이트/앱 만들 때 반복되는 패턴 정리.

코드 구조 관리 규칙

언제 정리해야 하나

  • 같은 코드 3곳 이상 복붙 → 컴포넌트/함수로 분리
  • 파일 1개가 300줄 초과 → 데이터와 UI 분리 검토
  • 기능 추가 시 6개 파일 동시 수정 → 공통 부분 추출 필요
  • 데이터가 계속 쌓이는 구조 → 데이터 추가 전에 구조 정리 (짐 넣기 전 선반 정리)

정리 타이밍

  • 기능이 안정된 직후 (버그 수정 끝나고, 데이터 대량 추가 전)
  • "나중에 해야지" = 안 하게 됨. 데이터 쌓인 후 리팩토링은 3배 귀찮음

CSS Grid 필수 체크

pre/code + Grid 조합

.grid-container > * {
  min-width: 0;  /* 필수! 없으면 긴 코드줄이 컬럼 비율 깨뜨림 */
}
- Grid 아이템의 min-width 기본값 = auto (콘텐츠 최소 너비) - <pre> 태그는 줄바꿈 안 하니까 긴 줄이 컬럼을 밀어냄 - overflow-x: auto 있어도 min-width:auto면 소용없음

iframe 주의사항

srcdoc 안에서 CSS 충돌

  • <style> + <body> 가 한 문서 안에 있으면 태그 셀렉터 주의
  • blockquote {}, table {} 같은 태그 셀렉터 → 미리보기 요소에도 적용됨
  • 해결: class 기반 셀렉터 사용 or 미리보기는 inline style

DOM 이동 시 참조 깨짐

  • parent.after(element) 로 iframe 포함 요소 이동하면 iframe 리로드
  • JS에서 iframe 참조 캐싱하지 말고, 필요할 때 동적으로 querySelector

Vercel 배포 체크

  • 커밋 이메일 ≠ Vercel 계정 이메일 → 배포 조용히 무시 (에러 없음!)
  • 확인: git config user.email → Vercel 계정과 동일한지
  • 배포 안 되면 이메일 불일치 먼저 의심

배포 전 필수 루틴

매번 하기

  1. 빌드 테스트: npx astro build (또는 npm run build) - 에러 없는지 확인
  2. 커밋은 작게: 기능 1개 = 커밋 1개. 문제 생기면 그 커밋만 되돌릴 수 있음
  3. push 후 배포 확인: Vercel 대시보드에서 배포 시작됐는지 체크

확인할 때

  • Ctrl+Shift+R (강력 새로고침) — 브라우저 캐시 때문에 옛 버전 보이는 경우 많음
  • "수정했는데 똑같아요" → 80%는 브라우저 캐시 문제
  • 시크릿 모드(Ctrl+Shift+N)로 열어보면 캐시 없이 확인 가능

되돌리기 (문제 생겼을 때)

  • git log --oneline -10 — 최근 커밋 목록 확인
  • git revert [커밋해시] — 특정 커밋만 취소 (안전, 기록 남음)
  • 절대 하지 말 것: git reset --hard (작업 내용 날아감)
  • 커밋을 작게 해둬야 → 되돌릴 때 딱 그 부분만 취소 가능

스크린샷으로 디버깅

  • 말로 설명하면 오해 생김 → 스크린샷이 최고의 버그 리포트
  • "안 돼요" → 뭐가 안 되는지 캡처해서 보여주기
  • 작동하는 것 vs 안 되는 것 나란히 비교 → 차이점이 원인 (이번에 Grid 버그 이렇게 찾음)

디버깅 마인드셋

  • 같은 코드인데 특정 요소만 깨질 때 → 콘텐츠 차이 의심 (길이, 특수문자, 태그)
  • "코드가 똑같은데 왜 다르지?" → 코드가 아니라 데이터가 다른 것
  • 여러 번 수정해도 안 되면 → 원인 가설 자체를 바꿔야 함
  • 같은 방향 3번 시도해도 안 되면 → 완전히 다른 각도에서 보기

GitHub Actions (자동화 워크플로우)

CI/CD의 일종. "특정 조건이 되면 서버에서 자동으로 스크립트를 실행"하는 것. 비유: 매일 아침 7시에 알바생이 가게 문 열고 청소하는 것.

핵심 개념

  • 워크플로우 파일: .github/workflows/이름.yml (YAML 형식)
  • 트리거: schedule(정기 실행), push(코드 올릴 때), workflow_dispatch(수동 실행)
  • Secrets: 비밀번호/API 키를 안전하게 저장. 리포 Settings > Secrets and variables > Actions
  • 코드에서 ${{ secrets.이름 }} 으로 접근
  • 한번 저장하면 다시 볼 수 없음 (수정만 가능)

기본 구조 (예: 매일 뉴스 수집)

name: 뉴스 수집
on:
  schedule:
    - cron: '0 22 * * *'  # UTC 22시 = KST 07시
  workflow_dispatch:       # 수동 실행 버튼
jobs:
  fetch:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4    # 코드 가져오기
      - uses: actions/setup-python@v5  # 파이썬 설치
        with:
          python-version: '3.11'
      - run: pip install requests     # 라이브러리 설치
      - run: python scripts/fetch-news.py  # 스크립트 실행
        env:
          API_KEY: ${{ secrets.API_KEY }}  # Secrets 주입
      - run: |                         # 결과를 git에 저장
          git config user.name "github-actions"
          git config user.email "actions@github.com"
          git add game/news.json
          git diff --cached --quiet || git commit -m "auto: update news"
          git push

실전 주의사항

  • cron 시간은 UTC: KST = UTC + 9시간. KST 07시 = UTC 22시 (전날)
  • push 충돌: Actions가 자동 커밋 + 사용자도 push하면 rejected (fetch first) 에러
  • 해결: git pull --rebase 후 다시 push
  • Re-run vs Run workflow: Re-run은 옛날 코드로 재실행. Run workflow가 최신 코드 실행
  • 빈 커밋 방지: git diff --cached --quiet || git commit (변경 없으면 커밋 안 함)
  • Actions 결과 확인: 리포 > Actions 탭에서 실행 로그 확인 가능

외부 API 활용 패턴

네이버 검색 API

  • 용도: 뉴스 검색, 블로그 검색 등
  • 인증: Client ID + Client Secret (네이버 개발자센터에서 발급)
  • 호출: HTTP GET + 헤더에 인증 정보
    import requests
    headers = {
        'X-Naver-Client-Id': 'YOUR_ID',
        'X-Naver-Client-Secret': 'YOUR_SECRET'
    }
    r = requests.get('https://openapi.naver.com/v1/search/news.json',
        params={'query': '보이스피싱', 'display': 20, 'sort': 'date'},
        headers=headers)
    data = r.json()
    
  • 주의: 일일 호출 한도 있음 (무료: 25,000건/일)
  • HTML 태그 제거: 응답에 <b>, &quot; 등 포함 → 정규식으로 제거 필요

Google News RSS

  • 용도: API 키 없이 뉴스 수집 (백업용)
  • URL: https://news.google.com/rss/search?q=키워드&hl=ko&gl=KR&ceid=KR:ko
  • 형식: XML → 파이썬 xml.etree.ElementTree로 파싱
  • 주의: URL이 news.google.com/rss/articles/... 형태의 리다이렉트 → 실제 기사 URL이 아님
  • 리다이렉트 URL은 "원문 보기"에 쓰면 안 됨 (빈 문자열로 처리)

뉴스 데이터 품질 관리

  • 제목 필수 키워드: "보이스피싱", "스미싱", "피싱" 등 → 없으면 제외
  • 제외 키워드: "전세사기", "검거", "교육", "대통령", "국회" 등 → 수법 기사가 아닌 것 걸러내기
  • 날짜 필터: 7일 이내만 (오래된 기사 제외)
  • URL 검증: 도메인만 있는 URL (https://example.com/), 리다이렉트 URL → 차단
  • 시나리오 매칭: 키워드 → 시나리오 직접 매핑이 카테고리 기반보다 정확함
  • 직접: "빗썸" → sms_finance_01 (정확)
  • 카테고리: "금융" → sms_finance_01 (애매)

JSON 데이터 설계

캐시 버스팅

fetch('data.json?t=' + Date.now())  // 매번 새 URL → 브라우저 캐시 무시
- 정적 파일(JSON, CSS, JS)은 브라우저가 캐시함 - 자주 바뀌는 데이터 → ?t=타임스탬프 또는 ?v=버전번호 붙이기 - CSS/JS 버전 관리: style.css?v=16 → 수정할 때마다 숫자 올리기

롤링 데이터 + 아카이브 패턴

  • 현재 데이터: news.json (최근 7일, 5~10개)
  • 아카이브: news-archive/2026-03.json (월별 누적)
  • 스크립트가 매일 실행 → 현재 파일 갱신 + 아카이브에 추가
  • 아카이브는 나중에 통계/분석에 활용 가능

fallback 데이터

  • API 실패 시를 대비해 fallback 데이터를 JSON에 포함
  • news 배열(실시간) + fallback 배열(수동 큐레이션) 구조
  • 코드에서: var items = data.news.length >= 3 ? data.news : data.fallback

호스팅 & 배포 비용 비교

호스팅 트래픽 비교

호스팅 트래픽 무료 초과 시
Cloudflare Pages 무제한 없음
Vercel 월 100GB 추가 과금
Netlify 월 100GB GB당 $55
AWS Amplify 월 15GB GB당 $0.15

이미지 저장소 비교

서비스 저장 무료 전송비 (1GB당)
Cloudflare R2 10GB 0원
AWS S3 5GB $0.09
Google Cloud 5GB $0.12

Cloudflare R2 무료 범위 (매월)

  • 저장: 10GB / 업로드: 100만 건 / 읽기: 1,000만 건 / 전송비: 무제한 무료
  • 활성화 시 카드 등록 필요 (무료 범위 초과 대비, 실 결제 안 됨)

Cloudflare 비즈니스 모델

  • "무료로 끌어들여서 기업 고객한테 돈 받기" (카카오톡과 같은 구조)
  • 개인/소규모: 무료. 대기업: Pro/Business/Enterprise (월 $20 ~ 수천만원)
  • 전 세계 인터넷 트래픽 약 20%가 Cloudflare 네트워크 경유

Cloudflare 선택 기준

  • 콘텐츠 사이트(블로그, 포트폴리오, 홈페이지) → Cloudflare Pages (트래픽 무제한)
  • 이미지 많은 사이트 → R2 추가 (전송비 0원)
  • 서버 기능 필요한 앱 → Vercel (서버리스 함수 편함)

R2 세팅 순서

  1. Cloudflare 계정 > Storage & databases > R2 > 활성화 (카드 등록)
  2. wrangler CLI: npm install -D wrangler
  3. 로그인: npx wrangler login
  4. 버킷 생성: npx wrangler r2 bucket create 버킷이름
  5. 퍼블릭 접근: 대시보드 > R2 > 버킷 > Settings > Public access

도메인 이전 절차 (기존 사이트 -> Cloudflare Pages)

  1. 새 사이트 완성 -> Cloudflare Pages에 임시 URL로 배포
  2. 기존 사이트 URL 목록 정리 -> 301 리다이렉트 매핑
  3. Cloudflare에서 도메인 추가 -> 네임서버 2개 받기
  4. 기존 도메인 관리사이트에서 네임서버 변경
  5. DNS 전파 완료 후 sitemap 재제출

프로젝트 시작할 때 체크리스트

첫 세팅

  • [ ] git config user.email 확인 (배포 서비스 계정과 일치하는지)
  • [ ] 배포 연결 후 테스트 push → 실제 배포되는지 확인
  • [ ] CLAUDE.md에 프로젝트 구조, 배포 설정, 현재 상태 기록

구조 설계

  • [ ] 반복될 UI 패턴 → 컴포넌트로 분리 (나중에 하면 귀찮음)
  • [ ] 데이터와 UI 분리 (데이터만 추가하면 페이지가 늘어나는 구조)
  • [ ] 공유 타입/인터페이스 정의 (여러 파일에서 같은 데이터 구조 쓸 때)

스타일

  • [ ] CSS Grid 쓸 때 → 자식에 min-width: 0 습관적으로 넣기
  • [ ] 모바일 반응형 → 개발 초반에 확인 (나중에 하면 전면 수정)
  • [ ] 폰트/색상 → CSS 변수(custom property)로 관리