ApiCatcher 실시간 동기화 사용 가이드

휴대폰에서 캡처한 HTTP/HTTPS 트래픽을 컴퓨터나 다른 시스템으로 실시간 전송합니다.

프로토콜 설명: Real-time Sync Protocol


1. 기능 개요

ApiCatcher는 iOS와 Android에서 VPN으로 트래픽을 캡처한 뒤, 같은 LAN에 있는 수신기로 WebSocket을 통해 스트리밍합니다. 캡처를 시작하는 즉시 전송되므로 세션이 끝날 때까지 기다렸다가 파일을 내보낼 필요가 없습니다.

수신기용도연결 방법
ApiCatcher Desktop컴퓨터에서 트래픽 확인, 분석, 리플레이Desktop QR 코드를 스캔
Burp Suite 확장Burp에서 보안 테스트확장 화면의 QR 코드를 스캔
사용자 정의 수신기자체 서비스나 사내 시스템ws:// 주소를 입력하고 연결 테스트

한 번에 하나만 켤 수 있습니다. 하나를 켜면 나머지 둘은 꺼집니다.


2. 활용 사례

컴퓨터에서 트래픽을 확인합니다. JSON이 크거나 헤더가 길거나 Body가 바이너리 데이터인 경우 휴대폰에서는 확인하기 어렵습니다. Desktop에 연결하면 컴퓨터에서 파싱, 비교, 리플레이할 수 있습니다.

Burp Suite로 전송합니다. ApiCatcher for Burp Suite Extension을 설치하면 휴대폰에서 캡처한 HTTP 트래픽을 Site map 또는 Proxy History로 전송한 뒤, 필요한 요청을 Repeater나 Intruder로 보낼 수 있습니다. 캡처는 휴대폰의 VPN을 통해 이루어지므로 컴퓨터에 시스템 프록시를 설정할 필요가 없습니다.

API 보안 검사 또는 DLP 플랫폼으로 전송합니다. 앱을 테스트할 때 캡처와 실시간 동기화를 활성화합니다. 트래픽을 사내 탐지 플랫폼으로 전송하여 주민등록번호, 휴대전화 번호, 토큰, 비밀 키 등의 민감 정보를 탐지합니다. 데이터 유출 가능성이 있는 API를 식별한 뒤 보고서를 생성하여 개발팀 또는 테스트팀에 전달할 수 있습니다.

실제 트래픽을 기반으로 API 문서를 업데이트합니다. 수신기는 이전에 수집한 필드와 비교하여 요청이나 응답에 새로 추가되었을 가능성이 있는 필드를 식별합니다. 대규모 언어 모델로 용도와 설명의 초안을 작성한 뒤 문서 담당자에게 이메일로 알릴 수 있습니다.

자동화 또는 Mock에 활용합니다. 완전한 요청을 테스트 데이터로 저장하거나 Mock을 생성하는 데 사용할 수 있습니다.


3. 시작하기 전에

  1. HTTPS를 복호화하려면 ApiCatcher 루트 인증서를 설치하고 완전히 신뢰해야 합니다.
  2. 휴대폰과 수신기를 같은 Wi-Fi에 연결하세요. 데이터 보안을 위해 현재는 LAN의 ws:// 연결만 지원합니다. wss://는 지원하지 않으며 트래픽은 LAN 밖으로 나가지 않습니다.
  3. 컴퓨터나 서버 방화벽에서 수신 포트(예: 8080)를 열어 두세요.
  4. 수신기를 먼저 실행한 다음 앱에서 연결을 테스트하세요.

4. 실시간 동기화 켜기

  1. ApiCatcher를 열고 캡처 홈으로 갑니다.
  2. 오른쪽 위 「+」를 누릅니다.
  3. Real-time Sync를 선택합니다.
  4. 상단에는 Desktop / Burp Suite / Custom Receiver 탭이 있습니다.

활성화하면 홈 화면에 Real-time Sync Active와 수신기의 Online 또는 Offline 상태가 표시됩니다. 해당 안내를 누르면 설정 화면으로 돌아갑니다.


5. ApiCatcher Desktop에 연결

  1. apicatcher.net에서 ApiCatcher Desktop을 받아 실행합니다.
  2. Desktop에서 실시간 동기화 수신을 시작하면 QR 코드가 나옵니다.
  3. 휴대폰에서 Real-time Sync → Desktop을 엽니다.
  4. Scan QR Code를 누르고 Desktop에 표시된 코드를 스캔합니다.
  5. 성공하면 수신 주소와 온라인 상태가 보입니다.
  6. Enable을 켭니다.
  7. 홈으로 돌아가 VPN 캡처를 켜고 대상 앱을 조작합니다. Desktop에 요청이 쌓이기 시작합니다.

오프라인으로 표시되면 Desktop이 실행 중인지, 휴대폰과 컴퓨터가 같은 서브넷에 연결되어 있는지 확인한 뒤 다시 스캔하세요.

ApiCatcher Desktop 실시간 동기화 수신


6. Burp Suite에 연결

확장 안내: ApiCatcher for Burp Suite Extension

  1. 확장 프로그램의 .jar 파일을 받거나 직접 빌드한 뒤, Burp의 Extensions → Installed → Add에서 Java 확장 프로그램으로 로드합니다.
  2. 상단의 ApiCatcher 탭을 열고 WebSocket 서버가 실행 중인지 확인합니다. 실행 중이 아니면 Start Server를 누릅니다.
  3. 휴대폰에서 Real-time Sync → Burp Suite를 열고 확장 화면의 QR 코드를 스캔합니다.
  4. Enable 스위치를 켠 다음 캡처를 시작합니다.
  5. 기본은 Target → Site map입니다. 요청·응답 전체를 보려면 동기화 대상을 Proxy → HTTP history로 바꿉니다. History로 간 요청에는 X-ApiCatcher-RequestId가 붙습니다.
  6. 이후 Repeater, Intruder로 보낼 수 있습니다.

동기화에 문제가 있으면 Extensions → Installed에서 이 확장 프로그램을 선택하고 아래의 Output / Errors를 확인하세요.

ApiCatcher for Burp Suite 확장 설정


7. 사용자 정의 수신기에 연결

  1. 컴퓨터나 사내망에서 수신기를 먼저 실행합니다(8절 참조). 주소는 ws://192.168.1.75:8080 형태입니다.
  2. 휴대폰에서 Real-time Sync → Custom Receiver를 엽니다.
  3. Remote URLws://IP:포트를 입력합니다. 오른쪽의 Documentation에서 프로토콜 설명을 확인할 수 있습니다.
  4. Test Connection을 누릅니다. 연결에 성공하면 주소가 저장됩니다.
  5. Enable Real-time Streaming을 켭니다. 주소가 비어 있거나 연결 테스트에 실패하면 스위치가 켜지지 않습니다.
  6. 주소를 바꾸면 스위치가 꺼집니다. 다시 테스트한 뒤에 켜세요.
  7. 캡처를 시작하면 수신기에 JSON 프레임이 들어옵니다.

http:// 또는 wss://를 입력하지 마세요. 127.0.0.1은 휴대폰 자체를 가리키므로 사용할 수 없습니다.


8. 사용자 정의 수신기에서 프로토콜 구현

설명: README.md
저장소: apicatcher-realtime-sync-protocol
Java SDK: apicatcher-sync-sdk-java

8.1 연결

역할누구
WebSocket ClientApiCatcher 앱
WebSocket Server사용자 정의 수신기
  • LAN의 ws://를 사용합니다(데이터 보안을 위해 wss://는 지원하지 않으며 트래픽은 LAN 안에 유지됩니다)
  • 연결이 끊기면 앱이 자동으로 다시 연결합니다
  • 연결이 끊긴 동안 캡처한 데이터와 전송이 완료되지 않은 조각은 폐기됩니다. 재전송되지 않습니다
  • 하나의 연결에서 여러 요청이 교차 전송되므로 반드시 requestId로 그룹화합니다

8.2 메시지 형식

각 메시지는 JSON Text Frame입니다.

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "req_start",
  "timestamp": 1711268370123,
  "payload": {}
}
필드의미
type지금은 http
requestId한 요청의 UUID. 조각은 이 값으로 모읍니다
event아래 이벤트
timestamp밀리초 단위의 타임스탬프
payload그 이벤트의 데이터

8.3 이벤트

한 요청의 일반적인 순서는 다음과 같습니다.

req_start → req_body* → res_start → res_body* → req_end

req_body / res_body는 없을 수도 있고 여러 조각으로 나뉠 수도 있습니다. Body가 없으면 해당 이벤트도 전송되지 않습니다.

req_start — 요청이 나가기 시작:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "req_start",
  "timestamp": 1711268370123,
  "payload": {
    "url": "https://api.example.com/data",
    "method": "POST",
    "httpVersion": "HTTP/1.1",
    "headers": [{"name": "User-Agent", "value": "ApiCatcher/1.0"}]
  }
}

받으면 requestId로 캐시를 만들고 URL, 메서드, 요청 헤더를 넣습니다.

req_body / res_body — Body 조각:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "res_body",
  "timestamp": 1711268370123,
  "payload": {
    "data": "eyBzdWNjZXNz..."
  }
}

payload.data에는 바이너리 데이터를 Base64로 인코딩한 문자열이 들어 있습니다. 프레임은 순서대로 전송되며 WebSocket은 TCP를 기반으로 하므로 도착 순서와 전송 순서가 같습니다. 도착한 순서대로 디코딩하여 이어 붙이세요. 큰 Body는 약 16~32KB 단위의 여러 조각으로 나뉩니다. 전체 Body가 한 번에 도착할 때까지 기다리지 마세요.

res_start — 응답 헤더 도착:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "res_start",
  "timestamp": 1711268370123,
  "payload": {
    "status": 200,
    "httpVersion": "HTTP/1.1",
    "headers": [{"name": "Content-Type", "value": "application/json"}]
  }
}

req_end — 이 요청이 끝남:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "req_end",
  "timestamp": 1711268370123,
  "payload": {
    "error": null,
    "timings": {
      "send": 0,
      "wait": 150,
      "receive": 5
    }
  }
}
  • errornull이면 정상 종료입니다. 아니면 "Timeout", "Connection Aborted" 같은 설명입니다
  • timings 단위는 밀리초입니다. 송신, 응답 대기, 수신
  • req_end를 받은 뒤에 한 건으로 조립하고 캐시를 지웁니다
  • WebSocket이 끊기면 req_end를 못 받은 기록은 전부 버립니다

8.4 조립

연결 수립
  └─ map: requestId → 조립 중인 요청

JSON 프레임 수신
  ├─ req_start  → 새로 만들고 url / method / headers 기록
  ├─ req_body   → Base64 디코드 후 요청 Body에 붙임
  ├─ res_start  → status / 응답 헤더 기록
  ├─ res_body   → Base64 디코드 후 응답 Body에 붙임
  └─ req_end    → error / timings 기록, 후속 처리 로직으로 전달하고 map에서 삭제

연결 끊김
  └─ map을 비움. 미완성 요청을 완료된 요청으로 처리하지 않음

스캔, 저장, 문서 갱신은 req_end 이후에 하세요. 조각이 오는 동안 Body는 아직 덜 모였습니다.

8.5 Java SDK 사용

apicatcher-sync-sdk-java가 WebSocket 서버와 조각 조립을 처리합니다. 요청 하나가 완성되면 HAR 1.2 엔트리 JSON 한 건을 콜백으로 전달합니다(HAR 파일 전체가 아닙니다).

환경: JDK 11 이상, Maven 3.x 이상.

리스너:

import com.apicatcher.sync.TrafficListener;

public class StandardConsoleListener implements TrafficListener {
    @Override
    public void onTrafficReceived(String harJson) {
        System.out.println("Received a complete request:");
        System.out.println(harJson);
    }
}

시작:

import com.apicatcher.sync.ApiCatcherReceiver;

public class App {
    public static void main(String[] args) {
        int port = 8080;
        ApiCatcherReceiver receiver =
            new ApiCatcherReceiver(port, new StandardConsoleListener());
        receiver.start();
        System.out.println("Listening on port " + port);
    }
}

휴대폰에는 ws://<이 컴퓨터의 LAN IP>:8080을 넣습니다. 방화벽에서 그 포트를 열어 두세요.

onTrafficReceived에서 민감 필드를 탐지하거나, 기존 문서와 차이를 비교하거나, 분석 서비스로 전달하거나, 메시지 큐에 기록할 수 있습니다.

8.6 직접 파싱할 때

  • Text Frame만 다루고 requestId로 묶습니다
  • Body는 도착 순서대로 이어 붙입니다. timestamp로 다시 정렬하지 마세요
  • 동시에 나가는 요청은 섞여 옵니다. requestId로 분리해야 합니다
  • 끊기면 끝나지 않은 기록은 버립니다. 프로토콜은 재전송하지 않습니다
  • 현재 명세 버전은 1.0.0-Draft입니다. 알 수 없는 event는 무시하고 처리를 중단하지 마세요

9. 일반적인 사용 절차

캡처해서 보안 검사

  1. 사내 수신기를 먼저 실행합니다
  2. 휴대폰에서 QR 코드를 스캔하거나 ws:// 주소를 입력하고, 연결 테스트 후 활성화합니다
  3. 캡처를 시작하고 테스트 사례에 따라 앱을 조작합니다
  4. 플랫폼에서 완전한 요청의 민감 필드를 탐지합니다
  5. URL, 필드명, 요청 헤더 / Query / Body 중 어느 위치에서 발견되었는지를 포함한 보고서를 이메일 또는 메신저로 전송합니다

트래픽을 기반으로 문서 업데이트

  1. 수신기가 각 API의 최근 요청과 응답을 저장합니다
  2. 경로와 메서드를 기준으로 필드를 비교합니다
  3. 새로 추가되었거나 타입이 변경된 필드를 모델에 전달하여 설명을 생성합니다
  4. 업데이트 목록을 정리하여 API 담당자에게 이메일로 보냅니다

Burp에서 보안 테스트

  1. 확장 프로그램을 설치하고 Start Server를 누릅니다
  2. 앱에서 QR 코드를 스캔하고 Burp 동기화를 활성화합니다
  3. 캡처 후 Site map에서 API를 확인하고 History에서 테스트할 요청을 선택합니다

10. 자주 묻는 질문

연결 테스트가 실패합니다
수신기가 실행 중인지, IP가 이 컴퓨터의 LAN 주소인지, 포트가 열려 있는지, 같은 서브넷에 연결되어 있는지 확인하세요. 127.0.0.1 또는 http://는 사용할 수 없습니다.

스위치가 켜지지 않습니다
주소는 비워 둘 수 없습니다. 사용자 정의 수신기는 연결 테스트를 먼저 통과해야 합니다.

홈은 오프라인인데 수신기는 돌아가고 있습니다
컴퓨터가 절전 모드로 전환되거나 Wi-Fi가 변경되거나 수신기 프로세스가 종료되면 오프라인으로 표시됩니다. 설정에서 상태를 확인하세요. Desktop / Burp는 QR 코드를 다시 스캔할 수 있습니다.

일부 요청이 컴퓨터에 안 보입니다
연결이 끊긴 동안 캡처한 트래픽은 다시 전송되지 않습니다. 동기화를 활성화한 뒤 캡처하세요. 필터 또는 도메인 차단 목록으로 인해 일부 트래픽이 MITM을 거치지 않을 수도 있습니다.

수신기 셋을 같이 켤 수 있나요
아니요. 우선순위는 Desktop → Burp Suite → 사용자 정의 수신기이며 한 번에 하나만 연결됩니다.

왜 HAR 파일 하나로 안 보내나요
큰 Body를 VPN 프로세스에서 하나의 대형 JSON으로 만들면 메모리가 부족해질 수 있습니다. 이 프로토콜은 Body를 여러 조각으로 나누어 전송하며, Java SDK가 수신기에서 HAR 엔트리로 다시 조립합니다.

홈 상태가 계속 돌아갑니다
WebSocket 연결 상태를 확인하는 중입니다. 상태 확인이 계속 완료되지 않으면 네트워크와 수신기 프로세스를 확인하세요.


11. 관련 링크