Next.js에서 특히 App Router를 사용할 때 폴더 구조는 코드 유지보수성과 개발 효율성에 큰 영향을 미칩니다. 이 글에서는 랜딩 페이지 중심의 Next.js 프로젝트에서 촐더 구조를 개선한 사례를 공유합니다!
📌 기존 폴더 구조의 문제점 📌
프로젝트 초기에는 다음과 같은 구조로 시작했습니다.
📦src
┣ 📂app
┃ ┣ 📂components
┃ ┃ ┣ 📂landing
┃ ┃ ┃ ┣ 📜Accomplishment.tsx
┃ ┃ ┃ ┣ 📜CaseCard.tsx
┃ ┃ ┃ ┣ 📜CaseSection.tsx
┃ ┃ ┃ ┣ 📜Closing.tsx
┃ ┃ ┃ ┣ 📜CurriculumCard.tsx
┃ ┃ ┃ ┗ ...
┃ ┃ ┣ 📂typography
┃ ┃ ┃ ┣ 📜H2.tsx
┃ ┃ ┃ ┗ 📜Text.tsx
┃ ┃ ┣ 📜CtaButton.tsx
┃ ┃ ┣ 📜DesktopViewContainer.tsx
┃ ┃ ┣ 📜Footer.tsx
┃ ┃ ┗ ...
┃ ┣ 📜page.tsx
┃ ┗ ...
이 구조의 주요 문제점:
- 관련 컴포넌트의 분산: 섹션별로 관련된 컴포넌트들이 분산되어 있어 코드 탐색이 어려움
- 책임 구분 불명확: 공통 컴포넌트와 특정 페이지 컴포넌트 구분이 모호함
- 재사용성 저하: 촐더 구조가 컴포넌트의 재사용성을 고려하지 않음
- 유지보수 어려움: 프로젝트 규모가 커질수록 관련 파일 찾기 어려움
📌 개선된 폴더 구조 📌
프로젝트 구조를 다음과 같이 개선했습니다.
📦src
┣ 📂app
┃ ┣ 📂_home
┃ ┃ ┗ 📂components
┃ ┃ ┃ ┣ 📂common
┃ ┃ ┃ ┃ ┗ 📜LeftTitle.tsx
┃ ┃ ┃ ┣ 📂accomplishment
┃ ┃ ┃ ┃ ┗ 📜Accomplishment.tsx
┃ ┃ ┃ ┣ 📂case
┃ ┃ ┃ ┃ ┣ 📜CaseCard.tsx
┃ ┃ ┃ ┃ ┗ 📜CaseSection.tsx
┃ ┃ ┃ ┣ 📂caseStudyRequest
┃ ┃ ┃ ┃ ┗ 📜Report.tsx
┃ ┃ ┃ ┣ 📂curriculum
┃ ┃ ┃ ┃ ┣ 📜CurriculumCard.tsx
┃ ┃ ┃ ┃ ┗ 📜CurriculumSection.tsx
┃ ┃ ┃ ┗ ...
┃ ┣ 📂components
┃ ┃ ┣ 📂typography
┃ ┃ ┃ ┣ 📜H2.tsx
┃ ┃ ┃ ┗ 📜Text.tsx
┃ ┃ ┣ 📜DesktopViewContainer.tsx
┃ ┃ ┗ ...
┣ 📂components
┃ ┣ 📂ui
┃ ┃ ┣ 📜button.tsx
┃ ┃ ┣ 📜input.tsx
┃ ┃ ┗ ...
📌 주요 개선 사항 📌
1. 페이지별 컴포넌트 분리
- 홈페이지 관련 컴포넌트를 _home 폴더로 분리했습니다. App Router에서 언더스코어(_)로 시작하는 폴더는 라우팅에서 제외되므로, URL 구조에 영향을 주지 않으면서도 코드를 논리적으로 구성할 수 있습니다.
2. 섹션별 폴더 구조화
- 기존에 평면적으로 나열되어 있던 컴포넌트들을 섹션별로 폴더화하여 구성했습니다. 예를 들어 기존의 CaseCard.tsx와 CaseSection는 이제 Case 폴더 내에 함께 위치합니다.
3. 의미 있는 폴더명 사용
- 기존의 모호한 폴더명(ex: report)을 더 명확한 이름(ex: caseStudyRequest)으로 변경했습니다. 이렇게 하면 개발자가 코드베이스를 처음 접할 때도 각 폴더의 목적을 쉽게 이해할 수 있습니다.
4. 공통 컴포넌트 추출
- 여러 섹션에서 반복되는 UI 패턴을 발견하고 공통 컴포넌트로 추출했습니다. 예를 들어, 여러 섹션에서 사용되는 제목 스타일을 LeftTitle 컴포넌트로 추출했습니다.
// _home/components/common/LeftTitle.tsx
interface LeftTitleProps {
title: string;
subTitle: string;
description: React.ReactNode;
}
export const LeftTitle = ({ title, subTitle, description }: LeftTitleProps) => {
return (
<div className="flex flex-col w-full gap-2">
<Text weight="bold" size="xl" className="...">
{title}
</Text>
<Text weight="bold" size="3xl" className="...">
{subTitle}
</Text>
<Text weight="medium" size="xl" className="...">
{description}
</Text>
</div>
);
};
이 컴포넌트는 다음과 같이 사용합니다.
// PointSection에서 사용
const POINT_TITLE = {
title: "POINT",
subTitle: "TeamSpartaの強み",
description: (
<>
受講生一人ひとりの成長のために
<br />
スパルタならではのソリューションで密着管理します。
</>
)
};
const PointSection = () => {
return (
<section>
<DesktopViewContainer>
<LeftTitle
title={POINT_TITLE.title}
subTitle={POINT_TITLE.subTitle}
description={POINT_TITLE.description}
/>
{/* 나머지 컨텐츠 */}
</DesktopViewContainer>
</section>
);
};
5. 전역 UI 컴포넌트 분리
- 애플리케이션 전체에서 사용되는 UI 컴포넌트는 src/components/ui 폴더로 분리했습니다. 이는 각 페이지에 특화된 컴포넌트와 전역 UI 컴포넌트를 명확히 구분합니다.
📌 개선 효과 📌
- 개발 효율성 증가: 관련 파일을 더 빠르고 찾고 수정할 수 있게 됨
- 코드 재사용성 향상: 공통 컴포넌트 추출로 중복 코드 감소
- 협업 용이성: 다른 개발자가 코드베이스를 더 쉽게 이해하고 작업할 수 있음
- 유지보수성 개선: 폴더 구조가 명확해져 버그 수정과 기능 추가가 더 쉬워짐
- 확장성 증가: 새로운 페이지나 섹션을 추가할 때 기존 패턴을 따르기 쉬움
📌 컴포넌트 refactoring 사례 📌
폴더 구조 개선과 함께 컴포넌트 내부 코드도 refactoring 했습니다. 예를 들어 InrtoVideoSection 컴포넌트는 다음과 같이 개선되었습니다.
기존 코드:
const IntroVideoSection = () => {
return (
<section>
<DesktopViewContainer>
<div className="flex gap-6">
<div className="h-full">
<div className="max-w-[564px]">
<video>
<source src={`${CDN_BASE_URL}/video.mp4`} />
</video>
</div>
</div>
<div className="flex flex-col">
<Text>「タイトル」</Text>
<Text>
説明テキスト<br />
説明テキスト
</Text>
</div>
</div>
</DesktopViewContainer>
</section>
);
};
개선 코드:
// 비디오 컴포넌트 분리
const VideoComponent = () => {
return (
<div className="h-full">
<div className="max-w-[564px]">
<video>
<source src={`${CDN_BASE_URL}/video.mp4`} />
</video>
</div>
</div>
);
};
const IntroVideoSection = () => {
return (
<section>
<DesktopViewContainer>
<div className="flex gap-6">
<VideoComponent />
<div className="flex flex-col">
<Text>「タイトル」</Text>
<Text>
説明テキスト<br />
説明テキスト
</Text>
</div>
</div>
</DesktopViewContainer>
</section>
);
};
📌 결론 📌
Next.js 프로젝트 폴더 구조를 개선하는 것은 단순한 파일 이동 이상의 가치가 있습니다. 이는 코드 품질, 개발, 경험, 그리고 궁극적으로 사용자 경험까지 향상시킬 수 있습니다.
'인턴' 카테고리의 다른 글
[ Troubleshooting🛠️ ] Zod 스키마 검증과 데이터 처리 (0) | 2025.03.28 |
---|---|
Next.js에서 서버와 클라이언트 간 모바일 감지 연동하기 (0) | 2025.03.27 |
React와 styled-components로 만드는 커스텀 토글 버튼 (0) | 2025.03.25 |
useMemo와 useCallback (0) | 2025.03.25 |
Jotai (0) | 2025.03.25 |