C.W.K.
Stream
Lesson 02 of 06 · published

curl — 거짓말 안 하는 진짜 도구

~10 min · production, curl, debugging

Level 0HTTP Newbie
0 XP0/46 lessons0/12 achievements
0/120 XP to next level120 XP to go0% complete
"curl 이 모든 Mac, 모든 Linux 박스, 모든 container 이미지에. HTTP 모든 버전 말함. 라이브러리가 숨기는 거 보여줌. API 호출 이상하게 굴면 curl 이 첫 수 — 마지막 아님."

매일 쓰는 flag

Flag 한 줌이 debugging 90% 커버:

  • -v — verbose. Request 줄 (>), response 줄 (<), curl 의 연결/TLS 부연설명 (*) 보여줌. 첫 debugging 수.
  • -i — 출력에 response header 포함. Header 만; 연결 chatter 아님.
  • -I (대문자) — HEAD request 만. Body download 없이 header 받기.
  • -X METHOD — 이 HTTP method 써. -X POST, -X DELETE 등.
  • -H 'Name: value' — request header 추가. 여러 개 위해 반복 가능.
  • -d 'body' — body 보냄. -d @file.json 가 파일에서 읽음. POST 묵시.
  • --data-binary @file — 파일 byte 글자 그대로 보냄, line-ending 변환 없음. Binary upload 에 써.
  • -u user:pass — HTTP Basic auth (-H 'Authorization: Basic ...' 단축).
  • -N — curl 자체 출력 buffering 없음. SSE / streaming 에 필수.
  • --compressed — gzip/br 요청과 decompress. 압축 vs 미압축 크기 비교 가능.
  • -L — redirect 자동 follow. 없으면 3xx response 보고 멈춤.
  • -o file / -O — body 를 파일에 씀 (이름 붙음 혹은 URL 에서).
  • -w '%{http_code}\n' — response 후 specific 전송 정보 (status code, 크기, 시간) print.

X-ray 수

curl -v 가 canonical "왜 안 동작" 도구:

# 보낸 모든 byte 와 받은 모든 byte 봐
curl -v -X POST https://api.example.com/users \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer abc.def.ghi' \
  -d '{"name":"Pippa"}'

# 출력 shape:
# *   Trying 1.2.3.4:443...               (TCP connect)
# * TLSv1.3 (OUT), TLS handshake, ...    (TLS handshake)
# > POST /users HTTP/1.1                  (request 줄)
# > Host: api.example.com                 (request header)
# > Authorization: Bearer abc.def.ghi     (request header)
# > Content-Type: application/json        (request header)
# > Content-Length: 17                    (request header)
# >
# > {"name":"Pippa"}                       (request body)
# < HTTP/1.1 201 Created                  (status 줄)
# < Location: /users/u_abc                 (response header)
# < Content-Type: application/json         (response header)
# < {"id":"u_abc","name":"Pippa"}          (response body)

Wire 위 정확히 뭐 일어났는지 와 정확히 뭐 돌아왔는지 봄. 라이브러리 마법 없음, framework 추상화 없음. "내 httpx 호출이 401 돌려주는데 curl 가 200" 미스터리 절반이 verbose 출력 비교하면 사라짐.

라이브러리 호출 이상하게 굴면 request 를 curl 에 먼저 복사. Curl 가 동작하는데 라이브러리 안 되면, 버그가 라이브러리가 API 호출 방식에 — API 자체 아님. Curl 도 실패하면 API 잘못 (혹은 네 이해 잘못). 분리가 어디 봐야 할지 알려줌.

Power 조합

Timing 분해 — DNS / TCP / TLS / response phase 따로 봐:

curl -w 'dns=%{time_namelookup}s connect=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n' -o /dev/null -s https://api.example.com/

Buffering 없는 SSE stream:

curl -N -H 'Accept: text/event-stream' https://api.example.com/stream

Rate limiting 테스트 — endpoint 100 번 두드림, status 셈:

for i in {1..100}; do
  curl -s -o /dev/null -w '%{http_code}\n' https://api.example.com/
done | sort | uniq -c

브라우저 fetch 재현 — Chrome DevTools Network 패널이 "Copy as cURL" 있음 — 터미널에 바로 붙여넣고 로컬에서 버그 재현.

cwkPippa 의 curl 사용

cwkPippa WebUI 가 hang 하거나 500 돌려주면 첫 수가 backend 에 대한 curl: curl -v http://localhost:8000/api/conversations/{id}. Backend 죽은지 (connection refused), CORS 차단 (브라우저 콘솔만 — curl 가 CORS 안 봄), auth 실패 (401), 실제 content 이슈 (200 + 나쁜 body) 인지 드러냄. Chrome DevTools 에서 Copy-as-cURL 도 셀 수 없이 — 도구 있는 터미널에서 브라우저 전용 버그 재현 위해.

Code

매일 curl 레시피 — copy/paste 준비됨·bash
# 매일 curl 레시피 — copy/paste

# 단일 request X-ray (canonical debug 수)
curl -v https://api.example.com/users/42

# Auth 가진 JSON POST
curl -X POST https://api.example.com/users \
  -H 'Authorization: Bearer abc' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Pippa"}'

# 파일을 body 로 POST (binary-safe)
curl -X POST https://api.example.com/upload \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @./image.png

# HEAD — header 빨리, body 없음
curl -I https://api.example.com/users/42

# Header 만 (curl chatter 없음)
curl -i https://api.example.com/users/42

# Redirect follow + 일어나는 거 봐
curl -L -v https://example.com/short-url

# 출력 buffering 없는 SSE stream
curl -N -H 'Accept: text/event-stream' https://api.example.com/stream
Power 조합: timing 분해 + status 분포·bash
# Timing 분해 — 시간 어디로 가는지 봐
curl -w '\ndns=%{time_namelookup}\nconnect=%{time_connect}\ntls=%{time_appconnect}\nttfb=%{time_starttransfer}\ntotal=%{time_total}\n' \
  -o /dev/null -s https://api.example.com/
# 출력:
# dns=0.005    (DNS lookup)
# connect=0.045  (TCP handshake — RTT 의존)
# tls=0.120    (TLS handshake)
# ttfb=0.180   (time-to-first-byte — server 처리)
# total=0.190  (full body 받음)

# Hammer 테스트 — 100 request, status code 분포
for i in {1..100}; do
  curl -s -o /dev/null -w '%{http_code}\n' https://api.example.com/
done | sort | uniq -c
# 출력 (예): 92 200, 8 429 (rate limit 발동)
Copy as cURL — 터미널에서 어느 브라우저 request 재현·bash
# Chrome DevTools → 터미널
# 1. Chrome DevTools 열기 (Mac 에서 Cmd+Option+I)
# 2. Network 탭
# 3. Request 우클릭 → Copy → Copy as cURL
# 4. 터미널에 붙여넣기
#
# 결과: 브라우저가 보낸 정확한 request, 모든 header, cookie, body,
# timing 포함. Curl, grep, jq, 전체 toolkit 있는 command line 에서
# 브라우저 전용 버그 재현.

# 붙여넣어진 결과 예:
curl 'https://api.example.com/api/me' \
  -H 'authority: api.example.com' \
  -H 'accept: application/json' \
  -H 'cookie: session=abc123' \
  -H 'user-agent: Mozilla/5.0 ...' \
  --compressed

External links

Exercise

라이브러리 호출 통해 최근 debug 한 HTTP 버그 하나 골라. curl -v 로 재현. Curl 가 보낸/받은 거 vs 라이브러리 보고가 보냈/받았다 한 거 비교. Gap (누락 header, 잘못된 method, body format 등) 식별. 그 다음 라이브러리 호출을 curl 의 동작 버전과 매칭하도록 fix. 보너스: 느린 API 호출에 시간이 어디로 가는지 (DNS / TCP / TLS / server 처리) 측정에 curl -w 써서 가장 느린 phase 식별.
Hint
라이브러리-vs-curl gap 이 보통 누락이나 잘못된 header — auth, content-type, accept, 혹은 API 기대하는 custom header. 일부 라이브러리가 원하지 않는 기본 조용히 추가 (httpx 가 기본 Accept-Encoding 추가; 일부 framework 가 User-Agent string 추가); 일부가 원하는 기본 생략. Curl X-ray 가 둘 다 보이게.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.