WEEK 24 · AI BRIEFING

JSON에서
AI 브리핑으로

업무 목록을 읽고, AI에 요청하고, 결과를 검증합니다. 사내 LLM으로 만드는 첫 브리핑 캐스터.

주소·키 없이도 demo로 시작하세요.
JSON 기반 · DB 설치 없음 · RPM·TPM과 토큰 사용량까지.
Cursor 실행 안내 · 실습 ZIP 다운로드

2026-10-26 · Cursor · Flask · 사내 LLM · Vercel · RPM · TPM

지난주에는 업무 목록을 인터넷 주소로 열었습니다. 이번에는 ‘🎙️ 오늘의 업무 브리핑 만들기’ 버튼을 추가합니다. JSON을 읽고, AI에 요청하고, 응답과 사용 토큰을 확인합니다. API 주소와 키를 아직 받지 않았어도 demo로 시작할 수 있습니다.

01 · 오늘 만들 앱

업무 담당자 상태
설문 응답 CSV 확인 민아 완료
인터뷰 일정 정리 준 대기
주간 리포트 초안 서연 대기

버튼을 누르면 다음과 같은 브리핑이 나타납니다. 아래는 예상 응답 예시이며 실제 AI 표현은 달라질 수 있습니다.

🎙️ 오늘의 업무 브리핑입니다! 전체 3건 중 설문 응답 CSV 확인이 완료됐습니다. 준님의 인터뷰 일정 정리와 서연님의 주간 리포트 초안이 대기 중입니다. 마감일 정보는 없어 업무 순서는 정하지 않았습니다.

단순 건수 계산은 Python으로도 충분합니다. 이번에는 익숙한 데이터로 AI 연결·요청·응답·검증 과정을 배웁니다. AI가 말한 업무명·담당자·완료 건수가 원본과 맞는지 직접 확인하세요.

DB는 사용하지 않습니다. sample-jobs.json은 코드와 함께 배포되는 읽기 전용 자료입니다. 업무를 바꾸려면 파일을 수정하고 다시 배포합니다. 브리핑은 화면에만 표시되며 새로고침하면 사라집니다. 업무 수정·사용자별 기록·영구 저장이 필요해질 때 외부 DB를 연결합니다.

02 · 배운 것과 연결하기

표시 기존 자료 이번 연결
복습 19주차 Worker와 API 입력을 처리하고 결과·실패를 구별하기
확장 20주차 인증과 인가 API 키와 실습용 접근 코드의 차이
복습 21주차 CSV·JSON·DB 고정 샘플 조회에는 JSON으로 충분
확장 22주차 저장 정책 무제한 저장뿐 아니라 무제한 AI 호출도 비용 문제
확장 23주차 Vercel 역할, 환경변수·재배포 Flask에서 사내 LLM을 호출하고 재배포
NEW 이번 주 요청 헤더·프롬프트·입출력 토큰·RPM·TPM·429

모델을 학습시키는 것은 데이터로 모델의 매개변수를 조정하는 과정입니다. 우리는 이미 학습된 모델을 호출해 결과를 생성합니다. 이번 호출로 모델 자체를 새로 학습시키는 것은 아닙니다. 머신러닝 역사와 학습 원리는 25주차에서 이어갑니다.

03 · AI는 어디에 연결할까?

브라우저 버튼 → Flask → JSON 읽기 → 사내 LLM 요청 → Flask → 브리핑 표시

위치 역할 보관하는 것
브라우저 버튼·로딩·결과 표시 실습용 접근 코드를 현재 화면 메모리에만 유지
Flask 가상 업무와 지시문을 묶어 요청, 오류 처리 서버 환경변수로 API 주소·키 사용
사내 LLM 게이트웨이 인증·허용된 모델 호출·정책 적용 실제 제한·집계 방식은 운영 안내 확인

API 키는 브라우저 JavaScript·HTML·GitHub에 넣지 않습니다. SUBSCRIPTION_KEY는 서버가 게이트웨이에 자신을 증명하는 값입니다. LAB_ACCESS_CODE는 실습 웹 화면에서 호출할 사람에게 강사가 알려주는 별도의 공유 코드입니다. 실제 사용자별 로그인이나 사용량 제한을 대신하지 않습니다.

요청의 구성

항목 이번 값과 의미
URL 추후 공유할 ENDPOINT를 PRIVATE_LLM_URL에 입력
메서드 POST: 생성 요청을 보냄
Ocp-Apim-Subscription-Key SUBSCRIPTION_KEY 값으로 게이트웨이 인증
anthropic-version 2023-06-01: 요청 API 버전
Content-Type application/json: 요청 본문이 JSON
model claude-sonnet-4-5-20250929: 제공받은 모델 식별자
messages user 메시지에 지시문과 가상 업무 자료 포함
max_tokens 출력 상한, 기본 256

프롬프트는 ‘한국어 업무 브리핑 캐스터처럼 짧게 설명하되 업무명·담당자·상태는 유지하고 없는 날짜·우선순위는 만들지 말라’고 요청합니다. JSON은 지시문이 아닌 자료로 구분합니다. 이런 지시도 정확성을 보장하지 않으므로 원본 비교가 필요합니다.

04 · RPM·TPM과 토큰 한도

토큰은 모델이 텍스트를 처리하는 단위입니다. 글자 수·단어 수와 항상 같지 않습니다. 요청 횟수 제한, 분당 처리량, 한 요청의 길이 제한은 서로 다릅니다.

항목 뜻 이번 실습
RPM Requests Per Minute, 분당 요청 수 짧은 요청도 여러 번 보내면 제한 가능
TPM Tokens Per Minute, 분당 토큰 처리량 요청 수가 적어도 긴 입력·출력으로 제한 가능
Input tokens 지시문·업무 데이터 등 입력 토큰 업무 세 줄 외에 프롬프트도 포함
Output tokens 모델이 생성한 출력 토큰 길게 말할수록 증가
max_tokens 한 요청의 출력 상한 256으로 설정, 반드시 256을 쓰는 것은 아님
컨텍스트 한도 한 요청에서 처리할 수 있는 문맥 한도 분당 처리량과 구별, 모델별 조건 확인

교육용 계산 예시: 한 요청에 입력 300 + 출력 150 = 450토큰을 쓴다면, 10회 사용한 합계는 4,500토큰입니다. 이것은 사내 운영 한도가 아닙니다. 실제 TPM은 입력·출력을 따로 집계하거나 출력 예약량·캐시를 반영할 수 있습니다. 공식 Claude API도 RPM·입력 TPM·출력 TPM을 구분하므로, 사내 게이트웨이의 집계 방식을 별도로 확인해야 합니다. 공식 제한 설명

실제 정책은 나중에 채우기

확인 항목 현재 상태
RPM / TPM 값 추후 공유
입력·출력 개별 토큰 상한 추후 공유
키별·사용자별·배포별 제한 범위 추후 공유
입력·출력 합산 여부, 시간 창, 캐시 집계 추후 공유
제한 초과 응답·재시도 헤더 실제 게이트웨이 확인 필요

화면은 응답의 usage.input_tokens, usage.output_tokens를 API 보고 값으로 보여줍니다. 없으면 ‘미제공’이며 0이나 추정값으로 바꾸지 않습니다. 캐시 관련 입력 토큰은 별도 필드일 수 있어 이 두 값만으로 청구 비용을 확정하지 않습니다. 응답과 사용량

stop_reason이 max_tokens이면 문장이 잘렸을 수 있다고 표시합니다. HTTP 200이어도 완전한 문장이나 정확한 사실을 보장하지 않습니다. 종료 사유 설명

05 · Cursor에서 먼저 실행하기

완성 예제 ZIP 다운로드 · README

Python 3.12 이상과 Cursor를 준비합니다. ZIP을 새 폴더에 풀고 app.py가 있는 briefing-lab 폴더를 Cursor에서 엽니다. 지난주 앱을 완료하지 않았어도 시작할 수 있습니다. 새 빈 폴더에서 직접 만들려면 아래 프롬프트와 완성 예제를 함께 참고합니다.

Cursor 프롬프트

복사해서 사용하기
Python 3.12와 Flask로 AI 업무 브리핑 캐스터를 만들어줘.
DB 없이 sample-jobs.json의 가상 업무 3건을 읽고 파일에는 쓰지 마.
목록 화면과 GET /api/jobs, GET /health, POST /api/summary를 만들어줘.
기본 LLM_MODE=demo에서는 현재 JSON으로 예제 브리핑을 만들고 실제 AI 호출이 아님을 표시해줘.
demo에서만 모의 429, 시간 초과, 출력 잘림을 선택해 체험하게 해줘.
live에서는 서버의 PRIVATE_LLM_URL에 POST하고 Ocp-Apim-Subscription-Key와
anthropic-version, Content-Type: application/json 헤더를 사용해줘.
모델은 PRIVATE_LLM_MODEL, API 버전은 ANTHROPIC_VERSION, 키는 SUBSCRIPTION_KEY에서 읽어줘.
messages의 user 내용에 지시문과 JSON 자료를 넣고 max_tokens는 기본 256으로 해줘.
브라우저로부터 프롬프트·주소·모델은 받지 말고 live 호출은 LAB_ACCESS_CODE를 검증해줘.
환경 파일은 .env_privatellm, 실제 파일은 Git·ZIP 제외, Vercel에서는 서버 환경변수로 설정해줘.
표준 Messages 텍스트 블록과 text/plain을 지원하고 사용량이 없으면 미제공으로 표시해줘.
출력 한도 종료는 잘림 안내, 429는 제한 안내와 유효한 Retry-After 대기 안내를 보여줘.
연결 5초·읽기 30초 타임아웃, 자동 재시도 없이 오류를 안전하게 표시해줘.
버튼 로딩·중복 클릭 방지·완료 후 5초 대기, 결과는 textContent로 표시해줘.
키·사내 주소·외부 원본 오류를 응답이나 로그에 노출하지 마.
sample_briefing.py와 Windows PowerShell README도 만들어줘.

터미널 실행

복사해서 사용하기
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe app.py

py가 없으면 python --version을 확인한 뒤 첫 명령의 py를 python으로 바꿉니다. 가상환경 활성화는 필요 없습니다. http://127.0.0.1:5000에서 목록과 demo 표시를 확인하고 버튼을 누릅니다. 종료는 Ctrl+C입니다. 포트가 사용 중이면 이전 실습 서버를 먼저 종료하세요.

터미널에서도 브리핑 듣기

새 터미널에서 아래 명령을 실행하면 텍스트 브리핑이 출력됩니다. 음성 합성은 하지 않습니다. demo에서는 외부 호출이 없고, live에서는 한 번의 실제 호출이 발생합니다.

복사해서 사용하기
.\.venv\Scripts\python.exe sample_briefing.py

이 도구는 서버 설정을 사용하는 로컬 실행 도구여서 웹의 LAB_ACCESS_CODE를 묻지 않습니다. URL과 키는 출력하지 않고 브리핑과 API 보고 사용량만 출력합니다.

06 · 주소와 키를 받으면 live로

실행 중인 서버를 종료하고 예제 환경 파일을 복사합니다. 기존 파일이 있으면 덮어쓰지 말고 Cursor에서 수정하세요.

복사해서 사용하기
if (-not (Test-Path -LiteralPath .env_privatellm)) {
    Copy-Item -LiteralPath .env_privatellm.example -Destination .env_privatellm
}
복사해서 사용하기
LLM_MODE=demo
PRIVATE_LLM_URL=
PRIVATE_LLM_MODEL=claude-sonnet-4-5-20250929
ANTHROPIC_VERSION=2023-06-01
SUBSCRIPTION_KEY=
LAB_ACCESS_CODE=
LLM_MAX_OUTPUT_TOKENS=256
  1. PRIVATE_LLM_URL에 공유받은 전체 HTTPS ENDPOINT를 넣습니다. 임의로 경로를 덧붙이지 않습니다.
  2. SUBSCRIPTION_KEY를 입력하고 LAB_ACCESS_CODE에는 API 키와 다른 추측하기 어려운 영문·숫자 코드를 정합니다.
  3. LLM_MODE를 live로 바꾸고 서버를 다시 실행합니다. 터미널 샘플 또는 웹 버튼으로 한 번 호출합니다.
  4. 브리핑과 업무 목록, 입력·출력 사용량을 비교합니다. 사용량이 없는 응답도 가능하며 실제 게이트웨이 형식을 확인해야 합니다.

실제 파일 .env_privatellm은 .env.* 패턴에 포함되지 않습니다. 제공한 .gitignore에는 별도 제외 규칙이 있습니다. GitHub에 올리기 전에 파일 목록을 확인하세요. 환경 파일은 기존 프로세스 환경변수를 덮어쓰지 않으므로, 예전에 터미널에서 설정한 값이 있으면 새 터미널에서 확인합니다.

07 · 실패와 제한을 안전하게 체험하기

demo 화면의 예제 선택에서 다음을 확인합니다. 실제 API에 반복 요청을 보내 한도를 소진하지 않습니다.

예제 확인할 결과
정상 브리핑 3건 중 1건 완료, 담당자별 남은 업무, 실제 호출 없음
429 요청·토큰 제한 제한 안내, 5초 대기, 자동 호출 없음
시간 초과 실패 안내, 수동 재시도 가능
출력 잘림 짧아진 결과와 잘림 안내, demo 토큰 수치 없음

live에서 잘못된 접근 코드는 사내 API를 호출하기 전에 거부합니다. 잘못된 사내 키·접근 권한은 별도 오류로 안내하고, 사내 주소·외부 원본 오류는 보여주지 않습니다. 429의 원인이 구체적으로 제공되지 않으면 RPM인지 TPM인지 단정하지 않습니다. 유효한 Retry-After의 초 또는 날짜는 대기 안내에 반영합니다.

요청 중에는 버튼을 비활성화하고 끝나면 최소 5초를 기다립니다. 이는 클릭 실수 방지이며 여러 사용자·탭의 호출량을 제한하는 서버 정책이 아닙니다. 공유 코드도 비용 상한 장치가 아닙니다. 실제 사용량과 조직의 제한을 확인하세요.

외부 호출은 연결 대기 5초·응답 읽기 대기 30초로 설정합니다. 이는 모든 네트워크 상황에서 총 실행 시간을 정확히 30초로 자르는 제한은 아닙니다. 화면은 45초 뒤 대기를 끝낼 수 있지만 이미 시작된 서버 호출까지 취소됐다는 뜻은 아닙니다. 즉시 반복 클릭하지 않습니다.

새로고침하면 결과가 사라지는지 확인합니다. JSON 상태를 수정하고 로컬 서버를 재실행하면 demo 브리핑도 바뀝니다. 배포 앱은 파일 수정 후 재배포해야 바뀝니다. 자동 저장이나 브리핑 기록은 없습니다.

08 · Vercel에서 실행하기

23주차 배포 절차를 복습합니다. briefing-lab만 별도 GitHub 저장소로 올리고 가져오면 기존 23주차 실습도 보존할 수 있습니다.

설정 값
Root Directory app.py가 있는 폴더
Framework Preset Flask 자동 감지 확인
Build / Output 기본값, 별도 override 없음
Python .python-version의 3.12
초기 LLM_MODE demo
함수 실행 설정 제공된 vercel.json의 app.py maxDuration=60

requirements.txt, llm_client.py, templates, sample-jobs.json이 함께 커밋됐는지 확인합니다. Vercel에서는 Python 앱을 실행하며 JSON은 배포 묶음에서 읽습니다. 이 앱은 실행 중 파일을 쓰지 않습니다.

먼저 demo로 배포해 휴대폰에서도 목록과 브리핑·오류 체험이 되는지 확인합니다. 사내 API의 Vercel 외부 접근이 허용되고 호출 정책이 확인된 경우에만 Settings → Environment Variables에 서버 변수들을 등록하고 live로 재배포합니다. 로컬 환경 파일을 업로드하지 않습니다. Preview에서 실제 호출을 원하지 않으면 live 설정을 Production에만 적용하세요.

사내망·VPN 전용 API면 Vercel demo + 로컬 live로 진행합니다. 제한을 우회하지 않습니다. 실습 종료 후 LLM_MODE를 demo로 바꿔 새 배포하거나 프로젝트를 삭제하세요. 새 배포가 생겨도 이전 배포 URL이 남을 수 있으므로 이전 live 배포도 삭제·보호하고 필요 시 실습용 키를 폐기합니다. 키의 폐기는 다른 사용자가 공유하는 키인지 운영 담당자와 확인합니다.

완료 체크

09 · 다음 주는 AI가 배우는 원리

우리는 이미 학습된 모델을 사용했습니다. 25주차에는 규칙 기반·머신러닝·딥러닝의 흐름과 학습·추론의 차이를 살펴봅니다. 모델이 왜 일반화에 실패할 수 있는지도 오늘의 결과 검증과 연결합니다. API 키 발급·충전을 추가로 요구하지 않습니다.

← 23주차 Vercel 배포 · 전체 학습 노트

사내 주소·키와 실제 제한값은 추후 제공됩니다. 예제는 모의 API로 검증하며 실제 사내 연결은 해당 값이 제공된 뒤 확인합니다. 공식 응답 형식 참고일: 2026-10-26. 사내 게이트웨이 정책은 공식 Claude API 정책과 다를 수 있습니다.