0730 프론트엔드 실무 심화 (12/N): 아키텍처 정리, 폴더 구조와 유지보수 전략
✅ 1. 프론트엔드 아키텍처란 무엇인가?
- 프론트엔드 아키텍처는 화면, 컴포넌트, API, 상태 관리, 라우팅, 스타일, 권한, 유틸 코드를 어떤 기준으로 나누고 연결할지 정하는 구조입니다.
- 단순히 폴더를 예쁘게 나누는 것이 아니라, 기능이 늘어나도 어디를 수정해야 하는지 바로 찾을 수 있게 만드는 작업입니다.
- 온라인 휴대폰 판매몰처럼 고객 화면과 관리자 화면이 함께 있는 프로젝트에서는 아키텍처가 더 중요합니다.
라우팅
↓
페이지
↓
기능 단위 feature
↓
컴포넌트
↓
hook / api / type / util
↓
공통 UI / 공통 lib
➕ 1-1. 아키텍처가 중요한 이유
- 기능 추가 속도가 빨라집니다.
- 버그가 났을 때 원인을 찾기 쉬워집니다.
- AI IDE나 Codex에게 작업을 맡기기 쉬워집니다.
- 공통 컴포넌트 수정 영향 범위를 예측할 수 있습니다.
- 고객 화면과 관리자 화면의 책임이 섞이지 않습니다.
- 새로 합류한 개발자나 미래의 내가 코드를 이해하기 쉬워집니다.
나쁜 구조:
pages 안에 모든 코드가 몰림
api 호출 코드가 컴포넌트마다 흩어짐
types가 중복 정의됨
utils가 아무거나 담는 폴더가 됨
공통 UI와 도메인 UI가 섞임
결과:
수정 범위 예측 어려움
리팩토링 부담 증가
AI 작업 결과 품질 저하
✅ 2. 좋은 프론트엔드 구조의 기준
- 좋은 구조는 처음 봐도 코드 위치를 예측할 수 있어야 합니다.
- “상담 목록 API는 어디 있지?”, “상담 상태 변경 모달은 어디 있지?”, “공통 Button은 어디 있지?”가 바로 떠올라야 합니다.
➕ 2-1. 좋은 구조의 조건
도메인별 코드가 모여 있음
공통 UI와 기능 UI가 분리됨
API 호출 코드가 한 곳으로 정리됨
상태 관리 기준이 명확함
라우팅과 페이지 역할이 분리됨
타입 정의 위치가 예측 가능함
비즈니스 로직이 UI에 과하게 섞이지 않음
➕ 2-2. 나쁜 구조의 신호
components 폴더에 모든 것이 들어 있음
utils 폴더가 너무 커짐
api.ts 하나에 모든 API가 있음
Page 컴포넌트가 1000줄 이상
같은 타입이 여러 파일에 중복됨
상태 라벨 매핑이 화면마다 다름
권한 체크 조건이 컴포넌트마다 다름
- 구조가 무너지면 코드가 많아질수록 작업 속도가 급격히 떨어집니다.
- 1인 개발자일수록 구조를 더 단순하고 일관되게 유지해야 합니다.
✅ 3. 고객 화면과 관리자 화면 분리
- 고객 화면과 관리자 화면은 목적, UI 밀도, 권한, 상태 관리가 다릅니다.
- 가능하면 라우팅, layout, feature 구조에서 둘을 분리하는 것이 좋습니다.
➕ 3-1. 고객 화면
목적:
상품 탐색, 혜택 확인, 상담 신청, 사전예약 전환
주요 기능:
상품 목록
상품 상세
상담 신청 모달
리뷰/FAQ
사전예약 페이지
이벤트 배너
➕ 3-2. 관리자 화면
목적:
운영 데이터 조회, 상담/주문 처리, 상품/배너 관리, 통계 확인
주요 기능:
관리자 로그인
상담 목록
주문 목록
상품 관리
배너 관리
엑셀 Export
권한 관리
유입 통계
➕ 3-3. 분리 기준
layout 분리:
CustomerLayout / AdminLayout
route 분리:
/products, /events
/admin/consults, /admin/products
feature 분리:
features/customer-products
features/admin-consults
공통 UI:
components/ui
- 고객 화면과 관리자 화면이 섞이면 번들, 권한, UI 기준이 꼬입니다.
- 특히 관리자 전용 코드가 고객 화면 번들에 과하게 섞이지 않도록 주의해야 합니다.
✅ 4. 추천 폴더 구조
- 프로젝트가 너무 작을 때부터 복잡한 구조를 만들 필요는 없지만, 고객/관리자/공통을 나눌 기준은 있어야 합니다.
src/
app/
routes/
providers/
pages/
customer/
HomePage.tsx
ProductListPage.tsx
ProductDetailPage.tsx
ReservationPage.tsx
admin/
AdminLoginPage.tsx
AdminDashboardPage.tsx
AdminConsultPage.tsx
AdminProductPage.tsx
layouts/
CustomerLayout/
AdminLayout/
features/
products/
api/
hooks/
types/
components/
utils/
consults/
api/
hooks/
types/
components/
utils/
admin-consults/
api/
hooks/
types/
components/
utils/
admin-products/
api/
hooks/
types/
components/
utils/
auth/
api/
hooks/
types/
utils/
components/
ui/
Button/
Input/
Modal/
Badge/
EmptyState/
ErrorState/
Pagination/
common/
PageHeader/
ConfirmDialog/
LoadingOverlay/
lib/
apiClient.ts
queryClient.ts
router.ts
config/
env.ts
constants.ts
styles/
tokens.ts
globals.css
utils/
formatDate.ts
formatCurrency.ts
normalizePhone.ts
➕ 4-1. 역할 정리
| 폴더 | 역할 |
|---|
pages | 라우팅 단위 페이지 |
layouts | 고객/관리자 공통 레이아웃 |
features | 도메인별 기능 코드 |
components/ui | 재사용 가능한 순수 UI |
components/common | 여러 화면에서 쓰는 공통 조합 컴포넌트 |
lib | 외부 라이브러리 설정, API client, query client |
config | 환경변수, 상수 |
utils | 순수 유틸 함수 |
- 핵심은 “기능별 코드는 features에 모으고, 진짜 공통 UI만 components/ui에 둔다”는 점입니다.
- 공통이라는 이름으로 도메인 로직이 섞이면 나중에 더 복잡해집니다.
✅ 5. Feature 기반 구조
- Feature 기반 구조는 기능 단위로 관련 파일을 모으는 방식입니다.
- 예를 들어 상담 관리에 필요한 API, hook, type, component를
features/admin-consults 안에 모읍니다.
➕ 5-1. 상담 관리 feature 예시
features/admin-consults/
api/
adminConsultApi.ts
hooks/
useAdminConsults.ts
useUpdateConsultStatus.ts
useConsultSearchParams.ts
types/
adminConsultTypes.ts
components/
ConsultSearchForm.tsx
ConsultTable.tsx
ConsultTableRow.tsx
ConsultDetailModal.tsx
UpdateConsultStatusModal.tsx
utils/
consultStatusLabel.ts
toAdminConsultRow.ts
➕ 5-2. 장점
관련 코드가 한 곳에 있음
기능 삭제/이동이 쉬움
AI에게 특정 feature만 수정시키기 좋음
도메인별 책임이 명확함
파일 탐색이 쉬움
- 상담 관리 화면을 수정할 때
features/admin-consults부터 보면 됩니다.
- 상품 관리 화면을 수정할 때는
features/admin-products를 보면 됩니다.
✅ 6. 공통 UI와 도메인 컴포넌트 구분
- 공통 UI와 도메인 컴포넌트를 구분하지 않으면
components 폴더가 금방 지저분해집니다.
➕ 6-1. 공통 UI
특정 도메인을 몰라도 되는 컴포넌트
예:
Button
Input
Modal
Badge
EmptyState
ErrorState
Pagination
Skeleton
➕ 6-2. 도메인 컴포넌트
특정 업무 개념을 아는 컴포넌트
예:
ConsultStatusBadge
ConsultSearchForm
ProductPriceSection
ReservationLeadForm
AdminOrderTable
ExportJobStatusBadge
➕ 6-3. 위치 기준
Button:
components/ui/Button
ConsultStatusBadge:
features/admin-consults/components/ConsultStatusBadge
ProductPriceSection:
features/products/components/ProductPriceSection
AdminSidebar:
layouts/AdminLayout 또는 components/common
ConsultStatusBadge는 Badge를 사용하지만, 상담 상태라는 도메인 개념을 알기 때문에 공통 UI가 아닙니다.
- 이런 구분이 되어야 공통 컴포넌트가 깔끔하게 유지됩니다.
✅ 7. Page 컴포넌트의 역할
- Page 컴포넌트는 라우팅 단위의 진입점입니다.
- 너무 많은 세부 UI를 직접 품으면 파일이 비대해집니다.
➕ 7-1. Page가 담당할 것
URL params 읽기
페이지 단위 query 호출
권한 guard 연결
큰 화면 구조 조립
feature 컴포넌트 배치
페이지 title/meta 설정
➕ 7-2. Page가 직접 하지 않는 것이 좋은 것
테이블 row 렌더링 세부 구현
폼 필드 하나하나 구현
상태 라벨 매핑
API 경로 직접 작성
복잡한 validation schema 직접 정의
권한 조건 문자열 직접 비교
➕ 7-3. 예시
function AdminConsultPage() {
const searchParams = useConsultSearchParams();
const consultsQuery = useAdminConsults(searchParams);
return (
<AdminPageLayout title="상담 관리">
<ConsultSearchForm defaultValues={searchParams} />
<ConsultTableSection query={consultsQuery} />
</AdminPageLayout>
);
}
- Page는 전체 흐름을 보여주고, 세부 구현은 feature 컴포넌트로 넘기는 것이 좋습니다.
✅ 8. Hook 분리 기준
- Hook은 상태 관리, URL 파싱, API query, 이벤트 로직을 재사용하기 위해 분리합니다.
- 하지만 모든 코드를 hook으로 빼는 것도 과합니다.
➕ 8-1. Hook으로 빼면 좋은 것
URL query string 파싱
TanStack Query useQuery/useMutation
권한 체크 조합
반복되는 모달 open/close
검색 폼과 URL 동기화
테이블 selection 상태
➕ 8-2. Hook으로 빼지 않아도 되는 것
한 컴포넌트에서만 쓰는 단순 useState
짧은 onClick handler
단순한 className 계산
한 줄짜리 derived value
➕ 8-3. 예시
export function useConsultSearchParams() {
const searchParams = useSearchParams();
return {
page: parsePage(searchParams.get('page')),
limit: parseLimit(searchParams.get('limit')),
keyword: searchParams.get('keyword') ?? undefined,
status: searchParams.get('status') as ConsultStatus | undefined,
source: searchParams.get('source') ?? undefined,
startDate: searchParams.get('startDate') ?? undefined,
endDate: searchParams.get('endDate') ?? undefined,
};
}
- URL 파싱 같은 로직은 여러 컴포넌트가 공유하거나 테스트하기 쉬우므로 hook으로 빼는 것이 좋습니다.
✅ 9. Type 위치 기준
- TypeScript 타입은 위치 기준이 중요합니다.
- 타입이 여기저기 중복되면 API 변경 시 수정이 어렵습니다.
➕ 9-1. 도메인 타입
features/admin-consults/types/adminConsultTypes.ts
예:
ConsultStatus
AdminConsultListItem
GetAdminConsultsParams
AdminConsultListResponse
UpdateConsultStatusPayload
➕ 9-2. 공통 타입
types/common.ts 또는 src/types/
예:
PaginationMeta
PageResponse<T>
ApiError
Option
➕ 9-3. UI 전용 타입
컴포넌트 파일 근처 또는 components/ui 내부
예:
ButtonProps
ModalProps
BadgeVariant
- API 응답 타입은 도메인 feature에 두는 것이 좋습니다.
- 여러 도메인이 공유하는 페이지네이션, API 에러 타입은 공통 타입으로 둡니다.
✅ 10. Utils 폴더 관리
utils는 관리하지 않으면 금방 쓰레기통이 됩니다.
- 아무 함수나
utils에 넣으면 나중에 찾기 어렵습니다.
➕ 10-1. 좋은 utils
formatDate.ts
formatCurrency.ts
normalizePhone.ts
parseNumber.ts
buildQueryString.ts
maskPhone.ts
➕ 10-2. 나쁜 utils
utils.ts
common.ts
helper.ts
temp.ts
data.ts
misc.ts
➕ 10-3. 기준
순수 함수 위주
파일명은 기능을 드러내기
도메인 전용 util은 feature 내부에 두기
공통 util은 정말 여러 도메인에서 쓰일 때만 root utils로 이동
- 상담 상태 라벨 매핑은 공통 utils가 아니라
features/admin-consults/utils에 두는 것이 자연스럽습니다.
- 날짜 포맷, 전화번호 정규화처럼 여러 기능에서 쓰면 root utils에 둬도 됩니다.
✅ 11. 상수 관리
- 상수는 화면마다 직접 쓰지 말고 기준 위치를 정해야 합니다.
- 특히 상태값, 권한명, route path, query param key는 중복되면 위험합니다.
➕ 11-1. 상수 예시
export const ROUTES = {
admin: {
login: '/admin/login',
consults: '/admin/consults',
products: '/admin/products',
},
customer: {
home: '/',
products: '/products',
},
} as const;
export const PERMISSIONS = {
CONSULT_READ: 'CONSULT_READ',
CONSULT_UPDATE: 'CONSULT_UPDATE',
CONSULT_EXPORT: 'CONSULT_EXPORT',
PRODUCT_UPDATE: 'PRODUCT_UPDATE',
} as const;
➕ 11-2. 기준
route path:
config/routes.ts
permission:
features/auth/constants 또는 config/permissions.ts
상태 라벨:
해당 feature 내부
공통 옵션:
도메인 위치에 따라 결정
- 상수를 한 곳에 몰아넣는 것도 좋지 않습니다.
- 공통인지 도메인 전용인지 구분해야 합니다.
✅ 12. Import 경로 정리
- import 경로가 지저분하면 코드 읽기가 어려워집니다.
- alias를 사용하면 구조가 깔끔해집니다.
➕ 12-1. 나쁜 예시
import { Button } from '../../../../components/ui/Button';
import { formatDate } from '../../../utils/formatDate';
➕ 12-2. 좋은 예시
import { Button } from '@/components/ui/Button';
import { formatDate } from '@/utils/formatDate';
➕ 12-3. 주의할 점
alias 기준을 프로젝트 전체에서 통일
index barrel export 남발 주의
순환 참조 발생 여부 확인
feature 간 의존성 과도하게 만들지 않기
- import alias는 생산성을 높여줍니다.
- 다만 feature끼리 서로 복잡하게 물고 물리는 구조는 피해야 합니다.
✅ 13. Feature 간 의존성 관리
- Feature 기반 구조에서 주의할 점은 feature끼리 지나치게 의존하지 않게 하는 것입니다.
- 예를 들어
admin-products가 admin-consults 내부 util을 직접 가져다 쓰면 구조가 꼬일 수 있습니다.
➕ 13-1. 좋은 의존성 방향
features/admin-consults
→ components/ui
→ lib/apiClient
→ utils/formatDate
→ types/common
features/admin-products
→ components/ui
→ lib/apiClient
→ utils/formatCurrency
→ types/common
➕ 13-2. 조심할 의존성
features/admin-products
→ features/admin-consults/utils
features/auth
→ features/admin-products/components
components/ui
→ features/admin-consults/types
- 공통으로 써야 하는 로직이면 root utils/types로 올리는 것이 좋습니다.
- 공통 UI는 특정 feature를 알면 안 됩니다.
✅ 14. Barrel Export 사용 기준
index.ts로 export를 모으는 방식을 Barrel Export라고 합니다.
- import를 짧게 만들 수 있지만, 과하게 쓰면 순환 참조와 번들 분석이 어려워질 수 있습니다.
➕ 14-1. 예시
export { Button } from './Button';
export { Input } from './Input';
export { Modal } from './Modal';
➕ 14-2. 장점
import 경로 짧아짐
외부로 공개할 API를 제한 가능
컴포넌트 사용성이 좋아짐
➕ 14-3. 주의점
모든 폴더에 무조건 만들지 않기
순환 참조 주의
큰 feature에서 불필요한 import 증가 가능
tree-shaking 확인 필요
- 공통 UI 정도는 barrel export가 편할 수 있습니다.
- feature 내부 깊은 파일까지 무조건 묶는 것은 신중하게 봐야 합니다.
✅ 15. 스타일 관리 전략
- 스타일 방식은 프로젝트마다 다릅니다.
- Tailwind, CSS Modules, styled-components, vanilla-extract, plain CSS 등 선택지가 있습니다.
- 중요한 것은 하나의 기준으로 일관되게 쓰는 것입니다.
➕ 15-1. 기준
공통 UI:
variant/size 기준 명확히
페이지 레이아웃:
layout 컴포넌트 또는 page 스타일
도메인 컴포넌트:
feature 내부에서 관리
전역 스타일:
최소화
디자인 토큰:
색상, 간격, radius, typography 기준화
➕ 15-2. 나쁜 스타일 구조
global.css에 모든 스타일 추가
className 이름 충돌
페이지마다 버튼 색상 직접 지정
모달 z-index 임의 증가
!important 남발
➕ 15-3. 좋은 방향
Button variant 사용
Modal z-index 기준 통일
Badge 상태 variant 통일
spacing token 활용
반응형 breakpoint 기준 통일
- 스타일은 작게 보면 CSS 문제지만, 크게 보면 UI 아키텍처 문제입니다.
- 공통 컴포넌트와 디자인 토큰이 있으면 화면 품질이 안정됩니다.
✅ 16. 라우팅 구조
- 라우팅은 화면 구조의 뼈대입니다.
- 고객 경로와 관리자 경로를 명확히 나누고, 권한 보호가 필요한 경로를 구분해야 합니다.
➕ 16-1. 경로 예시
고객:
/
/products
/products/:productId
/reservation
/reviews
관리자:
/admin/login
/admin
/admin/consults
/admin/orders
/admin/products
/admin/banners
/admin/statistics
/admin/settings
➕ 16-2. 기준
고객과 관리자 prefix 분리
관리자 layout 별도
관리자 route guard 적용
404 페이지 분리
권한 없음 페이지 분리
상세 페이지와 모달 경로 기준 정리
/admin 아래는 기본적으로 인증/권한 보호가 필요합니다.
- 고객 화면과 관리자 화면의 404/Forbidden 처리는 다르게 가져갈 수 있습니다.
✅ 17. Provider 구조
- React 앱에는 여러 Provider가 들어갑니다.
- QueryClientProvider, RouterProvider, AuthProvider, ThemeProvider, ToastProvider 등이 대표적입니다.
➕ 17-1. 예시
function AppProviders({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
<AuthProvider>
<ToastProvider>
{children}
</ToastProvider>
</AuthProvider>
</QueryClientProvider>
);
}
➕ 17-2. 기준
앱 전체에 필요한 provider만 상단 배치
특정 영역에만 필요한 provider는 범위 좁히기
자주 바뀌는 값을 거대한 context로 제공하지 않기
provider 순서 문서화
- Provider가 많아질수록 앱 초기 구조가 복잡해집니다.
- 필요한 범위에만 두는 것이 좋습니다.
✅ 18. 환경변수와 설정 구조
- 환경변수는 직접 여기저기 읽지 말고
config/env.ts에서 관리하는 것이 좋습니다.
➕ 18-1. 예시
const requiredEnv = {
apiBaseUrl: import.meta.env.VITE_API_BASE_URL,
assetBaseUrl: import.meta.env.VITE_ASSET_BASE_URL,
};
Object.entries(requiredEnv).forEach(([key, value]) => {
if (!value) {
throw new Error(`Missing env: ${key}`);
}
});
export const env = requiredEnv;
➕ 18-2. 기준
프론트에 Secret 넣지 않기
VITE_ 환경변수는 노출된다고 생각하기
API Base URL은 env에서만 읽기
환경별 .env.example 관리
배포 문서와 env 문서 연결
- 0728에서 정리한 것처럼 프론트 환경변수는 Secret 저장소가 아닙니다.
- 클라이언트에 노출돼도 되는 값만 넣어야 합니다.
✅ 19. 코드 리뷰 기준
- 1인 개발자라도 스스로 코드 리뷰 기준을 가져야 합니다.
- AI가 만든 코드라면 더더욱 리뷰 기준이 필요합니다.
➕ 19-1. 프론트 코드 리뷰 질문
이 파일이 올바른 feature 위치에 있는가?
공통 UI에 도메인 로직이 들어가지 않았는가?
API 경로를 컴포넌트에 직접 쓰지 않았는가?
queryKey에 조건이 빠지지 않았는가?
권한 조건이 공통 함수로 처리되는가?
로딩/에러/빈 상태가 있는가?
모바일 화면이 깨질 가능성이 있는가?
개인정보 로그가 남지 않는가?
➕ 19-2. 위험 변경
apiClient 변경
Auth/Permission 변경
QueryClient 설정 변경
공통 Button/Modal/Input 변경
전역 CSS 변경
라우팅 변경
환경변수 변경
상담 신청 폼 변경
- 위험 변경은 배포 전 QA 범위를 넓혀야 합니다.
- 공통 컴포넌트 하나 바꿨다고 한 화면만 보면 안 됩니다.
✅ 20. 리팩토링 전략
- 구조 정리는 한 번에 대공사로 하면 위험합니다.
- 기능 개발 중 작은 단위로 점진적으로 개선하는 것이 안전합니다.
➕ 20-1. 좋은 리팩토링 순서
1. 공통 Button/Input/Modal 기준 정리
2. API client 분리
3. 도메인별 API 함수 분리
4. query hook 분리
5. 상태 라벨/권한 util 분리
6. 큰 Page 컴포넌트 feature 컴포넌트로 분리
7. 폴더 구조 정리
8. 테스트 추가
➕ 20-2. 피해야 할 방식
모든 폴더를 한 번에 이동
기능 수정과 대규모 리팩토링을 섞음
테스트 없이 공통 컴포넌트 변경
import 경로 대량 변경 후 QA 생략
디자인 시스템을 처음부터 거창하게 만듦
- 리팩토링은 기능 동작을 유지하면서 구조를 개선하는 작업입니다.
- 기능 변경과 리팩토링은 가능하면 커밋을 분리하는 것이 좋습니다.
✅ 21. AI IDE/Codex에게 작업시키기 좋은 구조
- AI에게 코드를 맡길수록 프로젝트 구조가 중요해집니다.
- 구조가 명확하면 AI가 수정해야 할 파일을 더 잘 찾고, 불필요한 변경이 줄어듭니다.
➕ 21-1. AI 친화적인 구조
feature별 코드가 모여 있음
파일명이 역할을 잘 설명함
공통 UI 기준이 명확함
API 함수가 분리되어 있음
queryKey가 공통 관리됨
권한 util이 한 곳에 있음
docs에 화면/권한/API 기준이 있음
➕ 21-2. AI에게 주기 좋은 지시
features/admin-consults 내부만 수정해줘.
components/ui/Button은 건드리지 마.
API 경로는 adminConsultApi에 추가해.
queryKey는 queryKeys.adminConsults를 사용해.
권한 조건은 hasPermission을 사용해.
로딩/에러/빈 상태를 기존 EmptyState/ErrorState 패턴에 맞춰.
- 이런 지시가 가능하려면 프로젝트 구조가 먼저 정리되어 있어야 합니다.
- 구조가 없으면 AI가 임시 코드와 중복 파일을 만들 가능성이 큽니다.
✅ 22. 운영 문서와 프론트 구조 연결
- 프론트엔드 구조는 문서화하면 더 강해집니다.
- 특히 1인 개발자는 나중에 기억을 잃은 상태의 나를 위해 문서가 필요합니다.
➕ 22-1. 문서화하면 좋은 것
폴더 구조 설명
공통 컴포넌트 사용법
권한 기반 UI 기준
API 연동 기준
queryKey 규칙
환경변수 목록
배포 절차
QA 체크리스트
디자인 토큰
➕ 22-2. 문서 예시
# 프론트엔드 구조 문서
## 폴더 구조
- `features`: 도메인별 기능 코드
- `components/ui`: 순수 공통 UI
- `lib`: API client, query client
- `config`: 환경변수, route, permission 상수
## API 연동 규칙
- 컴포넌트에서 API 경로 직접 호출 금지
- 도메인별 `api` 파일에 함수 추가
- TanStack Query hook은 `hooks`에 작성
- queryKey는 `queryKeys` 객체 사용
## 권한 UI 규칙
- 버튼 노출은 `hasPermission` 사용
- 페이지 접근은 `ProtectedRoute` 사용
- 실제 권한 검사는 백엔드 Guard 기준
## 공통 UI 규칙
- Button variant: primary, secondary, danger, ghost
- Modal은 공통 Modal 사용
- Empty/Error 상태는 공통 컴포넌트 사용
- 문서는 AI에게도 좋은 컨텍스트가 됩니다.
- 코드 구조와 문서가 맞으면 작업 자동화 품질이 좋아집니다.
✅ 23. 구조가 무너졌을 때 정리 방법
- 이미 코드가 복잡해진 상태라면 한 번에 갈아엎지 말고 우선순위를 잡아야 합니다.
➕ 23-1. 먼저 찾을 것
가장 큰 Page 파일
중복 API 호출 코드
중복 상태 라벨 매핑
중복 Button/Modal 스타일
컴포넌트 안에 직접 쓰인 API URL
권한 조건 중복
utils.ts 같은 잡다한 파일
➕ 23-2. 정리 순서
1. 중복 API 호출을 도메인 api 파일로 이동
2. queryKey와 query hook 정리
3. 상태 라벨/권한 util 공통화
4. 공통 UI 컴포넌트 정리
5. 큰 페이지를 feature 컴포넌트로 분리
6. 폴더 구조 문서화
7. 테스트/QA 추가
- 구조 정리는 “자주 건드리는 곳”부터 하는 것이 효과적입니다.
- 거의 안 보는 화면을 먼저 정리해도 실무 효과는 낮습니다.
✅ 24. 1인 개발자 기준 현실적인 운영 구조
- 1인 개발자는 대기업식 아키텍처보다 “작고 일관된 구조”가 중요합니다.
- 너무 복잡한 패턴을 도입하면 오히려 유지보수가 힘들어질 수 있습니다.
➕ 24-1. 추천 기준
기능별 features 구조 사용
공통 UI는 최소 핵심만 정리
API client와 domain api는 반드시 분리
TanStack Query hook은 반복되는 곳부터 분리
권한 util은 초기에 정리
문서와 체크리스트를 같이 유지
대규모 리팩토링보다 작은 개선 반복
➕ 24-2. 지금 우선순위
1순위:
상담 신청, 관리자 상담 목록, 상태 변경, 권한 UI
2순위:
상품 상세, 상품 관리, 배너 관리, 엑셀 Export
3순위:
통계, 고급 테이블, 디자인 시스템 확장, Storybook
- 모든 화면을 예쁘게 구조화하는 것보다 핵심 흐름을 안정화하는 것이 먼저입니다.
- 상담 신청과 관리자 상담 처리 흐름은 서비스의 중심이므로 가장 먼저 정리해야 합니다.
✅ 25. 실무 체크리스트
➕ 25-1. 구조 체크리스트
- 고객 화면과 관리자 화면이 분리되어 있는가?
- feature별로 API, hook, type, component가 모여 있는가?
- 공통 UI와 도메인 컴포넌트가 구분되어 있는가?
- Page 컴포넌트가 너무 많은 책임을 갖고 있지 않은가?
- API URL이 컴포넌트에 직접 흩어져 있지 않은가?
- queryKey가 공통 기준으로 관리되는가?
- 권한 체크가 공통 함수로 관리되는가?
- 상태 라벨/variant 매핑이 한 곳에 있는가?
➕ 25-2. 유지보수 체크리스트
- 파일명만 봐도 역할을 알 수 있는가?
- utils/helper/common 같은 모호한 파일이 많지 않은가?
- 같은 타입이 여러 곳에 중복되어 있지 않은가?
- import 경로가 지나치게 복잡하지 않은가?
- feature끼리 불필요하게 의존하지 않는가?
- 공통 컴포넌트가 특정 도메인을 알고 있지 않은가?
- 환경변수가 config/env.ts에서 관리되는가?
- 새 기능을 추가할 위치가 명확한가?
➕ 25-3. AI 작업 체크리스트
- AI에게 수정 범위를 feature 단위로 줄 수 있는가?
- 건드리면 안 되는 공통 컴포넌트를 명확히 말할 수 있는가?
- API 추가 위치와 queryKey 기준을 알려줄 수 있는가?
- 권한 util과 공통 UI 패턴을 알려줄 수 있는가?
- docs에 폴더 구조와 API 규칙이 정리되어 있는가?
- AI 수정 후 git diff로 영향 범위를 확인하는가?
- 기능 변경과 리팩토링 커밋을 분리하는가?
- 배포 전 QA 체크리스트가 있는가?
✅ 26. AI를 활용해 프론트엔드 아키텍처를 점검할 때 질문법
- AI에게 아키텍처 점검을 요청할 때는 현재 폴더 구조, 주요 기능, 사용하는 라이브러리, 고객/관리자 화면 구분, 문제 증상을 같이 알려줘야 합니다.
➕ 26-1. 좋은 질문 예시
React + TypeScript + TanStack Query 기반 온라인 휴대폰 판매몰 프론트엔드 구조를 점검하고 싶어.
상황:
1. 고객 화면에는 상품 목록, 상품 상세, 상담 신청 모달, 사전예약 페이지가 있음
2. 관리자 화면에는 상담 목록, 주문 목록, 상품 관리, 배너 관리, 엑셀 Export, 권한 관리가 있음
3. 현재 API 호출 코드가 일부 컴포넌트 안에 직접 들어가 있음
4. 공통 Button/Modal/Input은 있지만 화면마다 약간씩 다르게 쓰이고 있음
5. 서버 상태는 TanStack Query를 사용함
6. 검색 조건은 URL query string으로 관리하고 싶음
7. 권한 체크는 hasPermission 유틸로 통일하고 싶음
8. AI IDE/Codex에게 기능 단위로 작업을 맡기기 쉬운 구조가 필요함
9. 1인 개발자라 너무 복잡한 엔터프라이즈 구조는 부담스러움
요청:
- 추천 폴더 구조
- 고객/관리자 화면 분리 기준
- features 구조 설계
- 공통 UI와 도메인 컴포넌트 구분
- api/hooks/types/utils 위치 기준
- queryKey 관리 방식
- 권한 util 위치
- 리팩토링 우선순위
- AI에게 작업 지시하기 좋은 구조
- 문서화 템플릿
을 실무 기준으로 정리해줘.
➕ 26-2. AI 답변 검증 기준
- 현재 규모에 비해 과하게 복잡한 구조를 강요하지 않는가?
- 고객 화면과 관리자 화면의 목적 차이를 반영하는가?
- API 호출 코드와 컴포넌트를 분리하라고 하는가?
- 공통 UI와 도메인 컴포넌트를 구분하는가?
- feature 기반 구조를 현실적으로 제안하는가?
- queryKey와 권한 util의 공통 관리를 포함하는가?
- 리팩토링을 작은 단계로 나누는가?
- AI 작업 범위를 제한하기 좋은 구조를 제안하는가?
📌 요약
- 프론트엔드 아키텍처는 화면, 컴포넌트, API, 상태 관리, 라우팅, 스타일, 권한, 유틸 코드를 어떤 기준으로 나누고 연결할지 정하는 구조입니다.
- 좋은 구조는 코드 위치를 예측하기 쉽고, 기능이 늘어나도 수정 범위와 영향 범위를 파악하기 쉽게 만듭니다.
- 고객 화면과 관리자 화면은 목적이 다르므로 layout, route, feature 기준으로 분리하는 것이 좋습니다.
features 기반 구조를 사용하면 상담, 상품, 주문, 배너처럼 도메인별 API, hook, type, component, util을 한곳에 모을 수 있습니다.
components/ui에는 Button, Input, Modal, Badge 같은 순수 공통 UI만 두고, ConsultStatusBadge처럼 도메인 개념을 아는 컴포넌트는 feature 내부에 두는 것이 좋습니다.
- Page 컴포넌트는 URL params, query 호출, 화면 조립 정도를 담당하고, 세부 UI와 비즈니스 로직은 feature 컴포넌트와 hook으로 분리하는 것이 좋습니다.
- API URL, queryKey, 권한 체크, 상태 라벨 매핑은 한 곳으로 모아야 중복과 실수를 줄일 수 있습니다.
utils.ts, helper.ts, common.ts 같은 모호한 파일명은 피하고, 기능이 드러나는 파일명으로 분리해야 합니다.
- 리팩토링은 한 번에 대공사로 하기보다 API client 분리, query hook 분리, 공통 UI 정리, 큰 Page 분리처럼 작은 단계로 진행하는 것이 안전합니다.
- AI IDE/Codex에게 작업을 맡기려면 feature별 구조, 명확한 파일명, 공통 UI 기준, queryKey 규칙, 권한 util, 문서화가 매우 중요합니다.