#React#TypeScript#프론트엔드#아키텍처#설계
React + TypeScript 실무 아키텍처 설계 포인트
차세대 프로젝트를 돌아보며, 프론트 구조를 어떻게 잡았는지 남긴 기록이다.
차세대 시스템을 맡으면서 가장 크게 느꼈다.
결국 기능보다 구조를 먼저 정해야 이후 운영이 덜 흔들린다는 점을.
왜 구조를 먼저 잡았는가
- 초반에 파일을 막 늘리면, 6개월 뒤엔 경로 찾는 데만 시간이 새었다.
- 타입 경계를 흐리게 두면, API 스펙이 바뀔 때마다 수정 범위가 연쇄적으로 퍼졌다.
- UI 상태와 서버 상태를 섞어두면, 장애 때 디버깅 범위가 넓어졌다.
그래서 “일단 돌아가게”보다 “나중에 읽을 수 있게”를 우선했다.
내가 실무에서 쓴 기준
- 도메인 단위로 폴더를 나눴다.
- 화면 컴포넌트와 비즈니스 로직을 분리했다.
- API 응답 타입과 View Model 타입을 따로 뒀다.
- 공통 훅은 재사용 기준이 분명할 때만 뽑았다.
이렇게 바꾼 뒤 체감한 점 (당시 결론)
- 신규 인원이 들어와도 탐색 경로가 짧아졌다.
- 기능 변경 시 영향 범위를 예측하기 쉬워졌다.
- 테스트 범위를 좁혀서 가져갈 수 있었다.
결국 당시 결론은 “구조는 속도를 늦추는 비용이 아니라, 나중의 속도를 사두는 투자”라는 것이었다. 새 기능을 빨리 내고 싶을수록, 역설적으로 구조를 먼저 고정해야 했다.
비슷한 경험 — 레거시 위에 React를 얹을 때
이 구조 감각은 차세대를 새로 짤 때만 쓰인 게 아니었다. JSP 전산 위에 React SPA를 iframe으로 붙일 때(ES5→ES6 단계적 이전), 똑같이 “경계부터 긋는” 습관이 결정적이었다.
- 이유: 기존 화면을 한 번에 갈아엎으면 운영이 멈췄다. 그렇다고 새 UI 요구를 계속 미룰 수도 없었다. 새로움과 안정성이 또 충돌했다.
- 당시 결론: 도메인·타입 경계를 먼저 그어 둔 덕에, “이 영역만 React로, 저장·승인은 기존 API로”라는 부분 이관 경계를 자신 있게 잡을 수 있었다. 구조가 없었으면 어디를 끊어야 안전한지조차 몰랐을 것이다.
- 새 프로젝트든 레거시든, 내가 먼저 하는 일은 똑같았다. 바뀔 곳과 지킬 곳의 선을 긋는 것.
아직 부족한 것 (개선점)
- API 응답 타입과 View Model 타입을 분리했지만, 둘을 잇는 변환 코드가 도메인마다 제각각이다.
- 공통 훅 추출 기준을 “분명할 때만”으로 뒀는데, 그 “분명함”의 판단이 여전히 사람마다 다르다.
- 폴더 구조 규칙이 문서로만 있어, 시간이 지나면 예외 폴더가 슬금슬금 생긴다.
앞으로 나가야 할 방향
- Spring Boot API 스펙에서 타입을 자동 생성해, 서버-프론트 타입 계약을 손으로 맞추는 일을 줄인다.
- 폴더·의존 경계를 ESLint 규칙(import 제한) 으로 강제해, 구조가 문서가 아니라 코드로 지켜지게 한다(클린코드 플레이북 연계).
- 모노레포 전환 시점에 맞춰 공통 타입·유틸의 소유 경계를 다시 정리한다(모노레포 고민).
- 구조 의사결정을 ADR(결정 기록)로 남겨, “왜 이렇게 나눴는지”를 다음 사람이 추적할 수 있게 한다.
다음에는 Spring Boot API와 프론트 타입 계약을 어떻게 맞췄는지도 적어볼 생각이다. 구조를 잡는 일은 한 번 끝나는 작업이 아니라, 기준을 계속 갱신하며 흔들림을 줄여가는 일이라는 걸 점점 더 느낀다.
#React#TypeScript#프론트엔드#아키텍처#설계