북마크릿으로 디바이스에 상관없이 서버로 데이터 보내기
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을 고정으로 넣어두면 어느 기기에서 클릭해도 같은 엔드포인트로 데이터가 모인다.
- [방법 1]: Beacon 엔드포인트 구성. Flask에 CORS 헤더 없는 POST 라우트를 두고 body를 메모리에 저장한다.
- 분석 및 해결 프로세스 (Analysis Flow):
- 도구/기술: Flask 수신 서버,
navigator.sendBeacon문자열 스니펫,requests로 재현한 전송 테스트. - 주요 단계:
/collect엔드포인트 준비(CORS 헤더 없음) $\rightarrow$ 북마크릿에 현재 페이지 title·URL을 담아 sendBeacon 호출하도록 구성 $\rightarrow$ 서버가 body를 메모리 리스트에 적재 $\rightarrow$ 누적 건수 확인. - 결과 도출 및 검증:
/collect에text/plain으로 JSON 페이로드를 전송한 결과 status 204와 함께 정상 수신됐고, 서버 메모리 리스트의 누적 건수가 1건 증가했다. CORS 헤더를 별도로 설정하지 않아도 전송이 성공했다.
- 도구/기술: Flask 수신 서버,
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.