작업이 있는 곳에서 보고하세요.
HTTP API로 진척을 보내고, 공유 URL에서 바로 확인합니다. 수치형과 작업 목록형을 지원하며, 브라우저는 WebSocket으로 최신 상태를 받습니다.
대화형 API 문서 열기 ↗01. 빠른 시작
API 기본 주소: https://progress.parklab.work. 페이지 생성에는 인증이 필요하지 않습니다.
curl -X POST https://progress.parklab.work/api/v1/progress \
-H 'Content-Type: application/json' \
-d '{"title":"데이터셋 전처리","total":100000,"unit":"records","precision":6}'응답의 url은 공유 링크이고, write_token은 수정·삭제·보고용 비밀 토큰입니다. 토큰은 생성 시 한 번만 반환됩니다. 공개 메시지나 URL에 넣지 말고 안전하게 보관하세요. 서버에는 해시만 남습니다.
curl -X POST "https://progress.parklab.work/api/v1/progress/$ID/reports" \
-H "Authorization: Bearer $WRITE_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"completed":68421,"status":"running","message":"레코드 정규화 중"}'
02. 실행 가능한 Python 샘플
샘플에는 생성·재시작·진척 보고·리소스 측정·429 재시도·완료·실패 보고가 포함됩니다. HTTPX와 psutil을 사용하며, uv가 필요한 패키지를 준비합니다. 실제 처리 코드는 예제의 time.sleep(args.delay) 자리에 넣으세요.
# report.py를 내려받은 후 uv run report.py --mode numeric # 별도 체크리스트 페이지 (동일 IP 생성은 60초에 1개) uv run report.py --mode checklist --state .checklist-state.json # 같은 state 파일로 실행하면 기존 페이지를 이어서 사용합니다. # state 파일에는 쓰기 토큰이 있습니다. 버전 관리에 넣지 마세요.
Python 샘플 전체 코드 보기
코드를 불러오는 중입니다.
03. 더 작은 단위, 더 정밀한 진척
보고 주체는 작업을 충분히 세분화하세요. “준비 / 실행 / 완료” 세 단계만 보내기보다 레코드·파일·바이트·테스트 케이스처럼 실제로 측정할 수 있는 작은 단위를 사용합니다. 100,000개 레코드라면 total=100000과 실제 완료 건수를 보냅니다.
입력 작업량은 소수점 6자리까지, 퍼센트 표시 자릿수 precision은 0–6을 지원합니다. 퍼센트는 서버가 Decimal로 계산하고 문자열로 반환합니다. 아직 끝나지 않은 작업이 반올림으로 100%가 되지 않도록 내림 표시합니다. 작은 작업 단위와 잦은 HTTP 요청은 별개입니다. 내부 카운터는 자주 갱신하되 보고는 보통 1초에 한 번으로 묶으세요.
증분 +1 대신 누적 완료량을 전송합니다. 재시도해도 수치가 중복 증가하지 않습니다. 단, 보고 이력에는 재시도 요청도 남을 수 있습니다. 총량이 미정이면 total:null로 생성하고, 파악한 뒤 총량을 수정하세요. 이때는 임의의 퍼센트를 표시하지 않습니다.
04. 긴 프로젝트는 작업 목록으로
POST /api/v1/progress
{
"title": "프로젝트 구현", "mode": "checklist", "precision": 6,
"items": [
{"title": "설계", "weight": 1},
{"title": "API 구현", "total": 100, "weight": 5},
{"title": "검증 및 배포", "total": 20, "weight": 2}
]
}각 항목은 UUID를 가지며 title, status, completed, total, weight, message를 가집니다. 가중치는 항목 간 상대 작업량입니다. 전체 진척은 Σ(weight × completed / total) / Σ(weight) × 100입니다. 기본 가중치·총량은 1이므로 단순 체크리스트로도 사용할 수 있습니다.
PATCH /api/v1/progress/{id}/items/{item_id}
Authorization: Bearer YOUR_WRITE_TOKEN
{"completed": 42, "status": "running", "message": "라우트 42개 구현"}
# 항목 완료 시 completed가 total에 맞춰집니다.
{"status": "completed"}모든 항목이 완료되면 전체 상태도 완료됩니다. 페이지당 최대 1,000개 항목을 지원합니다. 더 큰 작업은 별도 페이지로 나눌 수 있습니다.
05. 실행 중 분모와 범위를 바꾸기
새 작업이 발견되면 분모를 늘려도 됩니다. 진척률이 내려가는 것은 실제 작업 범위 변경을 반영한 것입니다. 과거 보고에는 당시 분모와 퍼센트가 그대로 보존됩니다.
# 숫자형 총량 변경. completed보다 작은 total은 422.
PATCH /api/v1/progress/{id}
{"total": 150000, "message": "추가 데이터 발견"}
# 항목 추가 / 일부 수정 / 삭제
POST /api/v1/progress/{id}/items
PATCH /api/v1/progress/{id}/items/{item_id}
DELETE /api/v1/progress/{id}/items/{item_id}
# 전체 목록 교체: GET으로 최신 version 및 항목을 확인한 뒤 요청
PUT /api/v1/progress/{id}/items
{"expected_version": 12, "items": [ ...전체 항목 목록... ]}목록 교체 시 유지할 항목은 기존 id를 포함하세요. expected_version이 최신 버전과 다르면 409가 반환되어 다른 에이전트의 보고를 덮어쓰지 않습니다. 일반 보고와 항목 수정에서도 이 필드를 선택적으로 사용할 수 있습니다. 완료된 페이지에 미완료 작업을 추가하면 진행 중으로 돌아갑니다.
06. CPU · Memory · Disk
보고하는 에이전트 또는 스크립트의 호스트 자원을 보냅니다. 각 값은 선택 항목이며, 사용률 범위는 0–100입니다. 디스크는 측정한 마운트 지점의 사용량입니다.
POST /api/v1/progress/{id}/reports
{
"metrics": {
"cpu_percent": 42.8, "memory_percent": 61.2, "disk_percent": 28.4,
"memory_used_bytes": 5257039872, "memory_total_bytes": 8589934592,
"disk_used_bytes": 30500000000, "disk_total_bytes": 107374182400,
"measured_at": "2026-10-06T00:00:00+09:00"
}
}metrics를 생략하면 마지막 측정치를 유지하고, 객체를 보내면 전체 측정치를 교체합니다. null을 보내면 지웁니다. 측정 시각은 timezone을 포함해야 하며, 생략 시 서버 수신 시각을 사용합니다. 값이 없는 지표는 0% 대신 ‘미보고’로 표시됩니다.
07. 이력 및 CSV 다운로드
공유 페이지의 ‘보고 이력’ 탭은 최근 30개 보고를 WebSocket으로 받습니다. ‘전체 이력 CSV’ 버튼은 모든 보고를 내려받습니다.
GET /api/v1/progress/{id}/history.csv
GET /api/v1/progress/{id}/events?after=0&limit=100
# Python으로 CSV 파일 저장 (조회 토큰 불필요)
with httpx.stream("GET", f"{base}/api/v1/progress/{id}/history.csv") as response:
response.raise_for_status()
with open("history.csv", "wb") as file:
for chunk in response.iter_bytes():
file.write(chunk)CSV는 UTF-8 BOM을 포함합니다. sequence, kind, reported_at, version, title, mode, status, completed, total, unit, percent, message, items_done, item_count, 리소스 지표, measured_at, item_changes_json을 저장합니다. 목록형의 completed/total은 가중 작업량입니다. 빈 지표는 미보고를 뜻하며, 수식으로 해석될 수 있는 텍스트 앞에는 작은따옴표를 붙입니다. 이력 JSON은 next_cursor를 다음 요청의 after로 사용해 페이지를 넘깁니다. 이력 JSON과 WebSocket에서는 큰 목록 교체 내용을 항목 수로 요약하며, 전체 항목 변경 데이터는 CSV에 보존됩니다. CSV는 IP당 분당 10회까지 허용합니다.
08. WebSocket · 폴링 없음
const socket = new WebSocket(
`wss://progress.parklab.work/api/v1/progress/${id}/ws`
);
socket.onmessage = ({data}) => {
const event = JSON.parse(data);
if (event.type === "ping") socket.send("pong");
if (event.type === "snapshot") render(event.progress, event.events);
if (event.type === "deleted") socket.close();
};연결 즉시 최신 progress와 최근 events가 포함된 snapshot을 받고, 변경 때마다 새 snapshot을 받습니다. 느린 수신자는 중간 화면 업데이트를 건너뛸 수 있으나 모든 수락된 보고는 DB와 CSV에 남습니다. 서버가 약 20초마다 ping을 보내면 텍스트 pong으로 답합니다. 끊겼을 때 지수 백오프와 jitter로 재연결하면 최신 상태로 복구됩니다. 서버는 삭제 시 deleted, 종료 시 shutdown을 보낼 수 있습니다.
09. 인증과 요청 제한
- 조회: UUID4 URL을 아는 사람 누구나 페이지·API·WebSocket·CSV를 볼 수 있습니다. 공개 목록과 검색 인덱스는 제공하지 않습니다. 링크는 읽기 권한이므로 민감한 값을 메시지에 넣지 마세요.
- 생성: 인증 없이 IP당 최근 60초 동안 1개. 삭제해도 생성 제한이 초기화되지 않습니다.
- 보고·수정·삭제: 해당 페이지의 Bearer 쓰기 토큰 필수. IP당 최근 1초 동안 합계 5회. 같은 IP의 여러 작업이 제한을 공유합니다.
- 429: 응답의
Retry-After초만큼 기다린 뒤 재시도하세요. 프록시 헤더를 바꿔도 제한을 우회할 수 없습니다. - WebSocket: IP당 동시 10개, 서버 전체 256개, 연결 시도는 IP당 분당 30회. 공개 인터넷의 분산 공격까지 IP 제한만으로 막지는 않습니다.
- 상태: queued / running / paused / completed / failed / canceled. 숫자형 완료는 알려진 total과 completed가 같아야 합니다.
- 삭제: 페이지와 보고 이력이 함께 삭제됩니다. 삭제 전에 필요한 CSV를 내려받으세요.