Programmers-helper 확장 만들기
코덱스를 처음 써보면서 했던 처음의 생각은 “지금 진행 중인 프로젝트가 없는데, 뭘로 성능 테스트를해볼까? ” 이다.
그래서 이 도구를 활용해서 할만한 적당한 난이도의 프로젝트가 뭘지 고민했고, 고민 끝에 코딩테스트용 도구 extension 만들기를 해보기로 결심했다.
백준이 문을 닫으면서, 한국에서 코딩테스트로 연습할만한 풀이 사이트가 코드트리, 프로그래머스 정도 있고, 정보올림피아드에서도 푼다고 하는데 익숙한 사이트는 프로그래머스 였기에, 문제수는 아쉽지만 그냥 고민하기 보다 시작해보기로했다.
처음에 정한 이 확장의 요구사항은
- C++를 기반으로 코딩테스트를 하는 ‘나’ 를 위해 만든다.
- 프로그래머스의 문제번호를 통해 사이트를 크롤링하여, 왼쪽 탭에 문제.md를, 오른쪽 탭에 solution.cpp을 띄운다
- 테스트 케이스를 파싱하여, 샘플테스트를 할 수 있게 한다.
- 샘플 테스트의 첫번째 케이스를 가지고 커스텀 테스트로 저장하고, 사용자가 조작할수 있게 한다.
정도이다.
하지만 점점 코덱스의 성능을 확인하면서, 이보다 더 복잡한 기능들도 잘 구현하겠다는 확신이 들었고, 더 많은 기능을 추가하기로한다. 주로 사용하면서 있었으면 좋겠다는 기능 위주로 추가하였다.
이후 추가된 요구 사항
- 실행 환경을 도커환경, 로컬환경으로 나누어 사용자가 선택할 수 있게 한다.
- 로컬 환경에서는 각 실행파일에 대한 fingerprint를 계산하여, 동일한 코드일시 컴파일하지 않고 실행.
- 상태메시지를 출력하여, 현재 테스트환경에 대해 지속적으로 피드백한다.
- 언어를 cpp, Java, Python 세개의 언어를 지원하고, 이 언어를 고를시 문제를 다시 선택할때 사이트에서 크롤링한다.
- 런타임에러, 컴파일에러에 대해 정돈된 에러메시지를 출력한다.
- 풀이기록, 메모 기능을 추가하여, 이전에 풀었던 문제를 다시보고, 다시 실행해보고, 메모를 통해 메모한 내용을 복습할수 있게한다.
- 문제 목록 스크롤에 auto focus 기능을 추가하여, 현재 문제에 focus되게 한다
- extension 초기 로드시 lazy load를 하게끔하여, 초기 로드 지연을 줄인다.
- git release를 통한 vsix파일 배포
- Marketplace를 통해 마켓플레이스 등록 및 배포
- 타이머 기능을 추가한다.
- 키 바인딩을 할수 있게 하여, 특정기능들을 편하게 쓸수 있게 한다 (샘플테스트, 메모 등등)
- 문제 목록을 github 레포로 관리할수 있게끔 옵션 부여하여, 다른 환경에서도 문제 목록이 유지되게끔 한다.
- 혹여나 파일 충돌이 발생시, 따로 webview를 통해 사용자가 충돌 파일들을 수정하고 merge 하여 레포를 갱신할수 있게끔 함.
- 지속적인 최적화
최적화에 특히 많은 신경을 씀
- 렌더링 최적화
- 문제 row를 key 기반 DOM Map으로 관리해 전체 HTML을 다시 만들지 않고 변경된 요소만 부분 렌더링하도록 수정했다.
- 문제 목록 캐시 JSON을 활용해 매번 폴더 전체를 스캔하지 않도록 하고, 파일 I/O 지연을 줄였다.
- 검색 입력에는 debounce를 적용해 연속 입력 중 불필요한 렌더링을 줄였다.
- Docker 컨테이너 최적화 1. Docker 컨테이너 준비를 확장 시작 시점이 아니라 문제 열기나 테스트 실행 시점까지 지연시켰다. 2. 사용자가 실수로 extension을 열었을 때 컨테이너가 자동으로 준비되는 상황을 막았다. 3. VS Code 종료 시 사용 중이던 helper 컨테이너를 자동 정리하도록 했다.
- 테스트 실행 최적화
1. 풀이 코드, 생성 runner, 컴파일 옵션, 실행 대상 경로를 fingerprint로 계산해 동일한 코드라면 기존 컴파일 artifact를 재사용했다.
2. 샘플 테스트는 저장된
programmers.json의 examples를 우선 사용하고, 필요할 때만problem.md를 fallback으로 파싱했다. - 타이머 최적화
1. 매초 값을 누적 저장하지 않고,
startedAt과 현재 시간의 차이를 기준으로 표시 시간을 계산했다. 2. 타이머 UI는 실행 중일 때만 1초 주기로 갱신하고, 저장은 checkpoint 방식으로 처리했다. - 리팩토링
1. 파일 크기가 커지면서 Codex가 한 번에 읽고 수정해야 하는 범위가 넓어졌기 때문에, 책임 단위로 모듈을 분리했다.
2.
core,problems,runners,ui,timers,sync처럼 영역을 나눠 필요한 부분만 읽고 수정할 수 있게 했다. 3. 중복 호출되던 코드를 줄이고, 문제 생성, 풀이 기록, 테스트 실행, 동기화처럼 기능별 책임을 더 명확히 했다.
앱 화면

충돌 처리

옵션

