[TOJ] 개발기록 - 프로젝트 폴더구조

조민호·2023년 11월 9일
1

해당 프로젝트를 진행하면서 사용하게 될 리액트 폴더구조를 간략히 표기하면 아래와도 같다

📦src
 ┣ 📂apis
 ┣ 📂assets
 ┣ 📂components
 ┃ ┣ 📂core
 ┃ ┃ ┗ 📂
 ┃ ┣ 📂layout
 ┃ ┃ ┗ 📂
 ┃ ┣ 📂widget
 ┃ ┗ ┗ 📂
 ┣ 📂config
 ┃ ┣ 📜const.ts
 ┃ ┗ 📜path.ts
 ┣ 📂data
 ┣ 📂hooks
 ┃ ┗📂queries
 ┣ 📂mocks
 ┣ 📂pages
 ┃ ┣ 📂
 ┃ ┗ 📜PageRouter.tsx
 ┣ 📂stores
 ┣ 📂svgs
 ┣ 📂type
 ┣ 📂util
 ┣ 📜App.css
 ┣ 📜App.tsx
 ┣ 📜main.tsx
 ┗ 📜vite-env.d.ts

apis 폴더

각종 api 로직들을 보관한다

다만 여기서 보관하는 방식은 CRUD별로 , 혹은 기능별로 분리해서 보관해도 된다

components 폴더

컴포넌트와 관련된 모든 코드가 들어간다
각 페이지마다 사용되는 컴포넌트들을 나누어서 정의하는 곳이다

components 폴더 내부에 존재하는 폴더들은 다음과 같다

1. core

각 페이지마다 공통적으로 사용되는 주요 컴포넌트들.

가장 작은 단위의 요소들 즉 , html태그로 존재하는 것들을 말한다

(button input checkbox li 등 …)

프로젝트 전반적으로 사용되는 위 요소들을 여기서 작성한 후,

각 컴포넌트에서 import 해서 사용한다

  • button (버튼 컴포넌트)

    사용되는 카테고리 별로 구분해서 사용한다
    ex) AuthButton (로그인,로그아웃) , SumitButton (각종 제출 버튼)

  • input (인풋 컴포넌트)

    사용되는 카테고리 별로 구분해서 사용한다
    ex) SignInInput , CommentInput

  • list (리스트 컴포넌트)
    • 리스트의 경우 리스트 내용들을 여기서 모두 작성해준다

      📦core
       ┣ 📂button
       ┃ ┗ 📜 ...
       ┣ 📂input
       ┃ ┗ 📜...
       ┣ 📂list
       ┃ ┣ 📜index.ts
       ┃ ┣ 📜Li.tsx //아래것들을 합친 것
       ┃ ┣ 📜LiButton.tsx
       ┃ ┣ 📜LiCheckBox.tsx
       ┃ ┗ 📜LiTextInput.tsx
       ┗ 📜index.ts

위에 언급하길, 기능 별로 구분해서 작성하는게 아니라 사용되는 카테고리 별로 구분해서 사용한다고 했다

왜냐하면 같은 카테고리 별로 사용되는 button , input 태그들은 보통 동일한 구조를 지니고 있기 때문이다


예를 들어 Navbar의 메뉴 버튼들은 코드 구조, 스타일 , 레이아웃 등이 거의 동일하다

그러므로 core/menuButton.tsx 에다가 props로 각 세부사항들을 넘겨줘서 재사용하는 것이다

기능 별로 구분해서 loginButton , logoutButton , homeButton 처럼 하나씩 만들 필요가 없다

2. layout

공통된 레이아웃을 지정

프로젝트 규모가 커서 아래처럼 각 페이지들을 묶어서

레이아웃 및 디자인을 적용하고자 할 때 사용한다.

아래와 같이 특정 레이아웃을 일괄 적용할 페이지들 끼리 라우터 별로 분리를 한 다음 ,

레이아웃으로 감싸는 것이다

PageRouter.tsx

📦layout
 ┣ 📜NeswLetterLayout.tsx
 ┣ 📜SignUpLayout.tsx
 ┗ 📜index.ts
import React from "react";
import styled from "styled-components";
import { Outlet } from "react-router-dom";

const NeswLetterLayout = () => {
  return (
    <NeswLetterWrapper >
      <Outlet />
    </NeswLetterWrapper >
  );
};

const NeswLetterWrapper = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;

  width: 100%;
  height: 100vh;

  **// 여기에 일괄적으로 적용할 레이아웃의 디자인 지정**

`;

export default NeswLetterLayout;

NeswLetterLayout , SignUpLayout 이 2개의 레이아웃을 여기서 만든 다음에

라우터 파일에 적용하는 것이다

widget

각 페이지 안에서 구성되는 일반 컴포넌트들을 작성한다
하나의 페이지에 구성되는 가장 큰 단위의 컴포넌트인 것이다

여기 작성되는 컴포넌트들은 실제 페이지의 각 부분들을 차지하는 컴포넌트들이 된다

그러므로 여기서 core 나 widget안에 있는 또 다른 컴포넌트들을 조합해서

일반적인 컴포넌트들을 만드는 것이다

  • 공통 컴포넌트(Navbar , Footer) 같은 경우에는 widget/common 폴더에 작성한다

  • 그 외의 일반 컴포넌트들은 widget아래에 폴더별로 작성을 한다

    여기서 하나의 컴포넌트에 사용되는 하위 컴포넌트는

    상위 컴포넌트가 작성된 폴더 안에 생성한다

    ProblemInfo컴포넌트에서 하위 컴포넌트로 사용되는

    ProblemDetails.tsx 나 Title.tsx 는

    probleminfo폴더 안에 폴더를 따로 생성해서 작성한다

configs

각종 설정 사항들

  • const (프로젝트에 필요한 상수들)
  • path (라우팅에 사용되는 경로들)

pages

라우팅에 사용되는 각 페이지들

  • 이 폴더 안에 PageRouter.tsx로 라우팅을 작성한다
  • 각 페이지 이름을 폴더명으로 사용하고
  • 이 안에 각 페이지들을 작성한다

각 페이지들은 components의 내용들을 import해서 구현한다

hooks

커스텀 훅들

stores

전역변수 설정 (zustand 코드)

type

전역적으로 사용 할 타입들


index.ts 패턴

components를 예로 들어보자

📦components
 ┣ 📂core
 ┃ ┣ 📂button
 ┃ ┃ ┣ 📜Button.tsx
 ┃ ┃ ┗ 📜**index.ts**
 ┃ ┣ 📂input
 ┃ ┃ ┣ 📜**index.ts**
 ┃ ┃ ┗ 📜Input.tsx
 ┃ ┣ 📂list
 ┃ ┃ ┣ 📜**index.ts**
 ┃ ┃ ┣ 📜Li.tsx  // LiButton,LiCheckBox,LiTextInput를 합친 것
 ┃ ┃ ┣ 📜LiButton.tsx
 ┃ ┃ ┣ 📜LiCheckBox.tsx
 ┃ ┃ ┗ 📜LiTextInput.tsx
 ┃ ┗ 📜**index.ts**
 ┣ 📂layout
 ┃ ┣ 📜CommonLayout.tsx
 ┃ ┣ 📜**index.ts**
 ┃ ┗ 📜SignUpInLayout.tsx
 ┣ 📂widget
 ┃ ┣ 📜**index.ts**
 ┃ ┣ 📜TodoInput.tsx
 ┃ ┣ 📜TodoList.tsx
 ┃ ┗ 📜TodoListNone.tsx
 ┗ 📜
  • list/index.ts 는 아래와 같다
    export { default as Li } from "./Li";
    export { default as LiButton } from "./LiButton";
    export { default as LiTextInput } from "./LiTextInput";
    export { default as LiCheckBox } from "./LiCheckBox";
    LiButton , LiTextInput , LiCheckBox 에서 export default로 export를 했다면 그걸 각각 받아서 as 로 지정한 이름으로 다시 export 해주는 것이다
  • list 상위 폴더인 core/index.ts는 아래와 같다
    export * from "./button";
    export * from "./input";
    export * from "./list"; // ./list는 ./list/index.ts 가 된다
    list/index.ts에서 각 컴포넌트들을 하나씩 export 해줬다면 list폴더 아래에 있는 모든 컴포넌트들( * )을 export 해주는 것이다
  • core 상위 폴더인 components/index.ts는 아래와 같다
    export * from './layout';
    export * from './core'; // ./core는 ./core/index.ts 가 된다
    export * from './widget';
    core/index.ts에서 core폴더에 존재하는 컴포넌트들을 모두 export 해줬다면 components폴더 아래에 있는 모든 컴포넌트들( * )을 export 해주는 것이다
    • core 아래에 있는 , 각 list,input,button 폴더 아래에 있는 , 모든 컴포넌트들을 export
    • widget 아래에 있는 ..
    • layout 아래에 있는 ..

이렇게 하게 되면 components폴더 아래에 있는 모든 파일들을 export 해주는 것이고
외부에서 components폴더 아래에 있는 모든 파일들에 접근할 때
”components” 라는 경로로 간편하게 import가 가능하다

예시를 보면

  • 외부에 존재하는 디렉토리에서 import 할 때 pages/todo/TodoPage.tsx
    import React, { useEffect, useState } from "react";
    import { useNavigate } from "react-router-dom";
    import styled from "styled-components";
    
    **// components
    import { TodoInput, TodoList } from "components";**
    
    ...
  • components/widget 에서 components/core 에 있는 컴포넌트를 import 할 때 (같은 components 디렉토리) components/widget/TodoInput.tsx
    import React from "react";
    import styled from "styled-components";
    
    **// components
    import { Button, Input } from "components";**
    
    ...

절대경로 사용시

  • 절대경로를 src를 기준으로 사용하며

  • 다른 디렉토리에 있는 파일들은 절대경로를 통해서 가져온다

  • 하위 디렉토리 및 동일 디렉토리의 경로에서는 상대 경로를 사용한다

    📦probleminfo
     ┣ 📂testcases
     ┃ ┣ 📜index.ts
     ┃ ┗ 📜TestCases.tsx
     ┣ 📂title
     ┃ ┣ 📜index.ts
     ┃ ┗ 📜Title.tsx
     ┣ 📜index.ts
     ┗ 📜ProblemInfo.tsx
    1. ProblemInfo.tsx 에서 TestCases.tsx를 가져올 땐

      상대 경로로 가져오며

    2. TestCases.tsx 에서 Title.tsx 을 가져올 때도 상대경로로 가져온다


모든 폴더구조는 재사용성을 강조하기 위해 props로 각 컴포넌트 내에 사용되는 다양한 정보들을 최대한 많이 넘겨주는 방식으로 사용해야 한다

각 컴포넌트들을 호출 할 때 그 요소를 사용하는데 필요한 옵션들은 전부 props로 넘겨준다.

  • 사용되는 로직들은 함수로
  • style 관련 요소들
  • 상태 , 상태 업데이트 함수 등
profile
할 수 있다

1개의 댓글

comment-user-thumbnail
2023년 11월 16일

우연히 폴더 구조 찾다가 읽게 되었는데 깔끔한 설명 감사합니당

답글 달기