chorock.page
소개글시리즈프로젝트
© 2026 chorock.page
← 프로젝트 목록

Project

외대종강시계

약 140명의 학우들이 사용하는 한국외국어대학교 학생용 크롬 익스텐션 서비스

작업 기간

2025.11 — 현재

프로젝트 정보

팀 구성

1인 개발

담당 역할

기획·프론트엔드·백엔드(FastAPI)

데모 보기GitHub

목차

맡은 일아키텍처성과와 한계주요 기능문제 해결스크린샷
목차
맡은 일아키텍처성과와 한계주요 기능문제 해결스크린샷

사용 기술

기술 스택

React.jsFastAPIReact QueryZustandVercelViteSCSSFormspreeAxiosSwiper.js

프로젝트 개요

한국외국어대학교 학생을 위한 크롬 새 탭 익스텐션입니다. 종강까지 남은 시간을 실시간으로 보여주고, 학식·도서관 여석·날씨·학사일정·시간표를 새 탭 하나에 모았습니다. 약 140명의 학우가 쓰고 있고, 2025년 11월부터 지금까지 유지보수하며 2.2.0까지 올렸습니다.

맡은 일

기획부터 배포까지 1인 개발입니다. React로 익스텐션을 만들고, 학교 사이트에서 학식·도서관 여석·학사일정을 긁어오는 FastAPI 서버를 따로 두어 Vercel에 올렸습니다. 크롬 웹스토어 심사와 버전 릴리즈도 직접 했습니다.

아키텍처

아키텍처 — React 컴포넌트 · Zustand · Chrome Storage API · Vercel 크롤링 서버의 데이터 흐름

  • 화면은 React 컴포넌트가 그리고, 사용자 설정·배경화면 같은 상태는 Zustand 전역 스토어 하나가 들고 있습니다. 비동기 처리와 탭 간 동기화를 한곳에서 다루려고 전역으로 뺐습니다.
  • Zustand는 Chrome Storage API와 양방향으로 붙어 있습니다. 설정이 바뀌면 저장하고, 새 탭이 열리면 저장된 유저 정보와 배경화면을 복원합니다. 위 "문제 해결"의 설정 초기화 버그가 바로 이 경계에서 났습니다.
  • 공지사항·학식·도서관 여석은 Vercel에 올린 크롤링 서버가 JSON으로 내려주고, 컴포넌트가 React Query로 요청해 캐시합니다. 크롤링 결과가 익스텐션 코드와 분리돼 있어 학교 페이지 구조가 바뀌어도 서버만 고치면 됩니다.

성과와 한계

  • 학식·도서관 여석·학사일정 데이터는 직접 만들어 함께 운영하는 FastAPI 크롤링 서버가 공급합니다. 이 API는 부 키우기(캡스톤 팀 프로젝트)의 학식 기능에도 그대로 재사용됐습니다.
  • 학식·도서관·학사일정은 학교 웹사이트를 크롤링해서 가져옵니다. 학교가 페이지 구조를 바꾸면 깨지는 구조라, 실제로 그때마다 파싱 로직을 고쳐왔습니다. 공식 API가 없어 택한 방법이지만 근본적인 한계입니다.

주요 기능

  • 종강까지 남은 시간 실시간 시각화
  • 학식 — 서울·글로벌 두 캠퍼스 식단을 크롤링해 제공
  • 도서관 여석, 캠퍼스 날씨(기상청 실시간·단기예보를 합쳐서), 학사일정
  • 시간표 — 학과별 검색, 저장, 그리드 편집
  • 북마크 커스텀(고정·개수 조절), 개발자 공지, 사용자 피드백 창구

문제 해결

새 탭을 여러 개 열면 설정이 초기화되던 문제

새 탭을 여러 개 열거나 새로고침을 반복하는 것만으로 사용자 설정이 기본값으로 돌아갔습니다. 재현 조건이 모호해 한참 붙잡았던 버그입니다.

원인이 세 겹이었습니다. 첫째, 저장소에서 값을 읽는 함수가 읽기 실패를 삼키고 null을 반환하고 있었습니다. 상태 관리 라이브러리에게 null은 "저장된 값이 없음", 즉 신규 사용자를 뜻합니다. 읽기가 한 번 실패하면 기존 사용자가 신규 사용자로 둔갑했고, 그 상태에서 다음 쓰기가 일어나면 실제 데이터가 기본값으로 영구히 덮였습니다.

둘째, 직전에 제가 넣은 수정이 상황을 악화시키고 있었습니다. 복원 콜백에서 상태를 직접 세팅했는데, 이 라이브러리는 상태를 세팅하는 즉시 전체를 디스크에 씁니다. 그리고 그 콜백은 복원에 실패한 경로에서도 호출됩니다. 결국 메모리가 기본값인 채로 디스크를 덮어쓰는 경로를 제가 하나 더 만든 셈이었습니다.

셋째, 탭 사이에 동기화가 없어 오래된 메모리 상태가 최신 설정을 덮어썼습니다.

읽기 실패를 감추지 않고 그대로 전파시키고, 복원이 성공하기 전에는 쓰기 자체를 거부하도록 모든 setter가 지나는 길목에 가드를 뒀습니다. 쓰기 허용 플래그는 복원 성공 콜백에서만 켜지게 해서, 읽기 실패든 저장된 값이 깨졌든 디스크가 보호되게 했습니다. 마지막으로 탭 간 변경 이벤트를 구독해 동기화를 붙였습니다.

고쳤다는 것을 테스트로 증명했습니다. 통합 테스트 21개(신규 6개)와 실제 크롬에 확장을 올려 돌리는 E2E 4개를 붙였는데, 중요한 건 이 테스트들을 수정 전 코드에 먼저 돌려본 것입니다. 신규 통합 테스트는 6개 중 5개, E2E는 4개 중 3개가 수정 전 코드에서 실패했습니다. 버그가 실재했다는 증거이자, 테스트가 실제로 그 버그를 잡고 있다는 증거입니다.

스크린샷

메인 화면

야간 모드

위젯 화면

타임라인