기술 스택
한국외국어대학교 학생을 위한 크롬 새 탭 익스텐션입니다. 종강까지 남은 시간을 실시간으로 보여주고, 학식·도서관 여석·날씨·학사일정·시간표를 새 탭 하나에 모았습니다. 약 140명의 학우가 쓰고 있고, 2025년 11월부터 지금까지 유지보수하며 2.2.0까지 올렸습니다.
기획부터 배포까지 1인 개발입니다. React로 익스텐션을 만들고, 학교 사이트에서 학식·도서관 여석·학사일정을 긁어오는 FastAPI 서버를 따로 두어 Vercel에 올렸습니다. 크롬 웹스토어 심사와 버전 릴리즈도 직접 했습니다.

새 탭을 여러 개 열거나 새로고침을 반복하는 것만으로 사용자 설정이 기본값으로 돌아갔습니다. 재현 조건이 모호해 한참 붙잡았던 버그입니다.
원인이 세 겹이었습니다. 첫째, 저장소에서 값을 읽는 함수가 읽기 실패를 삼키고 null을 반환하고 있었습니다. 상태 관리 라이브러리에게 null은 "저장된 값이 없음", 즉 신규 사용자를 뜻합니다. 읽기가 한 번 실패하면 기존 사용자가 신규 사용자로 둔갑했고, 그 상태에서 다음 쓰기가 일어나면 실제 데이터가 기본값으로 영구히 덮였습니다.
둘째, 직전에 제가 넣은 수정이 상황을 악화시키고 있었습니다. 복원 콜백에서 상태를 직접 세팅했는데, 이 라이브러리는 상태를 세팅하는 즉시 전체를 디스크에 씁니다. 그리고 그 콜백은 복원에 실패한 경로에서도 호출됩니다. 결국 메모리가 기본값인 채로 디스크를 덮어쓰는 경로를 제가 하나 더 만든 셈이었습니다.
셋째, 탭 사이에 동기화가 없어 오래된 메모리 상태가 최신 설정을 덮어썼습니다.
읽기 실패를 감추지 않고 그대로 전파시키고, 복원이 성공하기 전에는 쓰기 자체를 거부하도록 모든 setter가 지나는 길목에 가드를 뒀습니다. 쓰기 허용 플래그는 복원 성공 콜백에서만 켜지게 해서, 읽기 실패든 저장된 값이 깨졌든 디스크가 보호되게 했습니다. 마지막으로 탭 간 변경 이벤트를 구독해 동기화를 붙였습니다.
고쳤다는 것을 테스트로 증명했습니다. 통합 테스트 21개(신규 6개)와 실제 크롬에 확장을 올려 돌리는 E2E 4개를 붙였는데, 중요한 건 이 테스트들을 수정 전 코드에 먼저 돌려본 것입니다. 신규 통합 테스트는 6개 중 5개, E2E는 4개 중 3개가 수정 전 코드에서 실패했습니다. 버그가 실재했다는 증거이자, 테스트가 실제로 그 버그를 잡고 있다는 증거입니다.



