[주간회고] 2026.02.17

김재만·2026년 2월 17일

작업한 것

  • in c 프로젝트 신규 생성
    • 프로젝트 구조 논의(모노레포)
      • frontend
      • backend
    • 프로젝트 가이드 문서 작성
      • README.md
        # Classical Music Community (클래식 커뮤니티 서비스)
        
        클래식 음악 애호가들을 위한 커뮤니티 서비스 프로젝트입니다.
        
        ## 프로젝트 구조 (Monorepo)
        
        - `backend/`: FastAPI 기반의 RESTful API 서버
        - `frontend/`: Next.js 기반의 웹 프론트엔드 (향후 모바일 확장 고려)
        - `docs/`: BDD 시나리오, QMS 문서 및 프로젝트 관련 가이드
        
        ## 개발 프로세스
        
        1. **BDD (Behavior Driven Development)**: `docs/features` 내에 거킨(Gherkin) 문법으로 사용자 시나리오 정의
        2. **TDD (Test Driven Development)**: 정의된 시나리오를 바탕으로 유효하지 않은 테스트 작성 후 기능 구현
        3. **QMS (Quality Management System)**: 품질 관리 기준에 따른 문서화 및 검증
        
        ## 기술 스택
        
        - **Backend**: Python, FastAPI
        - **Frontend**: TypeScript, Next.js, Vanilla CSS
        - **Infrastructure**: FCM (Push Notification)
        
        ---
        *본 가이드는 PM과 개발팀 간의 협업을 위해 한국어로 작성되었습니다.*
        
      • ENGINEERING_GUIDE_KR.md
        # 엔지니어링 가이드라인: BDDQMS 프로세스
        
        이 문서는 프로젝트의 품질 관리 및 개발 효율성을 위해 BDD(Behavior-Driven Development)QMS(Quality Management System) 프로세스를 정의합니다. 모든 개발 단계는 한글을 기본 언어로 사용합니다.
        
        ## 1. BDD (Behavior-Driven Development) 프로세스
        
        BDD는 사용자의 관점에서 시스템의 동작을 정의하고 이를 바탕으로 테스트와 코드를 작성하는 방식입니다.
        
        ### 단계별 절차
        1.  **유저 플로우(User Flow) 작성**: 새로운 기능에 대한 사용자 시나리오를 **Mermaid 차트**로 작성하고 사용자(관리자)의 승인을 받습니다. (필요 시 Mermaid 코드를 피그잼에 복사하여 활용할 수 있습니다.)
        2.  **RTM(Requirement Traceability Matrix) 업데이트**: `docs/RTM.md`에 Markdown 테이블 형식으로 요구사항을 등록합니다. 식별 편의를 위해 테이블 상단/하단에 주석 형태의 JSON 데이터(`<!-- { "id": ... } -->`)를 포함할 수 있습니다.
        3.  **거킨(Gherkin) 시나리오 작성**: `# language: ko` 헤더를 사용하여 한글로 시나리오를 작성합니다. 초기에는 Cucumber 같은 무거운 도구 도입 없이, 테스트 코드와의 매핑 용도로 활용합니다.
        4.  **RTM 업데이트**: 작성된 거킨 시나리오와 요구사항을 매핑하여 RTM을 업데이트합니다.
        5.  **테스트 코드 작성**: **Playwright**를 사용하여 UI 테스트를 작성하고, 프로젝트 단위별 유닛 테스트를 병행합니다.
            - **중요**: 테스트 코드의 각 라인에는 대응되는 거킨 시나리오 문구를 주석으로 포함합니다.
              ```javascript
              // 조건: 사용자가 로그인 페이지에 있다
              await page.goto('/login');
              // ...
              ```
        6.  **코드 구현 및 테스트**: 테스트가 통과(Green)할 때까지 `코드 작성 -> 테스트 실행 -> 코드 작성` 과정을 반복합니다.
        7.  **최종 승인**: 모든 테스트가 Green 라이트가 되면 최종 푸쉬 승인을 요청합니다.
        
        ## 2. QMS (Quality Management System) 프로세스
        
        QMS는 소프트웨어 릴리즈의 안정성과 투명성을 보장하기 위한 시스템입니다.
        
        ### 릴리즈 노트 관리
        - **릴리즈 노트 작성**: 코드 머지(Merge) 시 해당 변경 사항에 대한 릴리즈 노트를 Markdown(`.md`) 형식으로 작성합니다.
        - **내용 구성**:
            - 변경 요약
            - 구현된 기능 목록 (RTM 참조)
            - 수정된 버그
            - 영향 범위 및 주의 사항
        
        ## 3. 언어 및 표기 규칙
        - 모든 기술 문서, 거킨 시나리오, 릴리즈 노트는 **한글 위주**로 작성합니다.
        - 거킨 시나리오 작성 시 파일 최상단에 `# language: ko`를 반드시 명시합니다.
        ## 4. 문서 동기화 규칙
        - 이 가이드라인과 `README.md`, 그리고 `.agent/workflows/bdd-process-kr.md`는 항상 **동일한 프로세스 정보를 유지**해야 합니다.
        - 프로세스에 변경 사항이 생길 경우, Antigravity는 위 세 파트의 문서를 한꺼번에 업데이트하여 정보의 불일치를 방지합니다.
        
      • .agent/workflows/bdd-process-kr.md
        # 엔지니어링 가이드라인: BDDQMS 프로세스
        
        이 문서는 프로젝트의 품질 관리 및 개발 효율성을 위해 BDD(Behavior-Driven Development)QMS(Quality Management System) 프로세스를 정의합니다. 모든 개발 단계는 한글을 기본 언어로 사용합니다.
        
        ## 1. BDD (Behavior-Driven Development) 프로세스
        
        BDD는 사용자의 관점에서 시스템의 동작을 정의하고 이를 바탕으로 테스트와 코드를 작성하는 방식입니다.
        
        ### 단계별 절차
        1.  **유저 플로우(User Flow) 작성**: 새로운 기능에 대한 사용자 시나리오를 **Mermaid 차트**로 작성하고 사용자(관리자)의 승인을 받습니다. (필요 시 Mermaid 코드를 피그잼에 복사하여 활용할 수 있습니다.)
        2.  **RTM(Requirement Traceability Matrix) 업데이트**: `docs/RTM.md`에 Markdown 테이블 형식으로 요구사항을 등록합니다. 식별 편의를 위해 테이블 상단/하단에 주석 형태의 JSON 데이터(`<!-- { "id": ... } -->`)를 포함할 수 있습니다.
        3.  **거킨(Gherkin) 시나리오 작성**: `# language: ko` 헤더를 사용하여 한글로 시나리오를 작성합니다. 초기에는 Cucumber 같은 무거운 도구 도입 없이, 테스트 코드와의 매핑 용도로 활용합니다.
        4.  **RTM 업데이트**: 작성된 거킨 시나리오와 요구사항을 매핑하여 RTM을 업데이트합니다.
        5.  **테스트 코드 작성**: **Playwright**를 사용하여 UI 테스트를 작성하고, 프로젝트 단위별 유닛 테스트를 병행합니다.
            - **중요**: 테스트 코드의 각 라인에는 대응되는 거킨 시나리오 문구를 주석으로 포함합니다.
              ```javascript
              // 조건: 사용자가 로그인 페이지에 있다
              await page.goto('/login');
              // ...
              ```
        6.  **코드 구현 및 테스트**: 테스트가 통과(Green)할 때까지 `코드 작성 -> 테스트 실행 -> 코드 작성` 과정을 반복합니다.
        7.  **최종 승인**: 모든 테스트가 Green 라이트가 되면 최종 푸쉬 승인을 요청합니다.
        
        ## 2. QMS (Quality Management System) 프로세스
        
        QMS는 소프트웨어 릴리즈의 안정성과 투명성을 보장하기 위한 시스템입니다.
        
        ### 릴리즈 노트 관리
        - **릴리즈 노트 작성**: 코드 머지(Merge) 시 해당 변경 사항에 대한 릴리즈 노트를 Markdown(`.md`) 형식으로 작성합니다.
        - **내용 구성**:
            - 변경 요약
            - 구현된 기능 목록 (RTM 참조)
            - 수정된 버그
            - 영향 범위 및 주의 사항
        
        ## 3. 언어 및 표기 규칙
        - 모든 기술 문서, 거킨 시나리오, 릴리즈 노트는 **한글 위주**로 작성합니다.
        - 거킨 시나리오 작성 시 파일 최상단에 `# language: ko`를 반드시 명시합니다.
        ## 4. 문서 동기화 규칙
        - 이 가이드라인과 `README.md`, 그리고 `.agent/workflows/bdd-process-kr.md`는 항상 **동일한 프로세스 정보를 유지**해야 합니다.
        - 프로세스에 변경 사항이 생길 경우, Antigravity는 위 세 파트의 문서를 한꺼번에 업데이트하여 정보의 불일치를 방지합니다.
    • MVP 유저플로우 정의
      # 상세 설계: 비회원 지역 맞춤 공연 알림 (MVP)
      
      이 문서는 MVP 기능인 비회원 맞춤 알림 서비스의 상세 설계를 정의합니다.
      
      ## 1. 프론트엔드 유저 플로우 (User Flow)
      ```mermaid
      graph TD
          A[사용자 웹사이트 접속] --> B[기본 공연 목록 표시]
          B --> C{개인 맞춤 알림 설정 유도}
          C -- 클릭 (설정 요청) --> D{알림 권한 요청}
          D -- 허용 --> E[지역 정보 선택/입력]
          D -- 차단 --> F[공연 목록 탐색 지속]
          E --> G[브라우저 FCM 토큰 추출]
          G --> H[백엔드로 토큰 및 지역 정보 전송]
          H --> I[맞춤형 상태 업데이트 및 목록 필터링]

      2. 백엔드 시스템 흐름 (System Flows)

      공연 정보 수집 및 파싱 흐름

      sequenceDiagram
          participant S as Scheduler
          participant C as Crawler/Parser
          participant DB as Database
          S->>C: 데이터 수집 트리거 (주기적)
          C->>C: 외부 API/웹 파싱 및 정제
          C->>DB: 중복 체크 및 신규 공연 저장
          DB-->>C: 저장 완료

      지역 맞춤 알림 발송 흐름

      sequenceDiagram
          participant DB as Database
          participant N as Notification Service
          participant FCM as Firebase (FCM)
          participant U as User Browser
          DB->>N: 오늘/내일 오픈되는 지역별 공연 조회
          N->>DB: 해당 지역 구독된 FCM 토큰 조회
          N->>FCM: 알림 메시지 전송 요청 (토큰 기반)
          FCM-->>U: 푸시 알림 도달
    • MVP 구현
      • Concert 정보 수집 기능 구현 image.png 스크린샷 2026-02-12 오후 8.44.10.png
      • 프로젝트 세팅
        • FastAPI 서버 설정
          # 1. backend 폴더를 만들고 들어갑니다.
          mkdir backend
          cd backend
          
          # 2. backend 폴더 안에서 가상환경을 만듭니다.
          python -m venv venv
          
          # 3. 가상환경 활성화
          source venv/bin/activate
          
          # 4. 필수 라이브러리 설치
          pip install fastapi uvicorn
          • 구조 설정
            # app 폴더를 만들고 그 안에 main.py를 생성합니다.
            mkdir app
            touch app/main.py
            
            // app/main.py
            from fastapi import FastAPI
            app = FastAPI()
            @app.get("/")
            def root():
                return {"message": "Hello from Backend Folder!"}
                
            # 현재 위치가 backend/ 인지 확인하고 실행하세요.
            uvicorn app.main:app --reload
            스크린샷 2026-02-14 오후 12.35.05.png
      • 연주회 정보 수집기 구조
        • backend - scraper
          mkdir app/scrapers
          
          touch app/scrapers/base.py
          
          // app/scrapers/base.py
          
          from abc import ABC, abstractmethod
          from typing import List, Dict, Any
          class BaseScraper(ABC):
              @abstractmethod
              def scrape(self) -> List[Dict[Any, Any]]:
                  """외부 사이트에서 데이터를 긁어와 리스트 형식으로 반환합니다."""
                  pass
          touch app/scrapers/sac_scraper.py
          
          // app/scrapers/sac_scraper.py
          
          from .base import BaseScraper
          
          class SACScraper(BaseScraper):
              def scrape(self):
                  # 실제 구현은 나중에 하고, 지금은 '동작' 확인을 위해 가짜 데이터를 리턴합니다.
                  print("예술의 전당 사이트 접속 중...")
                  return [
                      {"title": "베토벤 교향곡 9번", "date": "2024-12-25", "genre": "Classic"},
                      {"title": "재즈 페스티벌", "date": "2024-12-30", "genre": "Jazz"}
                  ]
          touch app/scrapers/factory.py
          
          // app/scrapers/factory.py
          
          from .sac_scraper import SACScraper
          class ScraperFactory:
              @staticmethod
              def get_scraper(scraper_type: str):
                  if scraper_type == "SEOUL_ARTS_CENTER":
                      return SACScraper()
                  raise ValueError(f"지원하지 않는 스크래퍼 타입입니다: {scraper_type}")
      • 수집기 호출 api 설정
        // app/main.py
        
        from fastapi import FastAPI
        # (중요) 상위 패키지 구조를 유지하기 위해 상대 임포트를 사용합니다.
        from .scrapers.factory import ScraperFactory 
        
        app = FastAPI(title="In-C 수련 서버")
        @app.get("/")
        def home():
            return {"message": "서버가 정상 동작 중입니다!"}
        @app.get("/collect")
        def collect_concerts(hall: str = "SEOUL_ARTS_CENTER"):
            """
            쿼리 파라미터로 hall 이름을 받아 적절한 스크래퍼를 찾아 실행합니다.
            """
            try:
                # 1. 팩토리에 마법을 부려달라고 합니다. (어떤 객체인지 몰라도 '스크래퍼'인 건 확실함)
                scraper = ScraperFactory.get_scraper(hall)
                
                # 2. 약속된 이름인 scrape()를 호출합니다.
                raw_data = scraper.scrape()
                
                # 3. 브라우저로 예쁘게 결과를 돌려줍니다.
                return {
                    "success": True,
                    "hall_requested": hall,
                    "data": raw_data
                }
            except ValueError as e:
                # 우리가 팩토리에서 만든 에러 처리가 여기서 빛을 발합니다.
                return {"success": False, "error": str(e)}
        스크린샷 2026-02-14 오후 1.02.37.png
      • SAC 스크래퍼 기능 구현
        pip install requests
        
        // app/scrapers/sac_scraper.py
        import requests
        import re
        from .base import BaseScraper
        
        class SACScraper(BaseScraper):
            def scrape(self):
                # 1. 예술의 전당 내부 데이터 API 주소
                url = "https://www.sac.or.kr/site/main/show/dataList"
                
                # 2. 파라미터 설정 (카테고리 000005가 '클래식'입니다)
                params = {
                    "CATEGORY_SECONDARY": "000005",
                    "pageSize": "10",
                    "cPage": "1"
                }
                
                # 3. 브라우저인 척 하기 위한 헤더 (없으면 거부당할 수 있어요!)
                headers = {
                    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
                    "X-Requested-With": "XMLHttpRequest"
                }
                print(f"SAC API 호출 중: {url}")
                response = requests.get(url, params=params, headers=headers)
                response.raise_for_status() # 에러 시 예외 발생
                
                raw_data = response.json()
                results = raw_data.get("paging", {}).get("result", [])
                
                # 4. 데이터 가공 (우리 입맛에 맞게)
                concerts = []
                for item in results:
                    concerts.append({
                        "title": item.get("PROGRAM_SUBJECT"),
                        "start_date": item.get("BEGIN_DATE", "").replace(".", "-"),
                        "end_date": item.get("END_DATE", "").replace(".", "-"),
                        "venue": item.get("CATEGORY_PRIMARY_NAME"),
                        "genre": "클래식"
                    })
                    
                return concerts
        스크린샷 2026-02-14 오후 1.05.51.png
  • AI Augmented Development 작업 방식 구체화
    • 주중
      • 반복구현
      • 백로그 최신화
    • 주말
      • 반복구현
      • 백로그 최신화
      • 반복구현 계획 수립
      • 백로그에 따른 업무 수행
        • 기능 개발
        • 시스템 개선
        • 방법론 변경

다음 작업

  • 백로그 생성하기

마무리

준비를 하기 위한 준비 끝!

profile
듣는 것을 좋아하는 개발자입니다

0개의 댓글