Skip to content

Latest commit

Β 

History

History
459 lines (351 loc) Β· 12.4 KB

File metadata and controls

459 lines (351 loc) Β· 12.4 KB

πŸš€ PLAYIDEA WEB PAGE

Index

  1. μ‹œμž‘ν•˜κΈ°
  2. 기술 μŠ€νƒ
  3. 디렉토리 ꡬ쑰 κ°€μ΄λ“œ
  4. ν˜‘μ—… 방법
  5. μ½”λ“œ μ»¨λ²€μ…˜

1. μ‹œμž‘ν•˜κΈ°

1. Clone

$ git clone https://github.com/PI304/PI_WEB.git
$ cd PI_WEB
$ yarn install

2. Run

$ yarn dev

2. 기술 μŠ€νƒ



3. 디렉토리 ꡬ쑰 κ°€μ΄λ“œ

β”œβ”€β”€ @types
β”‚Β Β  β”œβ”€β”€ base.d.ts
β”‚Β Β  β”œβ”€β”€ index.d.ts
β”‚Β Β  β”œβ”€β”€ main.d.ts
β”‚Β Β  β”œβ”€β”€ seo.d.ts
β”‚Β Β  β”œβ”€β”€ shared.d.ts
β”‚Β Β  β”œβ”€β”€ styled.d.ts
β”‚Β Β  β”œβ”€β”€ team.d.ts
β”‚Β Β  β”œβ”€β”€ value.d.ts
β”‚Β Β  └── work.d.ts
β”œβ”€β”€ components
β”‚Β Β  β”œβ”€β”€ layouts
β”‚Β Β  β”œβ”€β”€ pages
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ main
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ team
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ value
β”‚Β Β  β”‚Β Β  └── work
β”‚Β Β  β”œβ”€β”€ seo
β”‚Β Β  └── shared
β”œβ”€β”€ constants
β”‚Β Β  β”œβ”€β”€ index.ts
β”‚Β Β  β”œβ”€β”€ paths.ts
β”‚Β Β  └── seo.ts
β”œβ”€β”€ hooks
β”œβ”€β”€ modules
β”œβ”€β”€ pages
β”‚Β Β  β”œβ”€β”€ _app.tsx
β”‚Β Β  β”œβ”€β”€ _document.tsx
β”‚Β Β  β”œβ”€β”€ index.tsx
β”‚Β Β  β”œβ”€β”€ main.tsx
β”‚Β Β  β”œβ”€β”€ team.tsx
β”‚Β Β  β”œβ”€β”€ value.tsx
β”‚Β Β  └── work.tsx
β”œβ”€β”€ public
β”œβ”€β”€ styles
β”‚Β Β  β”œβ”€β”€ colors.ts
β”‚Β Β  β”œβ”€β”€ devices.ts
β”‚Β Β  β”œβ”€β”€ fonts.ts
β”‚Β Β  β”œβ”€β”€ global.ts
β”‚Β Β  β”œβ”€β”€ index.ts
β”‚Β Β  β”œβ”€β”€ reset.ts
β”‚Β Β  β”œβ”€β”€ sizes.ts
β”‚Β Β  β”œβ”€β”€ styled.ts
β”‚Β Β  └── svgs.tsx
β”œβ”€β”€ next-env.d.ts
β”œβ”€β”€ next.config.js
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ README.md
β”œβ”€β”€ package.json
└── yarn.lock

1. @types 디렉토리

  1. λͺ¨λ“  type 선언은 μ΄κ³³μ—μ„œ ν•΄μ£Όμ„Έμš”.
  2. 파일 이름은 *.d.ts ν˜•μ‹μ„ μ§€μΌœμ£Όμ„Έμš”.
  3. importκ°€ ν•„μš”ν•œ νƒ€μž… μ„ μ–Έ μ‹œμ—λŠ” @types/index.d.ts νŒŒμΌμ— μ„ μ–Έν•΄μ£Όμ„Έμš”.

PLEASE DO NOT - λ‹€λ₯Έ λ””λ ‰ν† λ¦¬μ˜ νŒŒμΌμ—μ„œ νƒ€μž… μ„ μ–Έ

2. components 디렉토리

  1. components/layouts - λ ˆμ΄μ•„μ›ƒ μ»΄ν¬λ„ŒνŠΈ
  2. components/pages - 각 page의 μ΅œμƒμœ„ μ»΄ν¬λ„ŒνŠΈ 및 ν•΄λ‹Ή pageμ—μ„œ μ‚¬μš©λ˜λŠ” ν•˜μœ„ μ»΄ν¬λ„ŒνŠΈ
  3. components/seo - CustomHead λ“± SEO에 μ‚¬μš©λ˜λŠ” μ»΄ν¬λ„ŒνŠΈ
  4. components/shared - 기타 곡용 μ»΄ν¬λ„ŒνŠΈ
  5. components/... - μΆ”ν›„ 좔가될 수 μžˆμŠ΅λ‹ˆλ‹€.

3. constants 디렉토리

  1. μ€‘μš”ν•œ μƒμˆ˜λŠ” μ΄κ³³μ—μ„œ κ΄€λ¦¬ν•΄μ£Όμ„Έμš”. (예: paths, seo...)
  2. μ€‘μš”ν•¨μ˜ κΈ°μ€€ (1개 이상 μΆ©μ‘± μ‹œ μ€‘μš”ν•˜λ‹€κ³  νŒλ‹¨)
    1. 2번 이상 μ‚¬μš©λ˜λŠ” 경우 (μž¬μ‚¬μš©)
    2. μΆ”ν›„ λ…Όμ˜μ— μ˜ν•΄ 변경될 수 μžˆλŠ” 경우 (μΆ”μ μš©μ΄)
    3. 기타 μ‚¬μœ λ‘œ μ€‘μš”ν•˜λ‹€κ³  νŒλ‹¨ν•˜λŠ” 경우

4. hooks 디렉토리

custom hook은 이곳에 μž‘μ„±ν•΄μ£Όμ„Έμš”.

5. modules 디렉토리

μΆ”ν›„ Redux κ΄€λ ¨ νŒŒμΌλ“€μ΄ λ“€μ–΄κ°‘λ‹ˆλ‹€.

6. pages 디렉토리

λΌμš°ν„° 섀정을 μœ„ν•œ Next.js μ˜ˆμ•½ λ””λ ‰ν† λ¦¬μž…λ‹ˆλ‹€.

7. public 디렉토리

이미지 λ“± asset은 public/assets 에 μ €μž₯ν•΄μ£Όμ„Έμš”.

μ°Έκ³  - SVGλŠ” 파일둜 μ €μž₯ν•˜μ§€ μ•Šκ³ , styles/svgs.tsx에 μƒμˆ˜λ‘œ μ •μ˜ν•˜μ—¬ κ΄€λ¦¬ν•©λ‹ˆλ‹€.

8. styles 디렉토리

  1. styles/colors.ts - λ””μžμΈ 컬러
  2. styles/devices.ts - λ°˜μ‘ν˜• μŠ€νƒ€μΌμ„ μœ„ν•œ λ””λ°”μ΄μŠ€ ꡬ뢄 κΈ°μ€€ λ“±
  3. styles/fonts.ts - λ””μžμΈ νƒ€μ΄ν¬κ·Έλž˜ν”Ό
  4. styles/global.ts - μ „μ—­ μŠ€νƒ€μΌ
  5. styles/reset.ts - 리셋 μŠ€νƒ€μΌ
  6. styles/styled.ts - μ€‘μš”ν•œ Styled-components (1번 이상 μž¬μ‚¬μš© OR μΆ”μ μš©μ΄)
  7. styles/svgs.tsx - SVG μ •μ˜

9. Named Export & Re-Export in Index.ts

각 λ””λ ‰ν† λ¦¬μ—λŠ” index.tsκ°€ μžˆμŠ΅λ‹ˆλ‹€.

// components/shared/index.ts
export * from './ContactWidget';
export * from './Navigator';
export * from './SpaceBackground';

디렉토리 λ‚΄λΆ€μ˜ νŒŒμΌλ“€μ„ ν•œκΊΌλ²ˆμ— λͺ¨μ•„ λ‹€μ‹œκΈˆ Re-Export ν•˜μ—¬,
λ‹€λ₯Έ λ””λ ‰ν† λ¦¬μ˜ νŒŒμΌμ—μ„œ μ•„λž˜μ™€ 같이 디렉토리λͺ…λ§ŒμœΌλ‘œ Import ν•˜κΈ° μœ„ν•¨μž…λ‹ˆλ‹€.

// components/layouts/WithNavigatorLayout.tsx
import { Navigator, ContactWidget } from '../shared';

μ»΄ν¬λ„ŒνŠΈλ₯Ό 각각 Importν•˜λŠ” 것에 λΉ„ν•˜μ—¬ Import 문을 짧게 관리할 수 있고,
μΆ”ν›„ μ»΄ν¬λ„ŒνŠΈ 파일 이름이 λ°”λ€ŒλŠ” κ²½μš°μ— λŒ€μ‘ν•˜κΈ° μš©μ΄ν•˜λ‹€λŠ” 이점이 μžˆμŠ΅λ‹ˆλ‹€.

export * from './μ»΄ν¬λ„ŒνŠΈκ²½λ‘œ' ν˜•μ‹μœΌλ‘œ νŒŒμΌμ„ Re-Export ν•˜κΈ° μœ„ν•΄μ„œλŠ”,
μ»΄ν¬λ„ŒνŠΈ νŒŒμΌμ—μ„œ μ»΄ν¬λ„ŒνŠΈλ₯Ό Default Exportκ°€ μ•„λ‹Œ Named Export둜 내보내주어야 ν•©λ‹ˆλ‹€.

λ”°λΌμ„œ μ»΄ν¬λ„ŒνŠΈλŠ” 항상 Named Export ν˜•μ‹μœΌλ‘œ λ‚΄λ³΄λ‚΄μ£Όμ‹œκ³ , ν•΄λ‹Ή λ””λ ‰ν† λ¦¬μ˜ index.tsμ—μ„œ μœ„μ™€ 같이 Re-Export ν•΄μ£Όμ„Έμš”.

μ•„λž˜λŠ” 잘λͺ»λœ μ˜ˆμ‹œμ™€ μ˜¬λ°”λ₯Έ μ˜ˆμ‹œμ˜ λΉ„κ΅μž…λ‹ˆλ‹€.

// 잘λͺ»λœ μ˜ˆμ‹œ (Default Export)
export default function Component() {
  return <></>;
}

// 잘λͺ»λœ μ˜ˆμ‹œ (Default Export)
const Component = () => {
  return <></>;
};

export default Component;

// 잘λͺ»λœ μ˜ˆμ‹œ (Named Export + 일반 ν•¨μˆ˜)
export function Component() {
  return <></>;
};
// μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ (Named Export + ν™”μ‚΄ν‘œ ν•¨μˆ˜)
export const Component = () => {
  return <></>;
};

4. ν˜‘μ—… 방법

1. Branching Strategy

PR을 톡해 Feature λΈŒλžœμΉ˜λ“€μ„ Develop에 λ¨Έμ§€ν•˜κ³ ,
μ΅œμ’… 배포할 μ‹œκΈ°κ°€ 되면 Admin κ΄€λ¦¬μžκ°€ Develop 브랜치λ₯Ό Production λΈŒλžœμΉ˜μ— λ¨Έμ§€ν•˜μ—¬ λ°°ν¬ν•˜λŠ” λ‹¨μˆœν•œ ꡬ쑰λ₯Ό λ”°λ¦…λ‹ˆλ‹€.

2. ν˜‘μ—… κ³Όμ •

  1. λ‘œμ»¬μ— Cloneν•œ λ ˆν¬μ—μ„œ Feature 브랜치λ₯Ό μƒμ„±ν•˜μ—¬ μž‘μ—…ν•©λ‹ˆλ‹€.
  2. 개발이 끝났닀면 λ‹€μ‹œ ν•œλ²ˆ 원격 레포의 μ΅œμ‹  컀밋을 λ°›μ•„μ™€μ€λ‹ˆλ‹€.
// 체크아웃 ν•˜κΈ° μ „, Feature λΈŒλžœμΉ˜μ—μ„œμ˜ μž‘μ—… λ‚΄μš©μ„ 컀밋해야 ν•©λ‹ˆλ‹€.
$ git checkout develop
$ git pull origin develop
  1. μΆ”κ°€λœ μ΅œμ‹  컀밋이 μžˆλ‹€λ©΄ λ‚΄κ°€ μž‘μ—…ν•œ Feature 브랜치λ₯Ό, μƒˆλ‘œμš΄ 컀밋이 μΆ”κ°€λœ Develop 브랜치의 λ§ˆμ§€λ§‰ μ»€λ°‹μœΌλ‘œ Rebase ν•©λ‹ˆλ‹€. (λ§κ·ΈλŒ€λ‘œ baseλ₯Ό λ°”κΎΌλ‹€λŠ” λœ»μž…λ‹ˆλ‹€)
$ git checkout Feature/[브랜치λͺ…]
$ git rebase develop
  1. 좩돌이 λ°œμƒν–ˆλ‹€λ©΄, μ—λ””ν„°μ—μ„œ μΆ©λŒμ„ ν•΄κ²°ν•œ λ’€ μ•„λž˜ λͺ…λ Ήμ–΄λ₯Ό μž…λ ₯ν•©λ‹ˆλ‹€.
$ git add .
$ git rebase --continue
  1. 이상이 μ—†λ‹€λ©΄ Feature 브랜치λ₯Ό push ν•©λ‹ˆλ‹€.
$ git push origin Feature/[브랜치λͺ…]
  1. Githubμ—μ„œ PR을 μƒμ„±ν•©λ‹ˆλ‹€. PR μ‹œ λ‚˜νƒ€λ‚˜λŠ” ν…œν”Œλ¦Ώμ„ μ±„μ›Œμ£Όμ„Έμš”.
## Feature Description

- 이런 이런 κΈ°λŠ₯μž…λ‹ˆλ‹€

## To Reviewers

- 이런 이런 점을 μœ μ˜ν•΄μ£Όμ„Έμš”
  1. Review 과정을 κ±°μΉ©λ‹ˆλ‹€.

  2. Self Merge ν•΄μ£Όμ„Έμš”.

  3. Squash Merge되며, Merge된 Feature BranchλŠ” μžλ™ μ‚­μ œλ©λ‹ˆλ‹€.

  4. λ‘œμ»¬μ—μ„œ Develop 브랜치둜 μ²΄ν¬μ•„μ›ƒν•œ λ’€ Pullν•˜κ³ , μƒˆλ‘œμš΄ Feature 브랜치둜 λΆ„κΈ°ν•˜μ—¬ λ‹€μŒ μž‘μ—…μ„ μ§„ν–‰ν•΄μ£Όμ„Έμš”.

3. μ½”λ“œ 리뷰

  1. PR μ‹œ sookyeongyeom을 Reviewer둜 μ§€μ •ν•©λ‹ˆλ‹€.
  2. μˆ˜μ •μ΄ ν•„μš”ν•˜λ©΄ Request Changes둜 μ½”λ“œ μˆ˜μ •μ„ μš”μ²­λ“œλ¦½λ‹ˆλ‹€.
  3. 이상이 μ—†μœΌλ©΄ Approve ν•©λ‹ˆλ‹€.
  4. Approve된 PR을 μ½”λ“œμž‘μ„±μžκ°€ Self Merge ν•©λ‹ˆλ‹€.

4. 브랜치 이름 μ»¨λ²€μ…˜

Feature/[κΈ°λŠ₯μš”μ•½]

- 맨 μ²«κΈ€μž F만 λŒ€λ¬Έμžλ‘œ, κΈ°λŠ₯μš”μ•½μ€ μ†Œλ¬Έμžλ‘œ μž‘μ„±ν•΄μ£Όμ„Έμš”
- κΈ°λŠ₯μš”μ•½μ€ μ˜μ–΄λ‘œ μž‘μ„±ν•΄μ£Όμ„Έμš”

ex) Feature/modal-publishing

5. 컀밋 λ©”μ„Έμ§€ μ»¨λ²€μ…˜

<νƒœκ·Έ>: <제λͺ©>

- : λ’€μ—λ§Œ 띄어쓰기가 μžˆμŠ΅λ‹ˆλ‹€
- 제λͺ©μ€ ν•œμ˜ 혼용이 κ°€λŠ₯ν•©λ‹ˆλ‹€ (가급적 μ˜μ–΄λ‘œ)
- νƒœκ·Έμ˜ μ²«κΈ€μžλŠ” λŒ€λ¬Έμžλ‘œ μž‘μ„±ν•΄μ£Όμ„Έμš”
- νƒœκ·ΈλŠ” μ•„λž˜μ— 적힌 κ²ƒλ“€λ§Œ μ‚¬μš©ν•΄μ£Όμ„Έμš”

Feat: μƒˆλ‘œμš΄ κΈ°λŠ₯ μΆ”κ°€, κΈ°λŠ₯ 둜직 λ³€κ²½
Fix: 버그 μˆ˜μ •
Refactor: μ½”λ“œ λ¦¬νŒ©ν† λ§ (κΈ°λŠ₯ λ³€ν™” X)
Style: μ½”λ“œ ν¬λ§·νŒ…, μ½”λ“œ 변경이 μ—†λŠ” 경우
Chore: λΉŒλ“œ 업무 μˆ˜μ •, νŒ¨ν‚€μ§€ λ§€λ‹ˆμ € μˆ˜μ •
Docs: λ¬Έμ„œ μˆ˜μ •, 주석

5. μ½”λ“œ μ»¨λ²€μ…˜

1. EsLint κ΄€λ ¨

EsLint Rule을 μž„μ˜λ‘œ ν•΄μ œν•˜μ§€ λ§μ•„μ£Όμ„Έμš”.

2. Type κ΄€λ ¨

  1. Props Type μ„ μ–Έ μ‹œ Type을 μ‚¬μš©ν•΄μ£Όμ„Έμš”. (Interface X)
  2. Props Type의 이름은 [μ»΄ν¬λ„ŒνŠΈμ΄λ¦„]+Props 의 ν˜•μ‹μœΌλ‘œ μ§€μ–΄μ£Όμ„Έμš”.
type HeaderProps = {
  onOpenDrawer: (e: React.MouseEvent) => void;
};

type PublicationBoxElementProps = {
  title: string;
  writer: string;
  img: string;
  pdf: string;
};
  1. Interface μ„ μ–Έ μ‹œ, 클래슀의 μΈν„°νŽ˜μ΄μŠ€λ‘œ μ‚¬μš©ν•  λͺ©μ μ΄ μ•„λ‹ˆλΌλ©΄ 접두사 Iλ₯Ό μ‚¬μš©ν•˜μ§€ λ§μ•„μ£Όμ„Έμš”.

3. Constant μ •μ˜ μ‹œ

객체둜 μ •μ˜ν•˜λ˜, as const ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ read-only 객체둜 λ§Œλ“€μ–΄μ£Όμ„Έμš”.

export const Paths = {
  new: '/new',
  newComplete: '/new/complete',
  main: '/main',
  reply: '/reply',
  replyComplete: '/reply/complete',
  view: '/view',
} as const;

4. styled-components κ΄€λ ¨ (1) - Type μ»¨λ²€μ…˜

styled-components λ₯Ό μœ„ν•œ Props Type μ„ μ–Έ μ‹œ 일반 μ»΄ν¬λ„ŒνŠΈμ˜ Props Type처럼 λ³„κ°œλ‘œ μ„ μ–Έν•˜μ§€ μ•Šκ³ , μ•„λž˜μ™€ 같이 μ„ μ–Έν•©λ‹ˆλ‹€. (μΆ”ν›„ μž¬μ‚¬μš© 용이)

// 잘λͺ»λœ μ˜ˆμ‹œ

// @types/styled.d.ts
type FAQBoxProps = {
  isOpen: boolean;
};

// components/FAQBox.tsx
export const FAQBox = styled.div<FAQBoxProps>`
  opacity: ${(props) => (props.isOpen ? 1 : 0)};
`;
// μ˜¬λ°”λ₯Έ μ˜ˆμ‹œ

// @types/styled.d.ts
type IsOpenType = {
  isOpen: boolean;
};

// components/FAQBox.tsx
export const FAQBox = styled.div<IsOpenType>`
  opacity: ${(props) => (props.isOpen ? 1 : 0)};
`;
// Type μ‘°ν•© μ˜ˆμ‹œ

// @types/styled.d.ts
type IsOpenType = {
  isOpen: boolean;
};

type IsFixedType = {
  isFixed: boolean;
};

// components/FAQBox.tsx
export const FAQBox = styled.div<IsOpenType & IsFixedType>`
  opacity: ${(props) => (props.isOpen ? 1 : 0)};
  opacity: ${(props) => props.isFixed && 1};
`;

5. styled-components κ΄€λ ¨ (2) - namespace S μ‚¬μš©

styled-componentsλŠ” μ‚¬μš©λ˜λŠ” μ»΄ν¬λ„ŒνŠΈ 파일 내뢀에 μž‘μ„±ν•˜λ˜, namespace S μ•ˆμ— μ •μ˜ν•˜μ—¬ μ£Όμ„Έμš”. 일반 μ»΄ν¬λ„ŒνŠΈμ™€ μ‰½κ²Œ κ΅¬λΆ„ν•˜κΈ° μœ„ν•¨μž…λ‹ˆλ‹€.

// μ»΄ν¬λ„ŒνŠΈ 파일
  return (
    <S.Container>
      <S.Wrapper isFocus={isFocus} isError={false}>
        <input
          placeholder={placeHolder}
          onFocus={onFocus}
          onBlur={onBlur}
          value={value}
          onChange={onChange}
        />
      </S.Wrapper>
      <IconButton svgIcon={svgCircleX} onClick={onClickRemove} />
    </S.Container>
  );
}

namespace S {
  export const Container = styled.div`
    display: flex;
    align-items: center;
    gap: 1.15rem;
    padding-right: 0.75rem;
    flex-grow: 1;
  `;

  export const Wrapper = styled.div`
    display: flex;
    align-items: center;
    gap: 1.15rem;
    padding-right: 0.75rem;
    flex-grow: 1;
  `;
}

이와 μœ μ‚¬ν•˜κ²Œ, μž¬μ‚¬μš©ν•  styled-componentsλŠ” λ‹€μŒκ³Ό 같이 μ •μ˜ν•©λ‹ˆλ‹€.

// styles/styled.ts
export namespace SC {
  export const HeaderContainer = styled.header`
    background: ${Colors.white};
    border-bottom: 0.1rem solid ${Colors.gray200};
    height: ${Styles.headerHeight};
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 2.4rem;
  `;

  export const HeaderLogo = styled.h1``;

  export const NewMainContainer = styled.div`
    background-color: ${Colors.white};
    border-radius: 0.8rem;
    border: 0.1rem solid ${Colors.gray200};
    padding: 4rem;
  `;
}

6. px - rem κ΄€λ ¨

1rem = 10px둜 μ„€μ •ν•΄λ‘” μƒνƒœμž…λ‹ˆλ‹€.
px이 μ•„λ‹Œ rem을 μ‚¬μš©ν•΄μ£Όμ„Έμš”.