curl -d만 쓰고 -X 안 써도 POST로 잡히는 이유
API 문서나 개발자 도구의 "Copy as cURL"에서 curl -d '{"key":"value"}' https://example.com 같은 명령을 본 적이 있을 겁니다. -X POST가 안 보이는데도 이 요청은 실제로 GET이 아니라 POST로 나갑니다. 많은 사람이 "-X가 없으면 기본값은 GET"이라고만 알고 있어서 이 동작을 처음 보면 당황합니다. 이 가이드는 왜 -d만으로 메서드가 바뀌는지, 그리고 이 규칙을 파싱 도구가 정확히 재현하지 못하면 어떤 문제가 생기는지를 정리합니다.
1. curl의 기본 메서드 규칙: 조건부 GET
curl의 공식 매뉴얼을 보면 메서드 관련 동작은 생각보다 단순하지 않습니다. -X/--request 옵션을 전혀 안 쓰면 curl은 "기본적으로" GET을 보내지만, 이 기본값에는 예외가 있습니다. -d, --data, --data-raw, --data-binary, --data-urlencode 같은 데이터 전송 옵션이 하나라도 있으면, curl은 자동으로 메서드를 POST로 바꿔서 보냅니다. 즉 "-X가 없으면 무조건 GET"이 아니라 "-X가 없고 데이터도 없으면 GET, 데이터가 있으면 POST"가 정확한 규칙입니다. 이건 curl이 임의로 넣은 편의 기능이 아니라, HTTP 스펙상 GET 요청에는 원칙적으로 본문(body)을 싣지 않기 때문에 본문이 있다는 사실 자체가 "이건 GET이 아니다"라는 강한 신호로 취급되는 것입니다.
2. 왜 자꾸 헷갈리는가: 문서·툴마다 표기가 다름
이 규칙이 자주 오해받는 이유는 실무에서 마주치는 세 가지 소스가 서로 다른 습관을 갖고 있기 때문입니다.
- API 공식 문서: 명확성을 위해 관례적으로 -X POST를 항상 명시하는 경우가 많습니다. 그래서 "cURL 예제에는 항상 -X가 있다"는 인상을 갖기 쉽습니다.
- 브라우저 개발자 도구의 "Copy as cURL": 실제 요청 메서드가 POST였어도, Chrome/Firefox는 -X를 생략하고 -d만 넣는 경우가 있습니다. 실제 전송된 메서드와 무관하게 curl 자체 규칙에 맡기는 방식입니다.
- 직접 손으로 짠 스크립트: 개발자가 "-d를 쓰니까 당연히 POST겠지"라고 생각하고 -X를 생략하는 경우입니다. 대부분 의도대로 동작하지만, 이 규칙을 모르고 짠 게 아니라 알고 생략한 것인지 코드 리뷰에서 구분하기 어렵습니다.
세 경우 모두 결과 자체는 같은 POST 요청이지만, 겉보기 명령어 형태가 다르기 때문에 "이게 맞는 문법인가?"라는 의문이 반복해서 생깁니다.
3. 파싱 도구가 이 규칙을 놓치면 생기는 문제
cURL 명령어를 분석해서 URL·메서드·헤더·본문으로 분해해주는 도구를 쓸 때 이 규칙이 특히 중요합니다. 단순하게 "-X 뒤 값을 메서드로, 없으면 GET"이라고만 구현하면 다음과 같은 흔한 입력에서 실제 동작과 다른 결과를 보여줍니다.
curl -d '{"name":"Alice"}' https://api.example.com/users실제 curl 동작: -d가 있으므로 자동으로 POST 요청 전송
규칙을 안 지키는 파서: -X가 없으니 기본값 GET으로 표시 → 실제 동작과 다른 결과를 보여줘 사용자가 API 서버 로그와 비교하며 혼란을 겪음
| 입력 형태 | 실제 curl이 보내는 메서드 | 규칙 없는 파서의 오답 |
|---|---|---|
| -X 없음, -d 없음 | GET | GET (일치) |
| -X 없음, -d 있음 | POST | GET (불일치) |
| -X GET, -d 있음 | GET(명시적으로 지정했으므로 그대로 유지) | GET (일치) |
| -X PUT, -d 있음 | PUT | PUT (일치) |
즉 문제가 되는 건 정확히 "-X 없이 -d만 있는" 한 가지 조합뿐이지만, 이게 실무에서 가장 자주 나오는 패턴이라는 게 함정입니다. cURL 파서는 -X가 명시적으로 없고 body가 있을 때만 GET 기본값을 POST로 교정하도록 구현되어 있어, 이 흔한 패턴에서도 실제 curl과 동일한 결과를 보여줍니다.
4. 검증 방법: 직접 확인하는 법
도구를 믿기 전에 직접 눈으로 규칙을 확인하고 싶다면, 터미널에서 curl -v -d 'test=1' https://example.com 2>&1 | grep "> POST" 처럼 verbose 모드로 실행해 실제 전송되는 요청 라인을 확인하면 됩니다. -v 옵션은 실제로 나간 HTTP 요청 라인(> POST / HTTP/1.1)을 그대로 출력하므로, 문서나 도구를 거치지 않고 curl 바이너리 자체의 동작을 검증할 수 있습니다. 온라인에서 명령어만 분해해 확인하고 싶다면 cURL 파서에 명령어를 붙여넣어 Method 필드가 어떻게 표시되는지 바로 확인할 수 있습니다.
5. 관련해서 자주 같이 겪는 실수
-d와 메서드 규칙 외에도 cURL 명령어를 다룰 때 흔히 헷갈리는 부분들이 있습니다. -H로 헤더를 여러 개 붙일 때 따옴표 처리를 잘못해 명령어가 깨지는 경우, 반대로 이미 완성된 요청을 바탕으로 cURL 명령어를 새로 만들어야 하는 경우도 자주 있습니다. 후자의 상황이라면 cURL 생성기로 폼 입력값을 채워 명령어를 역으로 만들어낼 수 있고, API 응답 구조 자체를 보기 좋게 확인하고 싶다면 API 테스터나 JSON 뷰어를 함께 활용하면 편합니다.
자주 묻는 질문
Q. -X GET과 -d를 같이 쓰면 어떻게 되나요?
-X로 메서드를 명시적으로 지정하면 그 값이 그대로 유지됩니다. -d가 있어도 자동 POST 교정은 -X가 아예 없을 때만 적용되므로, -X GET -d '...'는 흔치 않지만 유효한 조합으로 GET 요청에 본문을 실어 보냅니다(서버가 이를 어떻게 처리할지는 별개 문제입니다).
Q. --data-raw나 --data-binary도 같은 규칙이 적용되나요?
네. -d/--data뿐 아니라 --data-raw, --data-binary, --data-urlencode 등 데이터를 본문에 싣는 옵션은 모두 동일하게 -X가 없을 때 메서드를 POST로 바꿉니다.
Q. -F(멀티파트 폼 업로드)도 같은 규칙인가요?
-F/--form도 본문을 전송하는 옵션이므로 -X 없이 쓰면 마찬가지로 자동 POST가 적용됩니다. GET으로 파일을 업로드하는 것은 애초에 의미가 없기 때문입니다.
Q. 이 규칙은 curl 버전에 따라 다른가요?
오래전부터 이어진 curl의 기본 동작으로, 현재 널리 쓰이는 버전들에서 공통적으로 유지되고 있습니다. 다만 정확한 동작이 궁금하면 curl --manual 또는 공식 매뉴얼 페이지에서 최신 문서를 확인하는 것이 가장 안전합니다.