ToolPal
커맨드라인 HTTP 요청을 보여주는 터미널

cURL 완벽 가이드: 플래그 외우는 거 그만하고 명령어 바로 만들기

📷 Pexels / Pexels

cURL 완벽 가이드: 플래그 외우는 거 그만하고 명령어 바로 만들기

cURL은 모든 개발자가 사용하지만 완전히 이해하는 사람은 드문 도구입니다. 모든 플래그를 외우지 않고도 cURL 명령어를 만드는 실용적인 가이드입니다.

2026년 3월 28일9분 소요

개발자로 몇 달 이상 일했다면 cURL을 사용해봤을 것입니다. 그리고 아마 "curl post request json" 같은 검색을 원하는 것보다 훨씬 많이 해봤을 겁니다. 부끄러운 일이 아닙니다 — cURL은 플래그가 많고, 문법이 꽤 촘촘해서 경험 많은 개발자들도 전부 외워두지는 않습니다.

대부분의 개발자가 깨닫지 못하는 건 열두어 개의 플래그만 깊이 이해해도 일상적인 API 테스트 작업의 90%를 커버할 수 있다는 점입니다. 나머지는 필요할 때 찾아보거나, 빌더를 써서 문법을 외우지 않고 명령어를 조립하면 됩니다.

이 가이드는 실제로 중요한 cURL 부분에 집중합니다. 오늘 바로 실행해볼 수 있는 실제 예시와 함께요.

왜 굳이 cURL인가?

당연한 질문입니다. Postman도 있고, Insomnia도 있고, VS Code REST Client 확장도 있고, 브라우저 DevTools도 있는데 — 왜 cURL을 쓸까요?

몇 가지 이유가 있습니다:

어디에나 있습니다. cURL은 macOS와 대부분의 Linux 시스템에 기본 설치되어 있습니다. 새로운 서버, Docker 컨테이너, 동료의 컴퓨터 — cURL은 항상 사용 가능합니다. Postman은 그렇지 않습니다.

스크립트로 만들 수 있습니다. bash 스크립트, CI 파이프라인, cron 작업, Makefile에 cURL 명령어를 넣을 수 있습니다. 인프라의 일부가 됩니다. GUI 도구로는 할 수 없는 일입니다.

공유하기 쉽습니다. Slack 메시지나 GitHub 이슈에 cURL 명령어를 붙여넣으면 누구든 즉시 실행할 수 있습니다. "Postman에서 이렇게 재현하세요"라는 설명이 필요 없습니다.

공통 언어입니다. 대부분의 API 문서는 cURL 예시를 보여줍니다. 동료가 "이 요청이 실패하는데"라고 말할 때, 보통 cURL 명령어를 보내줍니다. cURL을 읽을 줄 아는 건 그 자체로 가치 있는 스킬입니다.

다만, cURL이 항상 최선의 도구는 아닙니다. 여러 단계로 이어지는 복잡한 워크플로우, 시각적인 응답 검사, 또는 많은 폼 데이터를 다루는 작업은 Postman에서 관리하는 게 보통 더 빠릅니다. 상황에 맞는 도구를 써야 합니다.

실제로 쓰게 되는 플래그들

-X — HTTP 메서드 지정

기본적으로 cURL은 GET 요청을 보냅니다. -X를 사용해 메서드를 바꿉니다:

curl -X POST https://api.example.com/users
curl -X PUT https://api.example.com/users/123
curl -X DELETE https://api.example.com/users/123
curl -X PATCH https://api.example.com/users/123

간단한 팁: -d로 본문을 보낼 때는 -X POST를 생략해도 됩니다. cURL이 POST를 추론하기 때문입니다. 하지만 명시적으로 쓰는 게 특히 명령어를 다른 사람과 공유할 때 더 명확합니다.

-H — 헤더 추가

거의 모든 API 요청에는 헤더가 하나 이상 필요합니다. POST/PUT 요청에는 Content-Type, 인증이 필요한 엔드포인트에는 Authorization:

# 콘텐츠 타입 설정
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json"

# 인증 토큰 추가
curl https://api.example.com/profile \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..."

# 여러 헤더 사용
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-token" \
  -H "X-Request-ID: abc123"

같은 명령어에서 -H를 여러 번 사용할 수 있습니다. 헤더 하나당 플래그 하나입니다.

-d — 요청 본문

요청 본문에 데이터를 보냅니다. POST, PUT, PATCH와 함께 사용합니다:

# JSON 본문
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name": "이민지", "email": "minji@example.com"}'

# 폼 데이터 (URL 인코딩)
curl -X POST https://api.example.com/login \
  -d "username=minji&password=secret"

Content-Type 헤더를 빠뜨리는 실수에 대해 한마디: JSON을 보내면서 -H "Content-Type: application/json"을 잊으면, 서버가 요청을 거부하거나 본문을 잘못 파싱할 수 있습니다. 이건 가장 흔한 cURL 실수 중 하나입니다. 무엇을 보내는지 알고 있다면 항상 Content-Type을 설정하세요.

-L — 리다이렉트 추적

기본적으로 서버가 301이나 302 리다이렉트를 반환하면 cURL은 멈추고 리다이렉트 응답을 보여줍니다. 보통은 따라가길 원합니다:

curl -L https://example.com/old-url

이 플래그는 HTTP를 HTTPS로 리다이렉트하는 API나 리소스가 이동된 경우에 자주 필요합니다. -L 없이는 301 Moved Permanently만 보이고 왜 데이터가 없는지 의아하게 됩니다.

-i — 응답 헤더 포함

기본적으로 cURL은 응답 본문만 보여줍니다. -i는 응답 헤더도 함께 보여줍니다:

curl -i https://api.example.com/users/1

출력은 이렇게 생겼습니다:

HTTP/2 200
content-type: application/json
x-rate-limit-remaining: 99
...

{"id": 1, "name": "이민지"}

상태 코드, Content-Type, 캐싱 헤더, 레이트 리밋 정보를 확인해야 할 때 유용합니다. -i는 전체 연결 디버그 출력 없이 헤더만 필요할 때 verbose 모드의 가벼운 대안입니다.

-v — Verbose 모드

이건 디버깅 플래그입니다. -v는 모든 것을 보여줍니다: cURL이 보낸 전체 요청 헤더, TLS 핸드셰이크, 전체 응답 헤더:

curl -v https://api.example.com/users

출력 예시 (축약):

* Trying 93.184.216.34:443...
* Connected to api.example.com (93.184.216.34) port 443
* SSL connection using TLSv1.3
> GET /users HTTP/2
> Host: api.example.com
> User-Agent: curl/8.1.2
> Accept: */*
>
< HTTP/2 200
< content-type: application/json
<
{"users": [...]}

>로 시작하는 줄은 cURL이 보낸 것, <로 시작하는 줄은 서버가 응답한 것, *로 시작하는 줄은 cURL 자체의 상태 메시지입니다. 인증 문제, 예상치 못한 헤더, TLS 문제를 디버깅할 때 매우 유용합니다.

-u — Basic 인증

HTTP Basic Auth를 사용하는 API라면 Authorization 헤더를 직접 구성할 수도 있지만 -u가 자동으로 처리해줍니다:

curl -u username:password https://api.example.com/protected

cURL이 자격 증명을 Base64로 인코딩하고 Authorization: Basic ... 헤더를 올바르게 전송합니다. 한 가지 주의사항: 터미널에 직접 입력하면 비밀번호가 쉘 히스토리에 남습니다. 그 후에 히스토리를 지우거나, 환경 변수를 사용하세요:

curl -u "minji:$API_PASSWORD" https://api.example.com/protected

-k — SSL 검증 건너뛰기

이 옵션에 대해서는 한마디 주의가 필요합니다. -k (또는 --insecure)는 cURL이 SSL 인증서 오류를 무시하도록 합니다:

curl -k https://localhost:8443/api/health

자체 서명 인증서를 사용하는 로컬 개발 환경에서는 정당한 사용입니다. 실제 프로덕션 요청에는 적합하지 않습니다. 실제 외부 서비스에 -k를 사용한다면 정당한 이유로 존재하는 보안을 우회하는 것입니다. 개발 환경에서만 사용하세요.

-o-O — 파일로 저장

응답을 터미널에 출력하는 대신 파일로 저장합니다:

# 특정 파일명으로 저장
curl -o output.json https://api.example.com/data

# 원격 파일명 사용
curl -O https://example.com/files/report.pdf

-o는 파일명을 직접 지정하고, -O는 URL의 마지막 경로 세그먼트를 파일명으로 사용합니다.

-s — 조용한 모드

진행 상태 표시와 에러 메시지를 억제합니다. 응답 본문만 원하는 스크립트에서 유용합니다:

curl -s https://api.example.com/status | jq .

jq로 파이프 연결하는 건 JSON 응답을 예쁘게 출력하는 흔한 패턴입니다. -s는 출력을 깔끔하게 유지해서 jq가 JSON만 받도록 합니다.

흔한 실수들

POST 요청에서 Content-Type 잊어버리기

이건 개발자들이 매번 걸리는 실수입니다. JSON을 보내는데 서버가 400 Bad Request나 415 Unsupported Media Type을 반환하고, 20분을 디버깅하다 결국 헤더 하나를 추가하면 해결된다는 걸 깨닫습니다:

# 헤더 누락 - 서버가 거부할 수 있음
curl -X POST https://api.example.com/users \
  -d '{"name": "이민지"}'

# 올바른 방법
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name": "이민지"}'

Windows에서의 따옴표 문제

Windows 명령 프롬프트(CMD)에서 cURL은 bash와 따옴표를 다르게 처리합니다. CMD에서는 작은따옴표가 작동하지 않습니다. 큰따옴표를 사용하고 내부 따옴표를 이스케이프해야 합니다:

rem Windows CMD - 큰따옴표 사용, 내부 따옴표 이스케이프
curl -X POST https://api.example.com/users ^
  -H "Content-Type: application/json" ^
  -d "{\"name\": \"이민지\"}"

PowerShell에서는 작은따옴표가 작동하지만 이스케이프 규칙이 여전히 다릅니다. Windows 개발자들이 Unix 시스템용으로 작성된 문서의 cURL 명령어를 사용할 때 가장 큰 혼란의 원인입니다. Windows에서 문서의 cURL 명령어가 작동하지 않는다면, 보통 따옴표 문제입니다.

파일을 본문으로 보낼 때 @ 잊어버리기

파일 내용을 요청 본문으로 보내려면 @파일명을 사용합니다:

# data.json 내용을 본문으로 전송
curl -X POST https://api.example.com/import \
  -H "Content-Type: application/json" \
  -d @data.json

@ 없이는 cURL이 해당 문자열을 파일명이 아닌 리터럴 본문 값으로 처리합니다. 파일 내용 대신 data.json이라는 텍스트 자체를 보내게 됩니다.

GET 요청에 -d 사용하기

-d는 본문을 보냅니다. GET 요청에는 본문이 없습니다 (서버는 일반적으로 이를 무시합니다). GET 요청에 쿼리 파라미터를 보내려면 URL에 직접 넣으세요:

# GET 요청에 파라미터를 전달하는 올바른 방법
curl "https://api.example.com/users?page=1&limit=20"

URL 주위의 따옴표에 주목하세요. 따옴표 없이는 URL의 &가 쉘에서 백그라운드 연산자로 해석될 수 있습니다.

실전 예시들

사용자 생성:

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name": "김준호", "email": "junho@example.com", "role": "editor"}'

파일 업로드:

curl -X POST https://api.example.com/upload \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@/path/to/document.pdf" \
  -F "description=4분기 보고서"

(참고: 멀티파트 폼 데이터는 -d 대신 -F 사용)

커스텀 페이로드로 웹훅 테스트:

curl -X POST https://your-app.com/webhooks/github \
  -H "Content-Type: application/json" \
  -H "X-GitHub-Event: push" \
  -H "X-Hub-Signature-256: sha256=abc123" \
  -d @sample-push-event.json

진행 상황 표시와 함께 다운로드:

curl -L -o large-file.zip https://example.com/downloads/archive.zip

verbose 모드 출력 읽는 법

-v 플래그를 처음 쓰면 출력이 좀 압도적으로 느껴질 수 있습니다. 실제로 무엇을 보고 있는지 분해해보면:

*   Trying 93.184.216.34:443...

cURL이 서버에 TCP 연결을 시도하고 있습니다. IP 주소와 포트가 보입니다.

* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384

TLS 협상 세부 정보. 인증서 문제를 디버깅할 때 여기에 오류가 나타납니다.

> GET /users HTTP/2
> Host: api.example.com
> Authorization: Bearer eyJ...

> 줄은 cURL이 실제로 보낸 요청 헤더입니다. 예상한 헤더가 모두 여기 있는지 확인하세요.

< HTTP/2 200
< content-type: application/json
< x-ratelimit-remaining: 99

< 줄은 서버의 응답 헤더입니다. 상태 코드, 콘텐츠 타입, 커스텀 헤더를 여기서 확인합니다.

인증이 예상대로 작동하지 않을 때는 -v 출력에서 > Authorization: 줄이 있는지, 그리고 값이 올바른지 확인하는 것부터 시작하세요.

빌더 사용하기 vs 직접 외우기

기본적인 GET 요청을 넘어서면, 적절한 플래그 조합을 기억에서 꺼내 조립하는 일이 금방 지겨워집니다. ToolPal cURL 명령어 빌더는 메서드, URL, 헤더, 본문을 폼으로 입력하면 cURL 명령어를 생성해줍니다 — 그러면 터미널에 바로 복사하거나 필요에 따라 수정할 수 있습니다.

다음 경우에 특히 유용합니다:

  • 전에 써보지 않은 인증 헤더가 있는 명령어 만들기
  • 멀티파트 폼 업로드 문법 올바르게 작성하기
  • bash에 익숙한데 Windows 호환 명령어가 필요할 때
  • cURL 플래그 문법을 모르는 팀원과 명령어 공유하기

생성된 명령어는 표준 cURL입니다 — 벤더 종속성 없음, 독점 요소 없음. 빌더는 생산성 단축키로 사용하고, 결과 명령어는 필요한 어디서든 사용하면 됩니다.

cURL vs. 다른 도구들

cURL vs. Postman: Postman은 반복적인 API 탐색, 요청 컬렉션 관리, 팀 협업에서 이깁니다. cURL은 스크립팅, 빠른 일회성 요청, 공유 용이성에서 이깁니다. 경쟁자가 아닙니다 — 대부분의 개발자는 둘 다 씁니다.

cURL vs. HTTPie: HTTPie는 더 친숙한 인터페이스와 예쁜 출력을 가진 최신 커맨드라인 HTTP 클라이언트입니다. 설치에 열려있다면 살펴볼 가치가 있습니다. cURL은 설치 없이 어디서나 사용 가능하다는 장점이 있습니다.

cURL vs. 브라우저 DevTools: 브라우저가 실제로 보내는 것 (쿠키, 세션 토큰, 복잡한 헤더)을 확인하려면 DevTools가 최고입니다. Network 탭에서 요청을 우클릭하고 "Copy as cURL"을 선택할 수도 있습니다 — 커맨드라인에서 브라우저 요청을 재현하는 유용한 방법입니다.

자주 마주치는 에러 메시지들

curl: (60) SSL certificate problem 서버의 SSL 인증서를 검증하지 못했습니다. 자체 서명 인증서를 사용하는 로컬 서버라면 -k를 추가하세요. 실제 외부 서버라면 시스템의 CA 번들이 오래되었을 수 있습니다.

curl: (7) Failed to connect to ... port 443 서버에 연결할 수 없습니다. URL이 맞는지, 서버가 실행 중인지, 방화벽 규칙이 연결을 차단하고 있지 않은지 확인하세요.

curl: (6) Could not resolve host DNS 조회가 실패했습니다. URL의 호스트명을 확인하거나 인터넷 연결을 확인하세요.

HTTP 401 Unauthorized 인증이 실패했습니다. 토큰이나 자격 증명을 확인하세요. -v로 실제로 보내진 Authorization 헤더를 확인하면 도움이 됩니다.

HTTP 415 Unsupported Media Type 거의 항상 Content-Type 헤더가 누락되었거나 잘못된 경우입니다. -H "Content-Type: application/json"을 추가하고 다시 시도하세요.


cURL은 투자한 시간만큼 보답하는 도구입니다. 모든 플래그를 외우지 않아도, 핵심 플래그들 — -X, -H, -d, -L, -v — 의 작동 방식을 이해하면 어디서든 사용 가능하고, 스크립트로 만들기 쉽고, 명확하게 소통할 수 있는 도구가 생깁니다. 그건 외워둔 문법 패턴 수보다 훨씬 가치 있습니다.

모를 때는 빌더를 쓰세요. 뭔가 잘못됐을 때는 -v를 쓰세요.

자주 묻는 질문

이 글 공유하기

XLinkedIn

관련 글