CAPSTONE 6 / NEWSROOM LENS / 120 MIN

뉴스룸 렌즈, 4개 매체 관점 비교

RSS 수집 → 토픽 클러스터 → 매체별 프레이밍 비교, LLM이 아니면 못 만드는 화면

같은 사건도 뉴스룸마다 다르게 부릅니다. BBC, The Guardian, NHK World, 연합뉴스의 헤드라인을 주기 수집해 나란히 놓고, Bedrock이 공통 토픽을 묶어 매체별 프레임을 한국어로 비교합니다. 요약을 넘어 관점을 읽는 도구 - 이것이 LLM 고유의 화면입니다. 키 발급 없음, 마감은 CloudFront 실배포, 120분에 완결합니다.

소요 시간 120분 미션 5개 + DoD 산출물 공개 URL로 열리는 내 미디어 렌즈 Update 2026.08
MISSION BRIEFING

관점을 비교하는 법

숙지

빈 폴더에서 superpowers 워크플로로 설계하고 Phase 단위로 빌드합니다. 2시간 트랙이라 키 발급이 없고(4개 매체 공개 RSS), 마감은 CloudFront 실배포입니다. 소스는 영문 3개 + 한국어 1개지만, 화면의 토픽과 비교 브리핑은 전부 한국어입니다(원문 제목 병기).

레이어구성핵심 원칙
수집BBC / Guardian / NHK World / 연합뉴스 RSS를 120초 폴링소스별 실패 격리, 피드 하나가 죽어도 뉴스룸은 산다
저장기사 link 멱등 딕셔너리(소스별 50건)본문은 저장하지 않는다, 헤드라인 + 요약 + 링크만
렌즈공통 토픽 클러스터 + 매체별 프레임을 JSON 계약으로LLM 출력이 곧 화면 데이터, 계약이 무너지면 화면도 무너진다
개장CDK로 CF → prefix SG → ALB → FargateBearer는 Secrets 기동 주입, 이미지에 비밀 없음

1. 뉴스룸 (기본 뷰)

기능설명
4열 그리드매체별 최신 헤드라인 카드, 원문 링크 새 탭, 상대 시각("12분 전")
소스 상태 바매체별 마지막 수집 시각과 건수, 실패 시 경고 배지
듀얼 테마시스템 기본 + 토글 + localStorage

2. 렌즈 (이 캡스톤의 심장)

기능설명
토픽 클러스터2개 이상 매체가 다룬 공통 토픽 3~5개, 공통 사실 요약
프레임 비교토픽마다 4개 매체의 프레임을 나란히, 미보도는 회색 - 침묵도 관점이다
근거 링크모든 프레임 칩에 원문 기사 링크, 출처 없는 주장 없음
렌즈 캐시같은 10분 버킷 동안 재사용
L학습 목표, Level 200

이 캡스톤을 마치면 다음 네 가지를 설명할 수 있고, 다시 만들 수 있습니다.

목표검증되는 순간
이질적 소스를 하나의 스키마로 정규화하는 법M2에서 4개 피드가 같은 모양의 JSON으로 나란히 설 때
LLM 출력에 JSON 계약을 거는 법M4에서 클러스터 응답이 파싱 한 번에 화면 데이터가 될 때
요약을 넘어 관점 비교를 시키는 프롬프트 설계같은 토픽의 매체별 프레임이 실제로 다르게 읽힐 때
컨테이너 앱을 CF → ALB → Fargate로 개장하는 법내 CloudFront URL이 다른 사람 브라우저에서 열릴 때
R챕터 연결 지도, 배운 내용이 재등장하는 곳
Ch1 설치부터 Headless까지M0~전체: 세션 운용, 지시 → 실행 → 검증 루프
Ch2 SubagentsM2~M3: 수집기 리뷰를 code-reviewer에게, 그리드와 상태 바 병행
Ch3 Admin SetupM4: Bearer 자격과 Secrets 주입이 도는 통제선의 배경
Ch4 Settings, 훅과 스킬OPT: 하네스 성숙화, 훅과 스킬의 프로젝트 자산화
Ch5 CLI Reference확장 방향: 아침 렌즈를 헤드리스로 뽑아 Slack에 배달하는 파이프라인
Ch6 Agent SDK확장 방향: 렌즈 생성을 코드에서 부르는 상주 미디어 데스크
규칙, 캡스톤 공통 ① 코드와 파일 구성을 직접하지 않고, Claude에게 지시해서 만듭니다 ② 각 Phase의 DoD를 통과해야 다음으로 ③ 막히면 "막힐 때 열어보기"의 힌트를 씁니다. 다른 참가자와의 의존성은 없습니다.
BLUEPRINT

구현 청사진

참고

M1 설계가 이 구조로 수렴하도록 방향을 잡아 주는 구현 지도입니다.

0세 개의 경로 한 눈에
수집 루프, 조회 경로, 렌즈 경로
[수집 루프]  120초마다, 소스별 격리
Scheduler ──> Collector: BBC / Guardian / NHK / 연합 RSS ──> 정규화(source, title, link, published, summary)
                                │ (한 피드 실패는 그 피드만)              │
                                +── 소스 상태 기록          Store <── link 멱등 upsert ──+

[조회 경로]  브라우저가 당길 때
Browser ── fetch ──> FastAPI: /api/articles ──> 4열 그리드 + 소스 상태 바

[렌즈 경로]  버튼 눌렀을 때만, 이 캡스톤의 심장
FastAPI ── 4소스 헤드라인 묶음 ──> httpx POST converse(Bearer) ──> JSON만:
   clusters[{topic, summary, frames{bbc/guardian/nhk/yna}, sources}] + overview
   │
   +── 10분 버킷 캐시 ──> 클러스터 뷰(프레임 나란히, 미보도 회색, 근거 링크)
1소스 계약 (2026.08 확인 기준)
매체언어피드비고
BBC World영어feeds.bbci.co.uk의 world 편 RSS공식 제공, 안정
The Guardian World영어theguardian.com/world/rss섹션 URL + /rss 관례, 공식
NHK World영어www3.nhk.or.jp 영문 뉴스 RSS일본 관점의 영문 발신
연합뉴스 국제한국어yna.co.kr 국제 섹션 RSS유일한 한국어 소스

참고: Reuters는 공식 RSS를 2020년에 중단해 소스에서 제외했습니다. 피드 URL은 변할 수 있는 값이라 구현 시 각 사 RSS 허브에서 확인해 config에 확인일과 함께 기록하는 것이 M2의 첫 작업입니다 - 상류 계약을 문서화하는 습관 자체가 학습입니다.

2렌즈 JSON 계약 (LLM 출력 = 화면 데이터)
POST /api/lens 응답 형태
{
  "clusters": [
    {
      "topic": "한국어 토픽명",
      "summary": "매체들이 공통으로 전하는 사실, 2문장",
      "frames": {
        "bbc": "이 매체가 무엇을 앞세우는지 1문장",
        "guardian": "...", "nhk": "...", "yna": "미보도"
      },
      "sources": { "bbc": [0, 3], "guardian": [1], "nhk": [2], "yna": [] }
    }
  ],
  "overview": "오늘의 미디어 지형, 3문장"
}
3기술 선택 4
선택이유
link 멱등 + 본문 미저장중복 없는 스토어와 출처 존중을 한 번에, 우리는 렌즈지 아카이브가 아니다
소스별 실패 격리RSS는 언제든 한 곳이 느려진다, 4분의 1의 장애가 4분의 4가 되면 안 된다
JSON 전용 LLM 계약자유 산문은 사람용, 화면용 출력은 스키마 - 파싱 가능성이 곧 신뢰성
CF → ALB → Fargate 개장 형식prefix list SG와 X-Origin-Verify 이중 방어를 갖춘, 공개 URL까지 가는 최단 경로
MISSION 00

사전 준비

5분

이 트랙은 외부 키 발급이 없습니다. Bedrock Bearer와 AWS 자격만 확인하면 출발입니다.

Terminal
mkdir -p ~/capstone/capstone-6 && cd ~/capstone/capstone-6
set -a; source ~/capstone/.env; set +a
python3 -c "import os; print('Bearer:', 'OK' if os.environ.get('AWS_BEARER_TOKEN_BEDROCK') else 'MISSING')"
aws sts get-caller-identity --query Account --output text
CHECKPOINT
MISSION 01

설계, 브레인스토밍

15분

소스 4개, 정규화, JSON 렌즈 계약, 배포까지 요구 9조항으로 넘깁니다.

이 미션의 바탕 학습: Ch1의 세션 운용과 Capstone Setup의 superpowers 워크플로.

Terminal (~/capstone/capstone-6)
claude
Claude 세션 입력, 전체 복사
/superpowers:brainstorming 다음 요구사항으로 "Newsroom Lens", 4개 매체의 관점 비교 뉴스룸을 설계하자.
1) 구조: backend/(Python 3.11+ FastAPI, app/collector 수집, app/store, app/api, app/llm, config.py)
   + frontend/index.html(빌드 없는 정적 SPA 한 장). FastAPI가 정적 파일을 함께 서빙해 :8000 완결.
   Dockerfile 한 장
2) 소스 4개(전부 공개 RSS, 키 불요), config.py 상수로:
   BBC World, The Guardian World, NHK World(영문), 연합뉴스 국제 - 각 항목은 {id, 이름, 언어, rss_url}.
   피드 URL은 구현 시점에 각 사 공식 RSS 허브에서 확인해 채운다(하드코딩하되 주석으로 확인일 기록)
3) 수집기: feedparser로 4개 피드를 120초 주기 수집, 소스별 최신 15건을
   {source, title, link, published(UTC ISO), summary(HTML 태그 제거, 300자 절단)}로 정규화.
   피드 하나가 실패해도 나머지는 계속(소스별 실패 격리), 마지막 성공 시각을 소스별로 기록
4) 스토어: link를 멱등 키로 하는 인메모리 딕셔너리(소스별 최대 50건). 같은 기사는 published만 갱신
5) API 계약: GET /healthz, GET /api/articles(소스별 최신 목록 + 소스 상태),
   POST /api/lens (아래 6, 같은 10분 버킷 캐시)
6) 렌즈(LLM, 이 캡스톤의 심장): Bedrock Converse를 SDK 없이 httpx 직접 REST로.
   POST https://bedrock-runtime.ap-northeast-2.amazonaws.com/model/global.anthropic.claude-sonnet-4-6/converse
   Authorization: Bearer(환경변수 AWS_BEARER_TOKEN_BEDROCK), maxTokens 1500.
   입력은 4개 소스의 최신 헤드라인+요약 묶음. 출력은 반드시 JSON만:
   {"clusters":[{"topic":"한국어 토픽명","summary":"공통 사실 2문장",
     "frames":{"bbc":"이 매체의 프레임 1문장","guardian":"...","nhk":"...","yna":"..."},
     "sources":{"bbc":[기사 인덱스],...}}], "overview":"오늘의 미디어 지형 3문장"}
   클러스터는 2개 이상 매체가 다룬 공통 토픽만 3~5개. 다루지 않은 매체의 frame은 "미보도".
   모든 생성 텍스트는 한국어, 기사 제목 원문은 화면에서 병기
7) 화면(텍스트 스펙): 라이트/다크 듀얼 테마. 상단 소스 상태 바(4개 매체, 마지막 수집, 건수).
   기본 뷰는 4열 카드 그리드(매체별 최신 헤드라인, 원문 링크 새 탭, 상대 시각).
   "렌즈" 버튼 → 클러스터 뷰: 토픽 카드마다 공통 요약 + 4개 매체 프레임을 나란히,
   미보도는 회색 처리, 근거 기사 링크 칩. 뷰 전환 토글
8) 키와 윤리: Bearer는 환경변수로만. 기사 본문을 저장하지 않는다(헤드라인+요약+링크만),
   화면 모든 카드에 원문 출처 링크 필수
9) 배포와 순서: CDK로 CloudFront → (prefix list SG + X-Origin-Verify) ALB → Fargate 를 구성,
   Secrets 기동 주입. Phase 1(수집 + 스토어 + /api/articles) → Phase 2(4열 그리드)
   → Phase 3(렌즈 JSON + 클러스터 뷰) → Phase 4(cdk deploy 개장). 2시간 제약: 테스트 생략,
   curl과 브라우저로 검증. 결정이 필요하면 이 범위 안에서 최소한으로만 물어봐.
자동화 옵션, auto mode 세션에 auto mode on을 선언해 두면 superpowers가 brainstorming → write-plan → execute-plan의 단계 전환과 승인 대기를 자동으로 이어 갑니다. 시간이 빠듯할 때 유용합니다. 되돌리려면 auto mode off입니다.

/superpowers:write-plan으로 Phase 4개 계획을 승인하고, 위 구현 청사진과 대조하세요.

CHECKPOINT
MISSION 02

Phase 1, 수집기와 스토어

30분

4개 피드가 같은 모양으로 정규화되어 쌓이고, 한 피드가 죽어도 나머지가 살면 끝입니다.

이 미션의 바탕 학습: Ch1의 지시 → 실행 → 검증 루프. 여유가 있다면 Ch2의 code-reviewer에게 정규화 로직 리뷰를 맡겨 보세요.

2시간의 열쇠, 인프라 선배포 cdk deploy는 첫 회 12~15분이 걸립니다. Phase 1을 시작하자마자 별도 터미널에서 인프라 배포를 먼저 걸어 두세요. 빌드와 배포 대기가 겹치면 M4는 이미지 푸시와 서비스 갱신만 남아 10분 안에 개장합니다.
Terminal 2, 인프라 선배포 (백그라운드)
cd ~/capstone/capstone-6 && npx aws-cdk@2 deploy --require-approval never   # Claude가 infra를 만든 직후 실행
Claude 세션 입력
/superpowers:execute-plan Phase 1만 구현하고 멈춰줘. 시작 전에 4개 피드 URL을 각 사 공식 RSS 허브에서 확인해 config.py에 확인일 주석과 함께 기록. backend venv + requirements(fastapi, uvicorn, httpx, feedparser, apscheduler), 소스별 격리 수집기(120초), link 멱등 스토어(소스별 50건), /api/articles(목록 + 소스 상태)와 /healthz, Dockerfile과 infra 골격까지. uvicorn과 curl 검증 방법 포함.
Terminal, 스모크
cd backend && .venv/bin/uvicorn app.main:app --port 8000 &
sleep 8
curl -s localhost:8000/api/articles | head -c 500; echo
개념 짚기 (Level 200), 정규화가 비교를 만든다 BBC와 연합뉴스의 RSS는 필드도, 날짜 형식도, 인코딩 습관도 다릅니다. 4개 피드를 {source, title, link, published, summary} 한 가지 모양으로 다듬는 순간에야 "나란히 놓기"가 가능해지고, 렌즈 프롬프트도 단순해집니다. 통합의 8할은 정규화입니다 - 그리고 summary의 HTML 태그 제거와 절단은 프롬프트 토큰 예산을 지키는 실무 규율입니다.
DEFINITION OF DONE
MISSION 03

Phase 2, 뉴스룸 그리드

30분

4열 그리드에 세계의 지금이 나란히 뜨면, 비교의 무대가 완성됩니다.

이 미션의 바탕 학습: Ch2의 병렬 감각. 그리드를 만드는 동안 소스 상태 바를 서브에이전트로 병행할 수 있습니다.

Claude 세션 입력
/superpowers:execute-plan Phase 2를 구현해줘. frontend/index.html 정적 SPA 한 장: 요구 7의 기본 뷰(듀얼 테마, 소스 상태 바, 4열 카드 그리드 - 매체명 헤더, 헤드라인, 상대 시각, 원문 새 탭 링크). 모바일에서는 2열로 접히게. FastAPI 정적 서빙 mount까지.
Terminal, 미리보기
# 브라우저에서 /proxy/8000/ 열기, 4개 매체의 지금이 나란히 선다
이 미션의 3대 함정 ① 한글이 깨진다 = 응답 인코딩을 feedparser에 맡기고, 화면은 UTF-8 meta를 확인하세요. ② 요약에 태그 조각이 보인다 = summary가 HTML입니다, 정규화에서 태그 제거가 빠진 것. ③ 시각이 뒤죽박죽 = published 포맷이 소스마다 다릅니다, 정규화에서 UTC ISO로 통일했는지 확인하세요.
DEFINITION OF DONE
MISSION 04

Phase 3 + 4, 렌즈와 개장

40분

LLM의 JSON이 그대로 화면이 되고, 내 CloudFront URL이 열리면 미션 완료입니다.

이 미션의 바탕 학습: Ch3에서 본 Bedrock 자격과 Secrets 주입의 배경, 그 위에서 도는 REST 계약.

Claude 세션 입력, 렌즈
/superpowers:execute-plan Phase 3(렌즈)을 구현해줘. llm 모듈: httpx POST converse(Bearer, maxTokens 1500, 타임아웃 504/파싱 502), 시스템 프롬프트에 요구 6의 JSON 스키마와 "JSON 외 출력 금지, 코드펜스 금지"를 명시, 응답은 json.loads 전에 백틱/여백 방어적 제거. POST /api/lens(10분 버킷 캐시). 화면 렌즈 뷰: 토픽 카드에 공통 요약 + 4개 프레임 나란히, 미보도 회색, sources 인덱스로 근거 기사 링크 칩, 뷰 전환 토글.
Terminal, 렌즈 스모크
curl -s -X POST localhost:8000/api/lens | head -c 400; echo
Claude 세션 입력, 개장
/superpowers:execute-plan Phase 4(개장)를 진행해줘. 선배포한 인프라에 앱 이미지를 빌드/푸시하고 서비스 갱신, CloudFront 도메인 출력. X-Origin-Verify와 Secrets 주입 확인 절차 포함.
개념 짚기 (Level 200), 관점을 묻는 프롬프트 "요약해줘"는 아무 모델이나 합니다. 이 캡스톤의 프롬프트는 세 가지가 다릅니다: ① 비교 지시 - "각 매체가 무엇을 앞세우고 무엇을 생략하는지"를 명시적으로 묻고, ② 침묵의 처리 - 다루지 않은 매체를 "미보도"로 표기하게 해 부재 자체를 정보로 만들며, ③ JSON 계약 - 출력이 화면 데이터이므로 스키마 밖 산문을 금지합니다. 그리고 근거 인덱스(sources)를 요구하는 순간, 렌즈는 주장이 아니라 링크로 검증 가능한 화면이 됩니다.
렌즈나 개장이 막힐 때 ① JSON 파싱 실패 = 응답 앞뒤의 코드펜스가 남은 것, 방어적 제거를 확인하세요. ② 클러스터가 1개뿐 = 정상일 수 있습니다, 조용한 뉴스 시간대엔 공통 토픽이 적습니다. ③ ALB 직접 접근 403 = 정상(이중 방어), ④ 브리핑만 실패 = 태스크 정의의 secrets 블록에서 Bearer 주입 확인.
DEFINITION OF DONE
BONUS

렌즈 퀄리티 강화 라운드, 시선을 벼려라

+α 자유

렌즈가 열렸다면 이제 렌즈를 내 것으로 만드는 시간입니다. 강화 카드 중 끌리는 것을 골라 하나씩 주문하세요. 요령은 같습니다: 한 번에 하나, 화면으로 확인하고, 마음에 들면 커밋과 재배포.

A강화 카드 1, 다섯 번째 시선
Claude 세션 입력
Al Jazeera English를 다섯 번째 소스로 추가하자. config에 피드를 등록하면
수집기, 스토어, 그리드(5열), 렌즈 프롬프트와 frames 스키마까지 자동으로 확장되는지가
이 카드의 진짜 시험이다. 하드코딩이 남아 있으면 이 기회에 소스 목록 주도로 리팩터.

추가 소스 후보 메뉴판 (한국 / 미국, 2026.08 기준 - NPR와 NYT는 웹 확인, 나머지는 등록 시 각 사 허브에서 피드 URL을 확인해 config에 확인일을 남기세요)

국가매체피드 허브비고
한국KBS 뉴스news.kbs.co.kr RSS공영 기준선, 안정
한국한겨레hani.co.kr RSS공식 제공 오래 유지
한국경향신문khan.co.kr RSS섹션별 제공
한국조선일보chosun.com RSS섹션별 제공
한국SBS 뉴스news.sbs.co.kr RSS방송사 중 충실
한국매일경제 / 한국경제mk.co.kr, hankyung.com RSS경제 섹션 렌즈용
미국NPRfeeds.npr.org미국 매체 중 RSS 지원 최상급
미국NYTrss.nytimes.com헤드라인 + 요약 무료, 렌즈는 본문 미저장이라 충분
미국Fox Newsfeeds.foxnews.com공식 제공
미국Washington Postfeeds.washingtonpost.com제공, 개편 잦은 편

참고: AP는 공식 RSS 미제공, CNN 피드는 레거시라 후순위입니다. 렌즈는 프레이밍 비교가 심장이므로 관점의 거리가 있는 짝(예: NPR + Fox, 국내라면 KBS + 한겨레 + 조선)일수록 화면이 살아납니다.

B강화 카드 2, 키워드 추적
Claude 세션 입력
관심 키워드 추적을 추가하자. 헤더의 입력창에 키워드(예: AI, 반도체)를 핀하면
그리드에서 매칭 헤드라인이 하이라이트되고, "이 키워드만" 필터 토글이 생긴다.
핀 목록은 localStorage에, 매칭은 대소문자 무시.
C강화 카드 3, 어조 온도계
Claude 세션 입력
렌즈 응답에 어조 온도를 더하자. 각 프레임에 tone 필드(-2 차분 ~ +2 격앙)를 JSON 계약에 추가하고,
화면은 프레임 옆에 작은 온도 바로 표시. 같은 사건에 대한 온도 차가 한눈에 보이면
프레이밍이라는 개념이 몸에 들어온다. 프롬프트에 "근거 문구 없이 극단값 금지"를 명시.
D강화 카드 4, 아침 렌즈 배달
Claude 세션 입력
렌즈를 텍스트로 내보내자. "복사용 브리핑" 버튼 → overview와 클러스터를
Slack에 붙여넣기 좋은 플레인 텍스트(토픽별 3줄 + 링크)로 만들어 클립보드에 복사.
매일 아침 팀 채널에 배달하는 내 미디어 브리핑의 원형이다.
E강화 카드 5, 나만의 렌즈로

여기부터는 정해진 카드가 없습니다. 당신이 편집장입니다. 뉴스룸을 보며 궁금했던 것 하나를 골라, 위 카드들처럼 직접 요구사항을 써서 주문하세요. 아이디어가 필요하면: 테크 섹션 전용 렌즈, 시간대별 헤드라인 변화, 매체별 다룬 지역 지도, 토픽 히스토리(오전 vs 오후), 읽음 표시, DynamoDB로 스토어 승격(재배포와 다중 태스크에도 기사 이력이 유지되고, 토픽 히스토리 카드의 토대가 됩니다).

Claude 세션 입력, 빈칸을 내 아이디어로
내 렌즈에 [내가 원하는 기능]을 추가하자. 규칙:
1) 데이터: [필요한 필드, 새 소스라면 공식 RSS 확인]
2) 화면: [어디에 어떻게 보이는지]
3) 계약: 본문 미저장과 원문 링크 필수 원칙, JSON 스키마 호환은 깨지 않는다
4) 배포: 완성되면 재배포까지
구현 전에 이 규칙을 네 계획으로 다시 말해주고, 승인하면 진행해.
강화 라운드의 요령 ① 카드 하나 = 커밋 하나, 되돌아갈 지점을 만들며 갑니다. ② 화면으로 확인하고 다른 점을 말로 다듬으세요. ③ 마지막엔 재배포로 Slack의 내 URL을 최신으로.
BONUS DONE, 진행률 미집계
OPTION

하네스 엔지니어링

+15분

완주한 프로젝트를 표준 하네스로 성숙시킵니다 (project-init으로 구조를 잡고 harness-eval로 6개 차원 등급을 받습니다).

이 미션의 바탕 학습: Ch4의 훅과 스킬을 팀 자산으로 승격하는 감각, 그리고 Reference 3의 플러그인 생태계.

Claude 세션 입력
/project-init:init-project .
Claude 세션 입력, 이어서
/harness-eval:quick

등급표에서 낮은 차원 하나를 골라 /add-adr 또는 /add-runbook으로 보강하고 재평가해 보세요.

OPTION DONE, 진행률 미집계

미션 종료

소스는 정규화로 나란히, 출력은 JSON 계약으로, 침묵은 미보도로. 요약을 넘어 관점을 읽었습니다.

가져가는 것내용
정규화의 힘이질적 소스 통합의 8할은 한 가지 모양으로 다듬는 일이다
LLM JSON 계약화면용 출력은 스키마로 계약한다, 파싱 가능성이 곧 신뢰성
프레이밍 프롬프트비교 지시, 침묵의 처리, 근거 링크 - LLM 고유 화면의 설계 문법
NEXT

포털로

워크샵 포털에서 다음 미션을 고르세요.