[HTTPie] curl 대신 쓰는 CLI HTTP 클라이언트
![[HTTPie] curl 대신 쓰는 CLI HTTP 클라이언트](https://blog.kakaocdn.net/dna/dWwzbB/dJMcagzEEZS/AAAAAAAAAAAAAAAAAAAAAEhFjo5ZzdqDORM8_FsTfEEgQ417b4iGFj5KZNbqUokL/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1788188399&allow_ip=&allow_referer=&signature=qJINQ0rtWHt0eGUjmnoZMAaEl%2F8%3D)
개발자 도구 > API & DB
[HTTPie] curl 대신 쓰는 CLI HTTP 클라이언트
HTTPie는 터미널에서 API를 때릴 때 curl 옵션을 외우지 않아도 되게 만든 도구예요. JSON 본문이 기본값이에요. 응답은 색이 입혀진 채로 나오고요. 설치부터 요청 문법, 세션 유지, 자주 걸리는 함정까지 정리했어요.
curl을 못 읽어서 생긴 도구예요
터미널에서 API 하나 확인하려고 curl 명령을 쓰면, 정작 중요한 URL과 본문은 -X -H -d 사이에 파묻혀요. JSON을 보내려면 헤더를 손으로 붙여야 해요. 따옴표도 이스케이프해야 하죠. 돌아온 응답은 한 줄로 뭉쳐 나와서 다시 jq에 파이프를 겁니다.
HTTPie는 그 지점을 고친 CLI HTTP 클라이언트예요. 공식 문서는 스스로를 "API 시대를 위한 명령줄 HTTP·API 테스트 클라이언트"로 소개해요. 목표는 "웹 서비스와의 CLI 상호작용을 최대한 사람 친화적으로"라고 적혀 있고요. 라이선스는 BSD-3-Clause 오픈소스고요.
대체 대상은 두 갈래예요. 하나는 curl의 가독성, 다른 하나는 GUI 클라이언트를 켰다 껐다 하는 왕복이에요. 요청 하나 확인하겠다고 앱을 띄우고 컬렉션을 뒤지는 대신, 셸 히스토리에 남는 한 줄로 끝내는 쪽에 가까워요.
| 하려는 일 | curl | HTTPie |
|---|---|---|
| JSON POST | curl -X POST -H "Content-Type: application/json" -d '{"name":"John"}' ... |
http POST ... name=John |
| 헤더 추가 | -H "X-API-Token: 123" |
X-API-Token:123 |
| 쿼리스트링 | URL에 직접 ?token=secret |
token==secret |
| 응답 보기 | 한 줄 출력, | jq 필요 |
기본으로 포매팅·색상 적용 |
| Content-Type | 직접 지정 | 데이터 항목이 있으면 JSON 자동 |
설치하고 첫 요청까지 명령 두 줄이면 돼요
패키지 매니저 대부분에 올라가 있어요. macOS는 Homebrew, Windows는 Chocolatey, 리눅스는 배포판 저장소나 공식 apt 저장소를 씁니다. OS를 가리지 않는 경로로는 pip가 있어요. 문서에는 apt·brew·choco·pip·port·snap·yum이 나열돼 있어요.
# macOS
brew update && brew install httpie
# Windows
choco install httpie
# 어디서나 (Python)
python -m pip install --upgrade pip wheel
python -m pip install httpie
설치하면 http와 https 두 개의 실행 파일이 깔려요. 이름이 곧 기본 스킴이라서, https example.org는 https://example.org로 나가요. 요청 문법의 뼈대는 http [플래그] [메서드] URL [항목...] 한 줄이에요.
http PUT pie.dev/put X-API-Token:123 name=John
메서드를 생략해도 돼요. 데이터 항목이 없으면 GET, 있으면 POST로 잡히기 때문에 조회는 http pie.dev/get처럼 URL만 던지면 끝나요.
로컬 개발 서버는 콜론 하나로 줄여요
포트만 바꿔 가며 로컬 서버를 두드릴 일이 많은데, 여기에 단축 문법이 따로 있어요. 콜론으로 시작하면 호스트가 localhost로 채워져요.
http :3000/bar # GET /bar → Host: localhost:3000
http :/foo # GET /foo → Host: localhost
http : # GET / → Host: localhost
포트를 안 적으면 80으로 봐요. 플러그인으로 다른 스킴을 쓸 때는 --default-scheme로 기본값을 바꿔 별칭을 만들어 두는 방식도 문서에 나와 있어요.
기호 여섯 개가 요청 문법의 거의 전부예요
HTTPie 문법에서 외울 건 URL 뒤에 붙는 "요청 항목"의 구분 기호예요. 왼쪽 이름과 오른쪽 값 사이에 무슨 기호를 쓰느냐로 헤더인지, 본문인지, 쿼리스트링인지가 갈려요.
= 와 := — 본문 필드
name=John은 문자열 필드, age:=29는 원시 JSON 필드예요. 숫자·불리언·배열·객체처럼 따옴표가 붙으면 안 되는 값은 := 쪽을 써야 해요. 데이터 항목이 하나라도 있으면 기본 직렬화가 JSON 객체라서, Content-Type을 따로 지정할 필요가 없어요.
http POST pie.dev/post name=John age:=29 admin:=false tags:='["a","b"]'
: 와 == — 헤더와 쿼리 파라미터
콜론은 헤더예요. X-API-Token:123처럼 씁니다. 값 없이 Header:로 끝내면 기본 헤더가 지워져요. 등호 두 개는 쿼리 파라미터라서 token==secret이 URL 뒤에 ?token=secret으로 붙어요. URL 인코딩은 HTTPie가 처리해요.
@ 와 =@ — 파일 붙이기
@는 폼 업로드예요. screenshot@~/Pictures/img.png처럼 쓰면 되는데, 이건 폼 모드에서만 동작해요. 파일 내용을 값으로 넣고 싶으면 =@(텍스트)나 :=@(JSON)를 쓰고요. 긴 JSON 본문을 셸에 그대로 붙여넣는 대신 파일로 빼 둘 때 쓸 만해요.
# 폼·멀티파트 전송은 -f
http -f POST pie.dev/post name='John Smith' cv@~/files/data.xml
# 파일 내용을 값으로
http POST pie.dev/post description=@files/text.txt bookmarks:=@files/data.json
파일 필드가 하나라도 섞이면 직렬화가 multipart/form-data로 바뀐다고 문서에 명시돼 있어요.
응답에서 볼 부분을 직접 골라요
기본 출력은 응답 헤더와 본문이에요. 여기서 더 보거나 덜 보고 싶을 때 쓰는 플래그가 나뉘어 있어요.
-v/--verbose— 요청과 응답 전체를 다 출력. 무엇을 보냈는지까지 확인할 때-h/--headers,-b/--body— 응답 헤더만, 본문만-p/--print— 문자 코드로 조합. H=요청 헤더, B=요청 본문, h=응답 헤더, b=응답 본문, m=응답 메타데이터--pretty=all|colors|format|none— 색상과 정렬을 켜고 끔. 파이프로 넘길 때none
http -v POST pie.dev/post name=John # 주고받은 전체
http -p Hb pie.dev/get # 요청 헤더 + 응답 본문만
세션 파일 하나로 로그인 상태를 들고 다녀요
인증은 -a user:pass가 기본이에요. 비밀번호를 빼고 -a user까지만 적으면 프롬프트로 물어봐요. digest나 bearer 같은 방식은 -A / --auth-type으로 지정합니다.
여기에 --session을 붙이면 헤더·인증·쿠키가 이름 붙은 세션에 저장돼요. 다음 요청부터는 세션 이름만 넘기면 인증 정보를 다시 안 적어도 되고요.
# 세션 만들면서 인증
http --session=user1 -a username:password pie.dev/get
# 이후 재사용
http --session=user1 pie.dev/headers
저장 위치는 유닉스 계열이 ~/.config/httpie/sessions/<host>/<name>.json, 윈도우가 %APPDATA%\httpie\sessions\...예요. 이름 대신 파일 경로를 주면 익명 세션이 됩니다. 세션을 갱신하지 않고 읽기만 할 때는 --session-read-only를 써요. 설정 파일은 ~/.config/httpie/config.json에 있어요. 위치는 HTTPIE_CONFIG_DIR 환경변수로 바꿉니다.
내려받기와 오프라인 조립
-d / --download를 붙이면 wget처럼 진행 표시줄을 띄우고 파일로 저장해요. 파일명은 -o로 직접 주거나, 서버의 Content-Disposition 헤더, 또는 URL과 콘텐츠 타입 조합으로 정해져요. 중간에 끊긴 다운로드는 --continue로 이어받고요.
반대로 --offline은 요청을 보내지 않고 조립 결과만 표준출력으로 찍고 끝나요. 이 옵션이 켜지면 --print=HB가 자동으로 붙어요. 서버를 건드리지 않고 "이 명령이 실제로 어떤 요청이 되는가"만 확인하는 용도예요.
http -dco file.zip example.org/file # 다운로드 + 이어받기 + 파일명 지정
http --offline POST pie.dev/post name=John age:=29
미리 알아두면 걸리지 않을 것들
@업로드는 폼 전용이에요.-f없이 쓰면 의도한 멀티파트가 안 나와요:=를 안 쓰면 숫자도 문자열로 나가요.age=29와age:=29는 서버에서 다른 값이에요- 배열·객체 값은 셸이 먼저 해석해요.
tags:='["a","b"]'처럼 작은따옴표로 감싸는 습관이 필요해요 - 출력을 파이프로 넘길 때는 색상 이스케이프가 섞여요.
--pretty=none으로 끄는 편이 안전해요 - 리다이렉트는 기본으로 따라가지 않아요.
-F/--follow를 붙여야 해요. 중간 응답까지 보려면--all을 씁니다. 기본 최대 리다이렉트는 30회예요 - 사설 인증서 환경은
--verify=no로 넘기기보다--verify=/path/to/ca_bundle로 CA 번들을 지정하는 쪽이 맞아요. 클라이언트 인증서는--cert,--cert-key로 붙여요 - pip로 설치했다면 플러그인도
httpie cli plugins install명령으로 관리해요. pip에 직접 설치하는 것과 경로가 달라요
http 실행 파일이 어느 쪽인지 헷갈리기 쉬워요. which http로 경로를 먼저 확인하세요. 플러그인은 그 설치본 기준으로 httpie cli plugins list에 잡히는지 보면 됩니다.어떤 사람에게 맞나
맞는 쪽은 명확해요. 로컬 서버를 띄워 놓고 엔드포인트를 반복해서 두드리는 개발 단계, JSON 본문이 주력인 API, 그리고 명령이 셸 히스토리와 스크립트에 남아야 하는 상황이에요. http :3000/api/users name=John 정도면 팀 채널에 그대로 붙여넣어도 상대가 바로 읽어요.
반대로 curl을 완전히 대체하지는 않아요. CI 이미지나 서버 안에는 curl이 이미 들어 있고 HTTPie는 별도 설치가 필요하니, 배포 스크립트까지 갈아치울 이유는 크지 않아요. 컬렉션 공유나 팀 단위 API 문서화가 목적이라면 Bruno·Postman 같은 클라이언트 쪽 영역이고요.
시작은 가볍게 할 수 있어요. 설치한 뒤 http --offline으로 평소 쓰던 curl 명령 하나를 HTTPie 문법으로 옮겨 보세요. 조립된 요청이 같은지 눈으로 맞춰 보는 순서가 무난해요. 여기서 기호 여섯 개에 익숙해지면 나머지는 필요할 때 문서에서 찾아 쓰면 되는 수준이에요.
이 글은 직접 사용기가 아니라 공식 문서와 저장소를 근거로 한 객관 정리예요. 명령·플래그·경로는 작성 시점 문서 기준이에요. 버전에 따라 달라질 수 있습니다.
'개발자 도구 > API & DB' 카테고리의 다른 글
| [Proxyman] Charles 대신 쓰는 macOS HTTP 디버깅 프록시 (0) | 2026.07.15 |
|---|---|
| [TablePlus] 여러 DB를 한 창에서 다루기 (0) | 2026.07.03 |
| [Postman] 요청 보내기만 쓰고 있다면 놓치는 3가지 (0) | 2026.06.19 |
| [Bruno] API 컬렉션을 Git으로 관리하는 법 (0) | 2026.06.05 |
| Bruno: Postman 대체할 오픈소스 API 클라이언트 (0) | 2026.05.13 |
📚 같이 보면 좋은
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 일정액의 수수료를 제공받습니다."