BOJ Snippets Mogiyoon
백준 문제풀이용 코드 스니펫 자동 삽입 크롬 확장프로그램
개요
기간
2026.04
개요
개인 프로젝트
주요 기능
언어별 스니펫 자동 삽입, 수동 삽입 버튼, 스니펫/규칙 커스터마이징, 크롬 계정 동기화
사용 기술
구현 기능 및 개발 과정
개발 동기
백준에서 문제를 풀 때마다 C++의 ios::sync_with_stdio(false), Python의 sys.stdin.readline, Java의 BufferedReader, JavaScript의 readline 등 동일한 보일러플레이트 코드를 반복 작성해야 함. 풀이와 무관하나 필수적인 코드를 매번 타이핑하는 과정에서 비효율과 휴먼 에러가 발생함.
CodeMirror 에디터 코드 주입
백준의 코드 에디터는 단순 textarea가 아닌 CodeMirror 라이브러리로 구현되어 있어, CodeMirror의 setValue() 함수로만 코드 삽입이 가능함.
크롬 확장프로그램의 Content Script는 Isolated World에서 실행되어 HTML 요소는 접근 가능하나 웹페이지의 JS 객체에는 접근 불가.
Background Service Worker에서 chrome.scripting.executeScript API를 사용하여 브라우저가 직접 웹페이지 컨텍스트에서 코드를 실행하는 방식으로 해결함.
저장 구조 설계
스니펫과 언어 매칭 규칙을 chrome.storage.sync에 저장. 스니펫은 키-값(언어명-코드) 형태로, 매칭 규칙은 matchType/pattern/presetKey 구조의 배열로 관리됨.
백준에서 'Python 3' 선택 시, 규칙을 순회하여 'python'이 포함된 규칙을 탐색하고 해당 키의 스니펫을 에디터에 삽입. 옵션 페이지에서 규칙과 스니펫의 추가/수정/삭제가 가능함.
언어 이름과 스니펫을 잇는 규칙을 목록으로 관리함. 'PyPy3'처럼 이름이 달라도 규칙 한 줄만 추가하면 됨. 규칙은 위에서부터 검사하므로 순서가 곧 우선순위임.
트러블 슈팅
Isolated World + CSP 차단 문제
크롬 확장프로그램과 웹페이지는 동일한 HTML을 공유하나 JS 변수는 격리되어 있음(Isolated World). CodeMirror의 JS 객체에 접근하기 위해 웹페이지 컨텍스트에서의 코드 실행이 필요했음.
시도 1: 페이지에 <script> 태그 직접 주입 → 백준의 CSP(Content Security Policy)에 의해 차단.
시도 2: Manifest V3의 world: 'MAIN' 옵션 적용 → 내부적으로 인라인 스크립트를 생성하므로 동일하게 CSP에 차단.
시도 3: 확장프로그램 파일을 <script src>로 로드 → chrome-extension:// 프로토콜 역시 CSP에 의해 차단.
최종 해결: Background Service Worker에서 chrome.scripting.executeScript를 world: 'MAIN' 옵션과 함께 사용.
크롬 브라우저 자체가 실행하는 방식이므로 CSP 제한을 회피할 수 있었음.
Chosen 라이브러리 이벤트 감지 문제
백준의 Chosen UI 라이브러리 기반 드롭다운 렌더링 구조. 실제 <select> 태그는 숨기고 Chosen이 만든 커스텀 UI를 보여주는 구조라 change 이벤트만으로는 언어 변경을 놓칠 수 있음.
3중 감시 체계 구축. (1) 기본 change 이벤트 리스너, (2) MutationObserver 기반 DOM 속성 변경 감시, (3) 500ms 간격 폴링 기반 값 변경 확인.
세 가지 방식을 병행하여 모든 상황에서 언어 변경을 감지함.
Extension Context Invalidated 에러
개발 중 확장프로그램 새로고침 시 Extension context invalidated 에러가 발생함. 확장프로그램 재시작 시 기존 페이지의 Content Script가 이전 확장프로그램 인스턴스에 연결된 상태로 유지되기 때문임.
개발 환경에서만 발생하는 문제로, 확장프로그램 새로고침 후 백준 페이지도 함께 새로고침하여 해결함.
결과 및 회고
배운 점
기획, 구현, 트러블슈팅 전 과정을 Claude를 활용한 바이브 코딩으로 진행함. 사용자는 요구사항 정의와 결과 검증을 담당함.
웹페이지의 JavaScript 객체에 접근하는 방법을 탐색하는 과정에서 세 차례의 시도가 CSP에 의해 차단됨. 실패한 시도를 삭제하지 않고 유지하여 각 방법이 차단된 원인을 확인할 수 있도록 함.
언어 이름과 스니펫을 잇는 규칙을 목록으로 관리하면 새 언어를 코드 수정 없이 추가할 수 있음.
회고
확장 프로그램 구조를 직접 설계하지 않고도 동작하는 결과물을 구현할 수 있었음. 다만 각 시도가 차단된 원인은 코드를 다시 검토해야 설명할 수 있었음.
옵션 페이지에서 규칙과 스니펫을 직접 편집하게 두어, 언어가 늘어도 코드를 고치지 않는 구조를 만듦.
규칙을 위에서부터 검사하는 구조라 순서가 곧 우선순위가 됨. 목록의 순서 자체가 동작을 결정하는 설계를 경험함.
라이선스
