Post

북마크릿으로 디바이스에 상관없이 서버로 데이터 보내기

Beacon API와 JSONP 비콘으로 브라우저 북마크릿에서 CORS 없이 내 서버에 데이터를 전달하는 방법을 정리했다

북마크릿으로 디바이스에 상관없이 서버로 데이터 보내기

북마크릿으로 디바이스에 상관없이 서버로 데이터 보내기

북마크릿에서 DOM 데이터를 읽었는데 내 서버로 보내려니 CORS 오류가 났다. Beacon API를 쓰면 Preflight 없이 POST가 됐다. 어느 기기 브라우저에서 실행해도 같은 서버로 데이터가 모인다.

1. 서론 (Introduction)

  • 문제/상황 (Problem): 북마크릿에서 현재 페이지 데이터를 추출했는데 내 서버로 보내는 게 문제였다. fetch로 다른 도메인에 POST하면 CORS Preflight 오류가 났다.
  • 목적 (Purpose): CORS 제약 없이 북마크릿에서 내 서버로 데이터를 전송하는 방법을 정리한다.
  • 대상 (Target Audience): 브라우저에서 수집한 데이터를 서버로 보내야 하는 개발자.

2. 방법 및 과정 (Methods & Process)

  • 배경 조사 및 데이터 (Data Collection): navigator.sendBeacon(url, data)는 브라우저가 제공하는 단방향 전송 API로 서버에 데이터를 POST하되 응답을 기다리지 않는다. 결정적으로 CORS Preflight 없이 동작하고, 페이지 이동이나 탭 종료 중에도 전송이 완료된다. 제약은 응답 내용을 읽을 수 없는 점과, CORS Simple Request 조건(text/plain, application/x-www-form-urlencoded, multipart/form-data)을 지켜야 하는 점 두 가지다. JSONP는 <script src="내서버?data=..."> 형태로 GET 요청을 보내는 방식으로, <script> 태그가 Same-Origin 제약을 받지 않는 점을 이용한다. URL 길이 제한(약 2,000자) 안에 들어가는 데이터에 적합하다.
전송 방식Preflight응답 읽기데이터 크기 제약
Beacon API없음불가없음(Simple Request 형식 준수)
JSONP 비콘없음(스크립트 로드)콜백으로 가능URL 길이 제한(약 2,000자)
일반 fetch(교차 출처)있음헤더 허용 시 가능없음
  • 접근 방법 (Approach Methods):
    • [방법 1]: Beacon 엔드포인트 구성. Flask에 CORS 헤더 없는 POST 라우트를 두고 body를 메모리에 저장한다. sendBeacon은 JSON을 text/plain으로 직렬화해서 보내면 Simple Request 조건을 만족한다.
    • [방법 2]: 어느 기기에서든 같은 서버로 수집. 모바일 브라우저, 태블릿, PC 어느 기기에서든 북마크릿은 동일하게 실행되므로 내 서버 URL을 고정으로 넣어두면 어느 기기에서 클릭해도 같은 엔드포인트로 데이터가 모인다.
  • 분석 및 해결 프로세스 (Analysis Flow):
    • 도구/기술: Flask 수신 서버, navigator.sendBeacon 문자열 스니펫, requests로 재현한 전송 테스트.
    • 주요 단계: /collect 엔드포인트 준비(CORS 헤더 없음) $\rightarrow$ 북마크릿에 현재 페이지 title·URL을 담아 sendBeacon 호출하도록 구성 $\rightarrow$ 서버가 body를 메모리 리스트에 적재 $\rightarrow$ 누적 건수 확인.
    • 결과 도출 및 검증: /collecttext/plain으로 JSON 페이로드를 전송한 결과 status 204와 함께 정상 수신됐고, 서버 메모리 리스트의 누적 건수가 1건 증가했다. CORS 헤더를 별도로 설정하지 않아도 전송이 성공했다.

3. 결과 (Results)

  • 분석 결과 요약: Beacon API로 북마크릿에서 내 서버 /collect 엔드포인트에 데이터를 보내는 게 됐다. CORS 오류가 사라졌고 별도의 서버 CORS 설정도 필요 없었다. 같은 북마크릿을 모바일과 PC에서 동시에 써서 수집 속도를 높일 수 있는 구조도 확인했다.

4. 인사이트 및 액션 (Insights & Action)

  • 인사이트 (Insight): Beacon API는 “발사 후 잊음(fire-and-forget)”으로 설계됐다. 브라우저가 전송을 보장하지만 응답 확인은 없다. 수집 데이터처럼 응답이 불필요한 경우에 딱 맞는다.
  • 실행 방안 (Action Plan): 서버 수신 엔드포인트에 IP·타임스탬프·User-Agent를 함께 로깅하면 어느 기기에서 보낸 데이터인지 추적할 수 있다.
  • 한 줄 결론 (Key Takeaway): Beacon은 응답 없이 보내는 브라우저 내장 POST다. 북마크릿의 CORS 문제를 가장 간단히 해결한다. 샘플 코드
  • 다음 스텝 (Next Step): 이번 데모는 단발성 전송만 확인했다. 짧은 시간에 여러 기기에서 동시에 Beacon이 들어올 때 서버 쪽 중복 제거나 순서 보장이 필요한지는 별도로 확인해야 한다.

This post is licensed under CC BY 4.0 by the author.