cURL 명령을 JavaScript fetch·Python requests로 변환하는 방법|DevTools 연동
API 디버깅에서 흔한 작업은 「Chrome DevTools에서 확인한 cURL 명령을 코드로 그대로 변환하는」것입니다. 이 문서에서는 <strong>cURL 옵션 체계</strong>, DevTools의 「Copy as cURL」기능의 작동 원리, 주요 언어(JavaScript fetch / axios / Python requests / PHP cURL / Go net/http)로의 변환 패턴을 설명합니다. 끝에 소개된 <a href="/ja/tools/curl/">cURL 변환 도구</a>를 사용하면 이들을 복사 붙여넣기 한 번으로 변환할 수 있습니다.
cURL을 시작점으로 삼는 이유
API를 구현하고 디버깅할 때, 일반적인 워크플로우는 먼저 「curl로 작동하는지 확인한 후 코드로 작성한다」는 것입니다. 이유는 다음과 같습니다:
- <strong>언어 독립적</strong>: curl은 거의 모든 환경에서 사용 가능한 공통 언어입니다
- <strong>DevTools에서 즉시 복사</strong>: Chrome / Firefox / Safari의 Network 탭에서 요청을 우클릭 → Copy as cURL로 완전한 재현 명령 획득 가능
- <strong>재현성 보장</strong>: 버그 보고나 Stack Overflow 질문에 curl 명령을 첨부하면, 환경 차이 없이 상대방이 동일한 요청을 시도해볼 수 있습니다
cURL의 주요 옵션
최소한 알아야 할 cURL 옵션은 다음과 같습니다.
| 옵션 | 용도 | 예시 |
|---|---|---|
-X / --request | HTTP 메서드 지정 | -X POST |
-H / --header | 요청 헤더 추가 | -H "Content-Type: application/json" |
-d / --data | 요청 본문 | -d '{"id":1}' |
--data-raw | 이스케이프 해석을 하지 않는 원본 데이터 | --data-raw 'a=1&b=2' |
-F / --form | multipart/form-data | -F "file=@./a.png" |
-u / --user | Basic 인증 | -u user:pass |
-b / --cookie | Cookie 전송 | -b "session=abc" |
-L / --location | 리다이렉트 추적 | — |
-k / --insecure | SSL 증명서 검증 건너뛰기 (개발 시에만) | — |
--compressed | gzip 수락 | — |
DevTools의 "Copy as cURL"에서 얻을 수 있는 것
Chrome / Firefox / Edge에서 Network 탭을 열고 임의의 요청을 마우스 오른쪽으로 클릭하면 <strong>Copy → Copy as cURL</strong>이라는 메뉴가 있습니다. 이를 클릭하면 완전히 재현된 명령이 클립보드에 복사됩니다.
- HTTP 메서드 및 전체 URL
- 전송된 모든 요청 헤더 (Authorization / User-Agent / Accept / Cookie 등)
- 요청 본문 (JSON / form-data / binary)
- ANSI-C quoting (<code>$'...'</code>)을 통한 이스케이프
주의할 점으로, Firefox의 "Copy as cURL"은 <code>--data-raw</code>를 사용하고 Chrome은 <code>--data-binary</code>를 사용하는 등 미묘한 차이가 있습니다. 변환 도구 측에서 둘 다 인식할 수 있는 구현이 필요합니다.
JavaScript fetch로 변환
일반적인 JSON POST 변환 예를 보여줍니다.
# cURL
curl -X POST https://api.example.com/users \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{"name":"Alice","email":"alice@example.com"}'
// JavaScript fetch
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN',
},
body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' }),
})
.then(r => r.json())
.then(console.log);
axios 버전
import axios from 'axios';
axios.post(
'https://api.example.com/users',
{ name: 'Alice', email: 'alice@example.com' },
{ headers: { 'Authorization': 'Bearer YOUR_TOKEN' } }
).then(r => console.log(r.data));
Python requests로 변환
import requests
response = requests.post(
'https://api.example.com/users',
headers={
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN',
},
json={'name': 'Alice', 'email': 'alice@example.com'},
)
print(response.json())
<code>data=</code> 대신 <code>json=</code>을 사용하는 것이 중요합니다. <code>json=</code>을 지정하면 requests가 자동으로 JSON을 직렬화하고 Content-Type도 자동으로 설정됩니다.
PHP cURL로 변환
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.example.com/users');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer YOUR_TOKEN',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'name' => 'Alice',
'email' => 'alice@example.com',
]));
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Go net/http로의 변환
package main
import (
"bytes"
"io"
"net/http"
)
func main() {
body := bytes.NewReader([]byte(`{"name":"Alice","email":"alice@example.com"}`))
req, _ := http.NewRequest("POST", "https://api.example.com/users", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
data, _ := io.ReadAll(res.Body)
println(string(data))
}
주의: 토큰의 하드코딩은 절대 금지
cURL 명령을 코드로 변환할 때 Authorization 헤더 값(Bearer 토큰이나 API 키)을 <strong>그대로 코드에 작성해서 커밋하지 않도록</strong> 주의하세요.
- 프로덕션 토큰을 환경 변수를 통해 읽기 (<code>process.env.API_TOKEN</code> / <code>os.environ['API_TOKEN']</code> / <code>getenv()</code>)
- 커밋 전에 <code>git diff</code>로 비밀 정보가 섞여 있지 않은지 확인
- 이미 커밋한 경우 토큰을 즉시 무효화(rotation)하고 히스토리를 다시 작성(git filter-repo)
DevLab cURL 변환 도구
<a href="/ja/tools/curl/">DevLab의 cURL ⇄ fetch / axios 변환 도구</a>는 위의 모든 변환을 <strong>브라우저에서 완결</strong>로 한 번의 클릭으로 실행합니다. 지원 대상은 13가지:
- JavaScript: fetch / axios / node-fetch / Node.js 표준 https
- Python: requests / urllib
- PHP: cURL / file_get_contents
- Go: net/http
- Rust: reqwest
- wget / HTTPie / PowerShell Invoke-WebRequest
cURL 옵션은 <code>-X</code> <code>-H</code> <code>-d</code> <code>--data-raw</code> <code>--data-binary</code> <code>--data-urlencode</code> <code>-F</code> <code>-u</code> <code>-b</code> <code>-A</code> <code>-e</code> <code>-L</code> <code>-k</code> <code>-I</code> 및 ANSI-C quoting <code>$'...'</code>을 지원하며 Chrome과 Firefox의 "Copy as cURL" 출력을 그대로 받아들입니다.
요약
cURL은 언어 비의존적인 HTTP 재현 공통 언어로 매우 편리하며, DevTools와 결합하면 실운영 중인 API 요청을 즉시 재현할 수 있습니다. 이 기사에서 보여주는 변환 패턴을 습득하면 어떤 언어에서든 동일한 동작을 재현할 수 있습니다. 수작업으로 변환하면 누락(특히 Content-Type이나 따옴표 이스케이프)이 발생하기 쉬우므로 자동화된 변환 도구 사용을 강력히 권장합니다.