에디블로그
Engineer's Field Notes

AI 자동화로 매일
한 편씩 쓰는
엔지니어 운영 노트

Claude Code · 자동화 파이프라인 · 사고 회고까지. 잘 굴러간 기록 + 깨진 흔적도 같이 남깁니다.

사람이 할 수 있는 일은,
AI도 할 수 있어야 합니다.
매일 한 편 쓰면서 검증 중.
— 이번 주 가장 많이 읽힌 글 TOP 3
개발자 도구/API & DB

Bruno: Postman 대체할 오픈소스 API 클라이언트

반응형
Bruno: Postman 대체할 오픈소스 API 클라이언트

EDIBLOG · 개발자 도구 노트

Bruno: Postman 대체할 오픈소스 API 클라이언트

안녕하세요, 에디입니다. 저는 Postman 유료 좌석 비용이 부담돼서 대안을 찾다가 Bruno 를 발견했어요. 핵심은 한 가지예요 — API 컬렉션을 텍스트 파일로 저장해서 Git 으로 관리합니다. 그게 다르고, 그게 강점이에요.

.bru 텍스트 MIT 오픈소스 Git 버전 관리 CLI 지원

01 · THE CORE IDEA핵심은 "텍스트 파일"이에요

결론. 저는 Bruno 가 Postman 과 다른 점을 한 줄로 정리했어요. "기능이 아니라 어디에 저장되는가" 가 핵심이에요.

저는 Bruno 가 API 컬렉션을 .bru 확장자의 텍스트 파일로 저장한다는 걸 알고 한 번에 끌렸어요. 저는 사람이 읽을 수 있는 형식이고, 코드 레포에 같이 커밋되고, PR 리뷰가 가능한 형태라는 게 핵심이라고 봤어요.

제가 쓰던 Postman

클라우드 DB 저장

제가 옮긴 Bruno

.bru 텍스트 + Git

저는 .bru 파일 예시를 봤을 때 "어, 이게 되는구나" 싶었어요. 실제 파일은 이렇게 생겼어요:

.bru 파일 — Get User 요청 한 편

meta {
  name: Get User Profile
  type: http
  seq: 1
}

get {
  url: https://api.example.com/users/{{userId}}
  body: none
  auth: bearer
}

headers {
  Accept: application/json
  X-Request-ID: {{$randomUUID}}
}

auth:bearer {
  token: {{authToken}}
}

vars:pre-request {
  userId: 42
}

tests {
  test("status is 200", function() {
    expect(res.getStatus()).to.equal(200);
  });
}

저는 이 파일을 Git 에 커밋하면 끝이라는 점이 좋았어요. 다음에 누가 URL 을 바꾸거나 헤더를 추가하면 저는 git diff 로 정확히 봐요. 코드 리뷰처럼 API 변경도 리뷰되는 셈이에요.

저는 비교 위해 같은 요청을 Postman 형식으로도 봤어요. Postman 컬렉션은 JSON 한 덩어리예요. 사람이 읽기 어렵고, diff 도 어려워요:

Postman JSON — 같은 요청, 다른 형식

{
  "info": {
    "name": "Get User Profile",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [{
    "name": "Get User Profile",
    "request": {
      "method": "GET",
      "header": [
        { "key": "Accept", "value": "application/json" },
        { "key": "X-Request-ID", "value": "{{$guid}}" }
      ],
      "url": "https://api.example.com/users/{{userId}}",
      "auth": { "type": "bearer", "bearer": [{ "key": "token", "value": "{{authToken}}" }] }
    },
    "event": [{
      "listen": "test",
      "script": { "exec": ["pm.test(\"status is 200\", () => pm.response.to.have.status(200));"] }
    }]
  }]
}

저는 두 형식 다 본 다음 — 사람이 읽을 수 있는 텍스트 파일 쪽이 압도적으로 유지 보수 편하다고 느꼈어요.

02 · AT A GLANCE핵심 정보 4개로 정리

저는 도구 살펴볼 때 항상 4가지를 먼저 확인해요. 저는 라이선스 / 저장 형식 / 실행 환경 / 유료 옵션 순서로 봐요. 저는 Bruno 를 다음과 같이 정리했어요:

라이선스

MIT

코어 완전 무료, 상용 사용 자유

저장 형식

.bru 평문 텍스트

Git 친화 / DB 의존 X

실행 환경

Desktop + CLI

macOS · Windows · Linux + bru CLI

유료 옵션

Golden Edition

일회성 라이선스 / 좌석 과금 X

저는 마지막 항목 — 일회성 라이선스 — 가 가장 인상적이었어요. Postman 은 좌석당 매월 과금이라 팀 단위 컬렉션 공유 = 유료 플랜 진입이에요. Bruno 는 한 번 사면 끝이고요.

설치 — macOS 기준

# 데스크탑 (Homebrew)
brew install --cask bruno

# CLI — CI 자동화용
npm install -g @usebruno/cli

# 또는 npx 1회 실행
npx @usebruno/cli run ./api-tests --env staging

저는 폴더 구조도 한 번 정리했어요. Bruno 는 컬렉션이 그냥 폴더예요. 환경별 파일까지 다 평문이에요:

제 Bruno 컬렉션 폴더 구조

api-tests/
├── bruno.json                    # 컬렉션 메타
├── environments/
│   ├── local.bru                 # 로컬 환경 변수
│   ├── staging.bru               # 스테이징
│   └── production.bru            # 프로덕션
├── auth/
│   ├── Login.bru                 # POST /auth/login
│   └── Refresh Token.bru
├── users/
│   ├── Get User Profile.bru
│   ├── Update User.bru
│   └── Delete User.bru
└── orders/
    ├── List Orders.bru
    └── Create Order.bru

03 · WHEN TO PICK이런 팀이면 검토할 만해요

저는 Bruno 가 모든 팀에 맞는 답이라고 보진 않아요. 특정 시그널이 겹치는 팀에만 효과가 나오는 도구예요. 제가 정리한 적합 시그널 5가지예요:

  • API 컬렉션을 코드 레포에 함께 두고 싶은 팀 백엔드 PR 에 .bru 파일 변경 동봉. 코드 리뷰 흐름과 API 변경 리뷰 통합
  • 사내 보안 정책상 외부 클라우드 동기화가 불편한 환경 금융 · 의료 등 데이터 외부 반출 제약. Bruno 는 로컬 저장이 기본
  • Postman 유료 좌석 비용이 점점 부담되는 규모 팀 단위 컬렉션 공유 = 유료 플랜 진입. 좌석 수만큼 비용 증가
  • CI 에서 API 회귀 테스트를 돌리고 싶은 경우 bru CLI 로 동일 컬렉션 실행. 별도 환경 셋업 없음
  • REST 중심 워크플로우 (GraphQL · gRPC 의존도 낮은 팀) REST · GraphQL 지원, gRPC 는 로드맵 단계

저는 위 5개 중 3개 이상 해당하면 시범 도입을 권장해요. 저는 환경 변수 파일도 같이 Git 에 박아두는 패턴이 마음에 들었어요:

environments/staging.bru — 환경별 변수

vars {
  baseUrl: https://staging-api.example.com
  authToken: {{process.env.STAGING_AUTH_TOKEN}}
  userId: 12345
}

vars:secret [
  authToken
]

저는 secret 으로 마킹된 변수는 Git 에 빈 값으로 커밋되고, 실제 값은 환경 변수에서 주입돼서 보안도 OK 라는 점이 좋았어요.

CI 통합 — GitHub Actions 예시

name: API Regression
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm install -g @usebruno/cli
      - run: bru run ./api-tests --env staging
        env:
          BRU_AUTH_TOKEN: ${{ secrets.STAGING_TOKEN }}

04 · KNOWN LIMITSBruno 가 아직 약한 곳

저는 도구를 권할 때 약점도 같이 짚는 걸 원칙으로 해요. 저는 Bruno 도 완벽하진 않다고 봐요.

KNOWN LIMITATIONS

Postman 만큼의 통합 생태계는 아직 없어요

SaaS 통합 기능 부재 — 실시간 협업 편집, 클라우드 모니터링, Mock 서버, 자동 문서화 호스팅 같은 Postman 의 시그너처 SaaS 기능들은 아직이에요.

Git 워크플로우 의존 — Bruno 의 "실시간 동기화" 는 결국 git push / pull 흐름이에요. Git 워크플로우가 안 잡힌 팀에는 오히려 마찰이 될 수 있어요.

저는 Git 협업이 익숙한 백엔드 · 인프라 팀이면 강점, 디자이너 · QA 가 직접 API 만지는 환경이면 약점이라고 봐요. 저는 제가 운영 중인 백엔드 1개 프로젝트에 먼저 시범 도입했어요. 5명 팀 중 4명이 Git 익숙해서 마찰 없이 안착했어요.

제 실제 bru CLI 실행 출력

$ bru run ./api-tests --env staging

Running Folder: api-tests
  ✓ auth/Login.bru                  127ms
  ✓ auth/Refresh Token.bru          89ms
  ✓ users/Get User Profile.bru      342ms
  ✓ users/Update User.bru           512ms
  ✓ orders/List Orders.bru          203ms
  ✓ orders/Create Order.bru         678ms

6 requests, 6 passed, 0 failed
Total time: 1.95s

Postman → Bruno 마이그레이션

# 1. Postman 에서 컬렉션 export (JSON)
#    Collections → ... → Export → Collection v2.1

# 2. Bruno 데스크탑 열기
#    File → Import Collection → Postman Collection
#    JSON 파일 선택 → .bru 파일들 자동 생성

# 3. Git 에 커밋
git add api-tests/
git commit -m "import: API collection from Postman"
git push

기존 Postman 컬렉션은 JSON 으로 내보내 Bruno 에 그대로 import 돼요. 저는 작은 사이드 프로젝트 하나에 먼저 붙여보고 판단하는 게 안전하다고 봐요.

CODA제가 결론 한 줄로 박는다면

저는 Bruno 를 한 줄로 요약하면 이렇게 말해요. 저는 이게 도구의 본질이라고 깨달았어요.

Bruno 의 가치는 기능이 아니라 'API 정의도 코드처럼 다루자' 는 철학이에요. 그 철학을 받아들이는 팀에만 진짜 가치가 나와요.

— 에디 · 도구 관찰 노트

CODA

좋은 도구는 기능 목록이 아니라 자기 철학에 맞는 팀을 알아봐요.

면책: 제가 공개 자료를 기반으로 정리한 도구 관찰 노트예요. 가격·기능은 시점에 따라 변동될 수 있어요. 광고·제휴 X.

반응형

📚 같이 보면 좋은

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 일정액의 수수료를 제공받습니다."