$ git clone https://github.com/PI304/BK-Nutrition.git
$ cd BK-Nutrition
$ npm install$ npm dev
- 모든 type 선언은 이곳에서 해주세요.
- 파일 이름은 *.d.ts 형식을 지켜주세요.
- import가 필요한 타입 선언 시에는 @types/index.d.ts 파일에 선언해주세요.
PLEASE DO NOT - 다른 디렉토리의 파일에서 타입 선언
- components/layouts - 레이아웃 컴포넌트
- components/pages - 각 page의 최상위 컴포넌트 및 해당 page에서 사용되는 하위 컴포넌트
- components/seo - CustomHead 등 SEO에 사용되는 컴포넌트
- components/shared - 기타 공용 컴포넌트
- components/... - 추후 추가될 수 있습니다.
- 중요한 상수는 이곳에서 관리해주세요. (예: paths, seo...)
- 중요함의 기준 (1개 이상 충족 시 중요하다고 판단)
- 2번 이상 사용되는 경우 (재사용)
- 추후 논의에 의해 변경될 수 있는 경우 (추적용이)
- 기타 사유로 중요하다고 판단하는 경우
custom hook은 이곳에 작성해주세요.
라우터 설정을 위한 Next.js 예약 디렉토리입니다.
이미지 등 asset은 public/assets 에 저장해주세요.
참고 - SVG는 파일로 저장하지 않고, styles/svgs.tsx에 상수로 정의하여 관리합니다.
- styles/colors.ts - 디자인 컬러
- styles/devices.ts - 반응형 스타일을 위한 디바이스 구분 기준 등
- styles/fonts.ts - 디자인 타이포그래피
- styles/global.ts - 전역 스타일
- styles/reset.ts - 리셋 스타일
- styles/styled.ts - 중요한 Styled-components (1번 이상 재사용 OR 추적용이)
- styles/svgs.tsx - SVG 정의
각 디렉토리에는 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 <></>;
};PR을 통해 Feature 브랜치들을 Develop에 머지하고,
최종 배포할 시기가 되면 Admin 관리자가 Develop 브랜치를 Production 브랜치에 머지하여 배포하는 단순한 구조를 따릅니다.
- 로컬에 Clone한 레포에서 Feature 브랜치를 생성하여 작업합니다.
- 개발이 끝났다면 다시 한번 원격 레포의 최신 커밋을 받아와줍니다.
// 체크아웃 하기 전, Feature 브랜치에서의 작업 내용을 커밋해야 합니다.
$ git checkout develop
$ git pull origin develop- 추가된 최신 커밋이 있다면 내가 작업한 Feature 브랜치를, 새로운 커밋이 추가된 Develop 브랜치의 마지막 커밋으로 Rebase 합니다. (말그대로 base를 바꾼다는 뜻입니다)
$ git checkout Feature/[브랜치명]
$ git rebase develop- 충돌이 발생했다면, 에디터에서 충돌을 해결한 뒤 아래 명령어를 입력합니다.
$ git add .
$ git rebase --continue- 이상이 없다면 Feature 브랜치를 push 합니다.
$ git push origin Feature/[브랜치명]- Github에서 PR을 생성합니다. PR 시 나타나는 템플릿을 채워주세요.
## Feature Description
- 이런 이런 기능입니다
## To Reviewers
- 이런 이런 점을 유의해주세요-
Review 과정을 거칩니다.
-
Self Merge 해주세요.
-
Squash Merge되며, Merge된 Feature Branch는 자동 삭제됩니다.
-
로컬에서 Develop 브랜치로 체크아웃한 뒤 Pull하고, 새로운 Feature 브랜치로 분기하여 다음 작업을 진행해주세요.
Feature/[기능요약]
- 맨 첫글자 F만 대문자로, 기능요약은 소문자로 작성해주세요
- 기능요약은 영어로 작성해주세요
ex) Feature/modal-publishing
<태그>: <제목>
- : 뒤에만 띄어쓰기가 있습니다
- 제목은 한영 혼용이 가능합니다 (가급적 영어로)
- 태그의 첫글자는 대문자로 작성해주세요
- 태그는 아래에 적힌 것들만 사용해주세요
Feat: 새로운 기능 추가, 기능 로직 변경
Fix: 버그 수정
Refactor: 코드 리팩토링 (기능 변화 X)
Style: 코드 포맷팅, 코드 변경이 없는 경우
Chore: 빌드 업무 수정, 패키지 매니저 수정
Docs: 문서 수정, 주석
EsLint Rule을 임의로 해제하지 말아주세요.
- Props Type 선언 시 Type을 사용해주세요. (Interface X)
- Props Type의 이름은 [컴포넌트이름]+Props 의 형식으로 지어주세요.
type HeaderProps = {
onOpenDrawer: (e: React.MouseEvent) => void;
};
type PublicationBoxElementProps = {
title: string;
writer: string;
img: string;
pdf: string;
};- Interface 선언 시, 클래스의 인터페이스로 사용할 목적이 아니라면 접두사 I를 사용하지 말아주세요.
객체로 정의하되, as const 키워드를 사용하여 read-only 객체로 만들어주세요.
export const Paths = {
new: '/new',
newComplete: '/new/complete',
main: '/main',
reply: '/reply',
replyComplete: '/reply/complete',
view: '/view',
} as const;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};
`;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;
`;
}1rem = 10px로 설정해둔 상태입니다.
px이 아닌 rem을 사용해주세요.