UMC Product Web: 단독 프론트엔드 개발에서 운영 서비스의 기준을 세우기까지
1. 프로젝트의 출발점
UMC 리크루팅은 기존에 학교별 Google Form 중심으로 운영되고 있었습니다.
이 방식은 빠르게 지원 폼을 만들고 학교별로 독립 운영하기에는 편했습니다.
하지만 규모가 커질수록 한계도 분명했습니다.
- 전체 지원자 현황을 중앙에서 보기 어렵다.
- 학교별 지원 흐름과 데이터 형식이 달라진다.
- 합격 이후 챌린저 활동과 운영 정보가 다시 다른 도구로 흩어진다.
- 운영진 권한에 따라 보여야 하는 정보가 다른데, 이를 일관되게 관리하기 어렵다.
UMC Product Web은 이 문제를 해결하기 위해 만든 통합 리크루팅/운영 서비스입니다.
지원자용 리크루팅 화면과 운영진용 백오피스를 한 제품 안에서 연결하는 것이 핵심이었습니다.
![]()
제가 맡은 역할은 사실상 단독 프론트엔드 개발에 가까웠습니다.
그래서 단순히 화면을 구현하는 것보다, 앞으로 기능이 늘어나도 유지될 수 있는 기준을 먼저 세우는 일이 중요했습니다.
2. 단독 개발에서 먼저 정한 기준
혼자 개발한다고 해서 기준이 느슨해지면 안 된다고 생각했습니다.
오히려 리뷰어가 적고 맥락을 공유할 사람이 적기 때문에, 구조와 검증 기준을 더 명확히 둬야 했습니다.
처음에 정한 기준은 네 가지였습니다.
- 라우팅, 서버 상태, 폼 상태의 책임을 섞지 않는다.
- 지원자 플로우와 운영진 백오피스의 데이터 흐름을 분리해서 본다.
- 권한별 UI 분기는 화면 단에서 임시로 처리하지 않는다.
- QA와 인수인계를 사람 기억에만 의존하지 않는다.
이 기준을 바탕으로 TanStack Router, TanStack Query, React Hook Form, Zod, Emotion 조합을 선택했습니다.
라우팅은 페이지 흐름을 책임지고, 서버 상태는 Query가 관리하고, 폼 입력과 검증은 React Hook Form과 Zod가 담당하도록 역할을 나눴습니다.
이렇게 나누지 않으면 지원서 작성, 수정, 자동저장, 권한별 조회가 늘어날수록 컴포넌트 안에 조건문이 계속 쌓일 수밖에 없었습니다.
3. 화면보다 어려웠던 것은 상태의 의존성
운영 서비스는 화면 수가 많다는 점이 먼저 보입니다.
하지만 실제로 더 어려웠던 것은 화면 사이의 의존성이었습니다.
UMC Product Web에는 단순 CRUD보다 복잡한 흐름이 많았습니다.
- 지원서를 생성한 뒤 어떤 조건에서 수정할 수 있는가
- 재지원 시 기존 응답을 어떻게 다룰 것인가
- 지원 파트를 바꾸면 기존 하위 답변을 유지할 것인가, 초기화할 것인가
- 자동저장은 언제 신뢰할 수 있는 상태로 볼 것인가
- 질문 생성 후
POST결과와GET결과의 정렬 기준을 어떻게 맞출 것인가 - 운영진 권한에 따라 같은 데이터를 어디까지 보여줄 것인가
이런 문제는 UI만 보고는 드러나지 않습니다.
하지만 한 번 잘못 설계하면 나중에 특정 조건에서 지원서가 꼬이거나, 운영진이 잘못된 데이터를 보게 될 수 있습니다.
그래서 기능을 만들 때 화면보다 먼저 상태 전이를 확인했습니다.
예를 들어 파트 변경은 단순 select 변경이 아니었습니다. 파트가 바뀌면 해당 파트에 종속된 질문과 답변의 의미가 달라집니다.
그래서 변경 전에 확인 모달을 띄우고, 사용자가 동의했을 때만 기존 응답을 초기화하는 흐름으로 분리했습니다.
이런 로직은 컴포넌트 안에 직접 넣지 않고 훅으로 분리했습니다.
화면은 사용자의 선택을 받고, 훅은 변경 가능 여부와 초기화 흐름을 책임지도록 나눴습니다.
4. 지원자 플로우와 운영진 백오피스는 다른 제품처럼 봤다
이 프로젝트는 하나의 서비스였지만, 사용자 입장에서는 두 개의 제품에 가까웠습니다.
지원자는 리크루팅 공고를 보고, 지원서를 작성하고, 저장하고, 제출합니다.
운영진은 학교별 지원 현황을 확인하고, 지원자를 관리하고, 권한에 맞는 운영 정보를 봅니다.
같은 데이터를 다루지만 목적이 다릅니다.
그래서 지원자 플로우에서는 폼 안정성과 저장 흐름을 우선했습니다.
반대로 운영진 백오피스에서는 권한과 필터링, 목록 조회, 상태 관리가 더 중요했습니다.
이 차이를 구분하지 않으면 모든 화면이 비슷한 CRUD처럼 보입니다.
하지만 실제 운영에서는 “누가, 어떤 목적을 가지고, 어떤 데이터를 보는가”가 훨씬 중요했습니다.
5. 폼 검증은 기능이 아니라 운영 안정성에 가까웠다
리크루팅 서비스에서 폼은 단순 입력 UI가 아닙니다.
지원자가 입력한 내용은 이후 운영진 평가와 합격 이후 활동까지 이어질 수 있습니다.
따라서 프론트엔드에서 입력값을 적당히 받고 서버에 넘기는 정도로는 부족했습니다.
이 프로젝트에서는 React Hook Form과 Zod를 함께 사용했습니다.
- 입력 상태는 React Hook Form으로 관리
- 필드별 검증 규칙은 Zod 스키마로 정의
- 서버로 보내기 전 데이터 형태를 한 번 더 정리
- 화면별로 검증 방식이 흩어지지 않도록 패턴 고정
이 조합을 선택한 이유는 단순히 많이 쓰이는 스택이라서가 아니었습니다.
지원서 작성 화면이 늘어나도 검증 기준이 흔들리지 않게 만들고 싶었습니다.
운영 서비스에서 폼 검증은 사용자 편의 기능이기도 하지만, 동시에 데이터 품질을 지키는 장치입니다.
잘못된 데이터가 들어오면 운영진 화면, 통계, 이후 프로세스까지 영향을 받기 때문입니다.
6. 권한은 UI 조건문으로 끝나지 않는다
UMC Product Web에는 챌린저, 파트장, 회장단, 총괄 등 여러 역할이 있었습니다.
역할마다 접근 가능한 화면과 데이터 범위가 달라야 했습니다.
처음에는 권한 처리를 단순히 “버튼을 보여줄지 말지” 정도로 생각하기 쉽습니다.
하지만 실제 백오피스에서는 그보다 더 앞단에서 막아야 하는 경우가 많았습니다.
- 접근 가능한 라우트
- 조회 가능한 데이터 범위
- 수행 가능한 액션
- 같은 화면 안에서 보이는 필드
- 잘못 접근했을 때의 처리
권한을 UI 조건문으로만 처리하면 화면은 그럴듯하게 막을 수 있습니다.
하지만 사용자가 URL로 직접 접근하거나, 권한이 맞지 않는 상태에서 데이터 요청이 먼저 발생하는 문제는 막기 어렵습니다.
그래서 권한 처리는 TanStack Router의 라우트 구조와 함께 설계했습니다.
페이지 컴포넌트 안에서 뒤늦게 분기하기보다, 라우트 진입 시점에서 “이 사용자가 이 화면에 들어올 수 있는가”를 먼저 판단하는 방식에 가깝게 가져갔습니다.
TanStack Router를 사용하면서 좋았던 점은 라우트 단위로 책임을 나눌 수 있다는 점이었습니다.
- 라우트 진입 전 필요한 사용자 정보 확인
- 권한이 맞지 않을 때 리다이렉트 또는 접근 차단
- 라우트별로 필요한 서버 상태 조회 기준 분리
- 페이지 컴포넌트에서는 권한 검사를 반복하지 않도록 정리
물론 최종적인 보안은 서버에서 보장해야 합니다.
프론트엔드의 권한 처리는 보안의 전부가 아니라, 잘못된 화면 진입과 불필요한 요청을 줄이는 사용자 흐름의 방어선에 가깝습니다.
그래서 이 프로젝트에서는 권한을 “UI를 숨기는 조건”이 아니라 “라우팅, 데이터 조회, 화면 액션을 결정하는 기준”으로 봤습니다.
이 기준을 잡아두니 운영진 역할이 늘어나도 각 화면에 조건문을 계속 덧붙이는 방식으로 흐르지 않을 수 있었습니다.
이 프로젝트를 하면서 백오피스의 핵심은 예쁜 테이블이 아니라, “사용자가 자신의 역할에 맞는 정보만 안정적으로 다루게 하는 것”이라는 점을 많이 느꼈습니다.
7. 혼자 개발할수록 검증 구조가 필요했다
단독 개발에서 가장 위험한 부분은 “내가 맞다고 생각한 상태로 계속 가는 것”입니다.
그래서 이 프로젝트에서는 개발 도구를 일부러 더 적극적으로 사용했습니다.
- Storybook으로 컴포넌트 단위 확인
- Playwright로 주요 사용자 흐름 검증
- Vitest로 주요 로직 테스트
- AI 리뷰어로 PR 단위 피드백 보완
- GitHub Actions와 AWS Amplify로 배포 상태 확인
Storybook은 단순히 UI를 예쁘게 보기 위한 도구로 쓰지 않았습니다.
PM, 디자이너, 후임 개발자가 같은 기준으로 화면을 확인할 수 있는 문서화 도구에 가까웠습니다.
특히 디자이너가 컴포넌트 단위 산출물 없이 작업하는 상황에서는, 구현된 화면을 기준으로 피드백을 주고받아야 했습니다.
Storybook은 이때 “어느 화면을 기준으로 이야기하는지”를 맞추는 역할을 했습니다.
8. QA 환경 분리는 데이터 보호 문제였다
운영 서비스에서는 QA를 어디서 하느냐도 중요했습니다.
리크루팅 서비스는 실제 지원 데이터와 운영 정보가 연결됩니다.
운영 환경에서 테스트를 잘못하면 단순 UI 버그가 아니라 데이터 훼손으로 이어질 수 있습니다.
그래서 develop과 main을 분리했습니다.
develop: 서버 테스트, 프론트 테스트, QAmain: 운영 반영
AWS Amplify를 사용하면서 브랜치별 배포 상태도 함께 관리했습니다.
이 구조 덕분에 QA에서 충분히 확인한 뒤 운영에 반영하는 흐름을 만들 수 있었습니다.
이 경험을 통해 QA 환경 분리는 단순한 개발 편의가 아니라 운영 데이터 보호 전략이라는 점을 배웠습니다.
9. 마무리
UMC Product Web에서 가장 많이 고민한 것은 화면의 개수보다 운영 기준이었습니다.
지원자 플로우와 운영진 백오피스는 같은 데이터를 바라보지만, 필요한 안정성의 기준이 달랐습니다.
지원자 화면에서는 입력과 저장 흐름이 중요했고, 운영진 화면에서는 권한과 조회 범위, QA 환경이 더 중요했습니다.
프론트엔드 개발은 화면을 구현하는 일이지만, 운영 서비스에서는 화면만으로 끝나지 않았습니다.
데이터가 어떻게 흐르는지, 누가 어떤 권한으로 접근하는지, 잘못된 입력을 어디서 막을지, QA를 어떤 환경에서 할지까지 함께 봐야 합니다.
이 프로젝트를 하면서 단독 개발에서 필요한 것은 더 많은 코드가 아니라, 흔들리지 않는 기준이라는 것을 배웠습니다.
GitHubGitHub - UMC-PRODUCT/umc-product-web: 1기 웹프로덕트팀 - (구) 리크루팅 사이트1기 웹프로덕트팀 - (구) 리크루팅 사이트. Contribute to UMC-PRODUCT/umc-product-web development by creating an account on GitHub.Enjoyed this article? Check out more projects and posts on my portfolio.
Explore this project