Projects
동글운영 중
요약
- 분류
- Team Project
- 기간
- 2024.12 - 현재
- 역할
- Frontend Developer
- 팀
- 초기 백엔드 2명 · 프론트엔드 2명
- 담당 범위
- 초기 학생용 사용자 앱 담당 · 이후 두 앱과 공통 모듈의 Turborepo 통합 단독 담당 · 출시 후 프론트엔드 전담
학생용 동아리 탐색 서비스와 동아리 회장·중앙동아리연합회용 관리 시스템을 함께 운영하는 통합 플랫폼입니다.
하이라이트
- 사용자·관리자 앱과 공통 모듈의 Turborepo 단독 통합
- 독립 앱 사이의 선택적 캐시 무효화
- 한글 IME와 URL 상태를 고려한 검색 경험
- 헬스체크 실패 시 이전 릴리스 자동 복구
기술 스택
- Next.js
- React
- TypeScript
- Turborepo
- Tailwind CSS
- TanStack Query
- Storybook
- Vitest
- Playwright
- Sentry
- GitHub Actions
목차
한눈에 보기
교내 동아리 정보와 모집 여부를 한곳에서 확인하고, 동아리 회장과 중앙동아리연합회가 동아리 정보, 활동보고서, 일정을 관리할 수 있는 통합 플랫폼입니다.
학생용 서비스와 관리자 시스템을 별도의 Next.js 애플리케이션으로 운영하며, 공통 API, 서비스, 타입, UI는 Turborepo 기반 모노레포 패키지로 관리했습니다.
초기에는 팀으로 개발하며 학생용 앱을 담당했고, 이후 사용자·관리자 앱과 공통 모듈을 Turborepo로 단독 통합했습니다. 직접 배포한 뒤에는 프론트엔드 유지보수와 기능 개선을 전담하며 캐시 무효화, 검색 경험과 배포 복구 흐름을 개선했습니다.
사용 대상
- 교내 동아리를 탐색하고 모집 정보를 확인하려는 대학 재학생
- 담당 동아리 정보와 활동 내역을 관리하는 동아리 회장
- 전체 동아리, 활동보고서, 일정을 관리하는 중앙동아리연합회
담당 범위
초기 — 팀 개발
- 백엔드 2명, 프론트엔드 2명으로 시작했습니다.
- 학생용 사용자 앱을 담당했고, 관리자 앱은 다른 프론트엔드 개발자가 담당했습니다.
이후 — 프론트엔드 단독 담당
- 사용자 앱과 관리자 앱, 공통 API·서비스·타입·UI 패키지의 Turborepo 모노레포 통합
- 동아리, 모집, 활동보고서, 일정, 사용자, 배너 도메인 화면 구현과 개선
- JWT 인증, Refresh Token 재발급, 역할 기반 접근 제어
- 테스트, 오류 모니터링, CI/CD와 운영 배포 환경 구성
- 직접 배포한 뒤 출시 후 프론트엔드 유지보수와 기능 개선 전담
구조
사용자 앱과 관리자 앱 사이의 중복 구현을 줄이고 변경 규칙을 일관되게 관리하기 위해 Turborepo 기반 모노레포를 구성했습니다.
공용 패키지로 분리한 영역은 다음과 같습니다.
- API 요청과 인증 처리
- 도메인 서비스
- 공통 타입
- UI 컴포넌트
- 날짜와 문자열 등의 공통 유틸리티
공용 UI는 Storybook을 통해 구현 상태와 사용 방식을 확인할 수 있도록 구성했습니다.
주요 기능
사용자 서비스
- 동아리 목록과 상세 정보 조회
- 분과, 모집 상태, 검색어 필터링
- 모집 기간과 외부 지원 링크 제공
- 활동보고서와 공개 일정 조회
동아리 회장 시스템
- 담당 동아리 정보와 모집 상태 관리
- 활동보고서 작성, 수정, 삭제
- 공개·비공개 일정 관리
- 계정 정보 관리
중앙동아리연합회 시스템
- 전체 동아리와 사용자 관리
- 전체 활동보고서 조회
- 동아리별 일정과 전체 일정 캘린더 관리
- 사용자 서비스에 노출할 메인 배너 관리
문제 해결 1. 분리된 앱 간 캐시 정합성
문제
사용자 앱과 관리자 앱은 독립된 Next.js 애플리케이션으로 실행됩니다. 관리자 앱에서 배너나 일정을 수정해도 사용자 앱에 남아 있는 캐시는 함께 갱신되지 않았습니다.
관리자 화면에서는 저장이 완료됐지만 공개 화면에는 이전 데이터가 일정 시간 노출될 수 있었습니다.
판단
모든 캐시를 무효화하면 구현은 단순하지만 불필요한 데이터까지 다시 조회하게 됩니다. 사용자 화면에 영향을 주는 데이터만 선택적으로 갱신하고, 외부 무효화 요청 실패가 관리자 저장 작업 자체를 실패시키지 않아야 했습니다.
구현
- 사용자 화면에 영향을 주는 캐시 태그 선별
- 공유 시크릿으로 캐시 무효화 요청 검증
- 외부 무효화 요청과 관리자 저장 성공 여부 분리
- 시크릿 오류, 잘못된 태그, 네트워크 실패 분기 테스트
결과
독립적으로 배포된 사용자 앱과 관리자 앱 사이에서도 필요한 데이터만 선택적으로 갱신할 수 있게 됐으며, 관리자 수정 결과와 공개 화면 사이의 불일치 가능성을 줄였습니다.
문제 해결 2. 한글 입력을 고려한 검색 경험
문제
검색어 입력과 목록 필터링이 동시에 실행되면서 한글 조합 중 목록이 반복적으로 렌더링됐습니다. 검색 조건이 화면 내부 상태에만 있어 상세 페이지를 확인한 뒤 돌아오면 검색어와 필터도 초기화됐습니다.
구현
- 한글 조합 시작과 종료 이벤트를 별도로 처리
- 입력 중인 값과 실제 필터링에 사용하는 검색어 분리
- 지연 렌더링으로 입력과 목록 갱신 우선순위 분리
- 결과 목록의 불필요한 렌더링 최소화
- 검색어와 필터를 URL Query String에 동기화
결과
한글 입력 과정에서 검색 로직이 불필요하게 실행되는 문제를 줄였고, 상세 화면을 방문한 뒤에도 기존 검색 조건을 유지할 수 있게 됐습니다.
문제 해결 3. 헬스체크 기반 배포 복구
문제
새 버전 배포 후 애플리케이션이 정상적으로 실행되지 않으면 서버에서 이전 버전을 직접 다시 배포해야 했습니다.
사용자 앱과 관리자 앱을 함께 운영하기 때문에 한쪽 애플리케이션의 실행 실패도 서비스 운영에 영향을 줄 수 있었습니다.
구현
- Next.js standalone 아티팩트를 릴리스별 디렉터리에 저장
- 현재 운영 버전을 심볼릭 링크로 관리
- PM2 재실행 후 사용자·관리자 앱 헬스체크
- 헬스체크 실패 시 심볼릭 링크를 이전 릴리스로 복구
- 실패한 배포가 운영 버전으로 남지 않도록 자동화
결과
배포 결과를 프로세스 실행 여부가 아니라 실제 애플리케이션 응답으로 검증하고, 실패 시 이전 정상 버전으로 복구할 수 있는 구조를 마련했습니다.
기타 개선
- 활동보고서 생성·수정 과정의 인증, 이미지 업로드, API 실패를 공통 오류 규약으로 분리
- 서버 실행 지역과 관계없이 모집 기간이 동일하게 처리되도록 KST 기준 날짜 정규화
- Vitest 단위 테스트와 Playwright E2E 테스트를 이용한 주요 흐름 검증
회고
초기에는 한 앱만 담당했지만, 두 앱과 공통 모듈을 통합하고 출시 후 운영을 전담하면서 프론트엔드의 책임이 화면 구현에만 머무르지 않는다는 점을 경험했습니다.
데이터 정합성, 입력 방식, 배포 실패처럼 사용자에게 직접 보이지 않는 문제도 서비스 신뢰도에 영향을 줍니다. 이후 기능을 구현할 때는 정상 흐름뿐 아니라 앱 사이의 경계와 실패 시 복구 방식까지 함께 설계하려고 합니다.
서비스 구조
사용자 앱
학생용 동아리 탐색 서비스 · Next.js
관리자 앱
동아리 회장·중앙동아리연합회용 관리 시스템 · Next.js
공용 패키지
Turborepo 모노레포
- API 요청과 인증 처리
- 도메인 서비스
- 공통 타입
- UI 컴포넌트Storybook으로 구현 상태와 사용 방식 확인
- 날짜와 문자열 등의 공통 유틸리티