HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤎
프론트엔드 데브코스 5기 교육생
/
조윤호팀
조윤호팀
/
📝
알고바로 프로젝트 컨벤션(FE)
📝

알고바로 프로젝트 컨벤션(FE)


📋 목차
🚩 기술 스택 🚩 코드 컨벤션📌 코딩스타일📌 네이밍 컨벤션📌 스타일 컴포넌트 컨벤션🚩 디렉터리 구조🚩 Git 컨벤션📌 Git Flow 브랜치 전략📌 커밋 컨벤션📌 ESLint 및 Prettier 설정 파일📌 PR 컨벤션📌 깃허브 이슈, 프로젝트 칸반보드└ 깃허브 이슈└ 프로젝트 칸반보드[부록] 팀 회의 내용

🚩 기술 스택

구분
기술
비고
번들러
Vite
CRA vs Vite - CRA는 무겁고 느린 단점이 있다. - 가볍고 추후 배포 연계를 위해 가벼운 Vite를 선택했다.
라이브러리
React
ㅤ
슈퍼셋
TypeScript
- 동적 타입핑으로 일어날 수 있는 이슈를 막을 수 있다. - 일관성 있는 코드를 작성할 수 있다. - 미리 타입을 지정함으로서 코드 자동완성을 통해 개발 경험을 향상시킬 수 있다. - 협업에 있어 팀원이 작성한 코드에 대한 이해도를 높여준다.
라우터
React-router
ㅤ
스타일링
styled-components, MUI
styled-components (결정) vs Emotion
코드 포맷팅
ESLint, prettier, husky
ㅤ
배포
Vercel
ㅤ
API
axios
axios vs fetch - axios interceptor 기능을 활용하면 에러 핸들링, 응답 처리를 한 번에 할 수 있다.
서버 상태 관리
React-query
ㅤ
전역 상태 관리
Zustand
- recoil에 비해 번들 사이즈가 작음, recoil은 업데이트 된 지 오래됨 - store와 action을 한 번에 관리할 수 있다.
협업 툴
Github, Slack, Gather, Discord, Notion, FigJam, Figma
원활한 문서화 및 회의를 위해 목적에 따라 다른 협업 툴을 사용했다.

🚩 코드 컨벤션

📌 코딩스타일

풀네임 사용 여부
축약형보다는 풀네임을 권장
길이 제한
4음절로 제한
컴포넌트 작성 순서
styled-components > hook(상태) > 상수 > 변수 > 함수 > jsx
JSDoc
공통 컴포넌트, 함수 등
함수 형태
컴포넌트는 함수 선언식 export default function Component(){} 그 외 함수는 함수 표현식 export const Fn = () ⇒ {}

📌 네이밍 컨벤션

분류
규칙
예시
상수
SNAKE_CASE
const MAX_USERS = 10;
변수
camelCase
let userName = 'JohnDoe'; let isActive = true; let hasLoggedIn = false;
함수
camelCase, 동사+명사
const getUserProfile = () ⇒ { ... }
이벤트 핸들러
camelCase 컴포넌트에 props 넘겨줄 때는 on 접두사 이벤트 함수는 handle 접두사
props -> onChangeHandler func -> handleChange
타입, 인터페이스
- type : 유니언 타입, 유틸리티 타입 - interface : 타입 외 나머지 - 접미사 Props
interface AvatarProps {…} type AvatarProps {…}
타입 별칭
- 접미사 Type
type ButtonType = …;
인터페이스
PascalCase
ㅤ
컴포넌트
PascalCase
Avatar
 

📌 스타일 컴포넌트 컨벤션

  1. tsx 컴포넌트 파일에서 기본값 설정, 스타일 분기 처리
  1. 스타일 컴포넌트에서는 props를 사용하기만 하는 방식으로 props 및 theme은 상단에서 선언한 것을 재사용하기 위해 css 선택자로 묶어주기
export default function Button({ type = 'button', disabled = false, width = '13.3rem', height = '4.3rem', shape, ...props }: ButtonProps) { const theme = useTheme(); return ( <BaseButton type={type} disabled={disabled} $width={width} $height={height} $shape={shape || theme.shape.round} {...props} > {isLoading && <CircularProgress size={20} />} {!isLoading && children} </BaseButton> ); }
import styled, { css } from 'styled-components'; export const BaseButton = styled.button<StyledButtonProps>` ${({ $width, $height, theme, }) => css` width: ${$width}; height: ${$height}; // theme 사용 예시 border-radius: ${$theme.shape.round}; color: ${theme.color.black_primary}; `} `;
 

🚩 디렉터리 구조

AlgoBaro ├─ 📂 public // 파비콘 등 자료나 이미지 │ └─ favicon.ico └─ 📦 src ├─ 📂 assets ├─ 📂 components ├─ index.ts └─ 📂Common // 공용 컴포넌트 폴더 └─ 📂Avatar ├─ index.ts // 폴더 내 .tsx 파일이 하나일 경우 생략 ├─ Avatar.tsx └─ Avatar.style.ts ├─ 📂 constants ├─ 📂 hooks ├─ 📂 pages ├─ 📂 routes ├─ 📂 services ├─ 📂 auth └─ apiconfig.ts ├─ 📂 store ├─ 📂 styles ├─ 📂 types ├─ 📂 utils ├─ App.tsx └─ main.tsx ├─ .gitignore ├─ index.html └─ README.md
// component를 관리하는 index.ts 는 배럴 export 구문을 사용 // src/components/index.ts export { default as Modal } from './Modal';
# src/components/Avatar if) Avatar 폴더 내부에 추가적인 .tsx 파일이 있다 ? => index.tsx 파일을 생성해준다 else if) ( 폴더 내부에 추가적인 .tsx 파일이 없다 ? || 폴더 내부에 추가적인 .ts 파일이 있다 ? ) => index.tsx 파일 생성 X

🚩 Git 컨벤션

📌 Git Flow 브랜치 전략

main
최종 배포용
dev
개발 단계
release
release-{버전명} • 백업 용도로 사용 시맨틱 버전으로 버전명 기술 ◦ major.minor.patch // 주.부.수
feature
이슈 생성 ⇒ feature/{이슈번호}-{핵심작업내용(파스칼케이스)} ex) feature/#1-MainPage, feature/#2-LoginError (fix, refactor 사용 여부는 프로젝트 중후반 추가 결정 ) 핵심작업내용은 선택 사항, 이슈 내 2개 이상의 브랜치가 존재할 경우는 필수적으로 추가 작성
hotfix
main 브랜치에서 정말 사소한 수정들 위주로 사용
 

📌 커밋 컨벤션

# <타입>: <제목> 형식으로 작성하며 제목은 최대 50글자 정도로만 입력 # 제목을 아랫줄에 작성, 제목 끝에 마침표 금지, 무엇을 했는지 명확하게 작성 ################ # [✨feat]: 새로운 기능 추가 # [🐛fix]: 버그 수정 # [📝docs]: 문서 수정 # [♻️refactor]: 코드 리팩토링 (기능에 영향을 주지 않을 때) # [💄style]: 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우 # [🎨design]: CSS 등 사용자 UI 디자인 변경 # [🔨chore]: 빌드 부분 혹은 패키지 매니저 수정사항 # [🔥remove]: 파일을 삭제하는 작업만 수행하는 경우 # [🚚rename]: 파일 혹은 폴더명 수정하거나 옮기는 경우 # [💬comment]: 필요한 주석 추가 및 변경 ################
 

📌 ESLint 및 Prettier 설정 파일

.eslintrc.json
{ "env": { "browser": true, "es6": true, "node": true }, "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module", "project": ["tsconfig.json"], "createDefaultProgram": true }, "plugins": [ "react", "react-hooks", "react-refresh", "prettier", "unused-imports", "simple-import-sort" ], "extends": ["plugin:prettier/recommended"], "settings": { "react": { "version": "detect" } }, "rules": { "react/jsx-key": "error", "no-unreachable": "warn", "react-refresh/only-export-components": [ "warn", { "allowConstantExport": true } ], "no-unused-vars": "warn", "no-console": "warn", "unused-imports/no-unused-imports": "warn", "unused-imports/no-unused-vars": [ "warn", { "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" } ], "simple-import-sort/imports": "warn", "simple-import-sort/exports": "warn" }, "globals": { "React": "writable" } }
.prettierrc
{ "printWidth": 80, "tabWidth": 2, "useTabs": false, "semi": true, "singleAttributePerLine": true, "singleQuote": true, "trailingComma": "es5", "endOfLine": "auto", "bracketSameLine": false, "jsxBracketSameLine": false, "bracketSpacing": true, "arrowParens": "avoid" }
 

📌 PR 컨벤션

  • assignee는 자기 자신, reviewer는 전체 팀원
  • label 구분
    • 예) Feat, Fix, Refactor, Docs 등
 

📌 깃허브 이슈, 프로젝트 칸반보드

└ 깃허브 이슈

이슈 생성 ~ PR 생성 ~ Merge 흐름
[사용방법]
  1. 이슈 생성 (템플릿은 PR 컨벤션과 동일)
  1. 우측 하단의 Development 항목의 create a branch 클릭
      • feature/#이슈번호-기능 규칙으로 브랜치 생성
  1. 해당 브랜치로 개발한 내용 push
    1. # 브랜치 전환 방법 git fetch origin // 원격 저장소와 연동 git checkout -t origin/feature/#이슈번호-기능 // 해당 원격 브랜치를 로컬에 만들고 해당 브랜치로 이동
  1. PR 생성 (템플릿 이용)
  1. 코드 리뷰 후 1명 이상 approve 시 Merge
      • 개발 중에는 dev 브랜치로 병합

└ 프로젝트 칸반보드

[사용방법]
  1. 레포의 [Project] 탭에서 칸반보드를 생성
  1. 이슈, PR 생성할 때마다 오른쪽의 Projects 항목에서 등록
  • 이슈 Closed시에 자동으로 칸반보드도 Done 상태로 변경
 

[부록] 팀 회의 내용

기술스택

ESLint & Prettier

(내일까지 각자 조사해보기)
윤호팀 Eslint & Prettier
  • ESLint plugin
    • eslint-plugin-import
    • unused-import
    • css 자동정렬
    • eslint 커스텀화

ESLint

박수현
  • simple-import-sort
    • 저장 시 그룹에 맞게 import문을 자동 정렬 해줌
    • 그룹: 외부 라이브러리/절대경로/상대경로 등..
  • unused-imports
    • 저장 시 사용하지 않는 import 코드 제거
배건호
 
 
{ // map과 같은 배열 내에서 key 값 사용하지 않을 시 에러 "react/jsx-key": "error", // 코드 블록의 return 문 이후로 작성되는 코드는 경고를 띄우게끔 "no-unreachable": "warn", }
신수영
  • 논의: 스니펫
  • 논의: 컴포넌트 방식
rules: { // React export 규칙 - airbnb "react-refresh/only-export-components": [ "warn", { allowConstantExport: true }, // 상수 컴포넌트 허용 ], "no-unused-vars": "warn", // 사용하지 않은 변수 경고, 프로덕션 코드 "no-console": "warn", // 디버깅용 콘솔 문 경고, 프로덕션 코드 },
조익준
eslint & prettier 조사

Prettier

박수현
// 취향에 따라서 선택해서 사용하면 좋을거 같아요! { "printWidth": 80, "tabWidth": 2, "semi": true, "singleAttributePerLine": true, "singleQuote": true, "jsxSingleQuote": true, "trailingComma": "all", "endOfLine": "lf", }
 
 
배건호
{ "tabWidth": 2, "bracketSameLine": true, // 오른쪽 꺽쇠괄호(>)를 다음 줄에 혼자 놓지 않고 마지막 줄 끝에 놓음 "singleQuote": true, "endOfLine": "lf", // 파일 맨 아래줄에 자동 개행을 해줍니다. "trailingComma": "none", // 객체나 코드 맨 마지막에 , 를 나오지 않게끔 수정해 줍니다. // 스타일코드 컨벤션 추가 예정입니다~ // 아래는 import 순서 지정해주는 예시 $ npm install -D @trivago/prettier-plugin-sort-imports "plugins": ["@trivago/prettier-plugin-sort-imports"], "importOrder": [ "@storybook*", "@emotion*", "^react*", "^@*", "^[../]", "^[./]" ], // 위 예시의 순서대로 정렬되게 됩니다 "importOrderSeparation": false, // import 구문 사이에 공백이 들어갈지 유무입니다. "importOrderSortSpecifiers": true // true로 해줘야 설정한대로 정렬되어요! }
notion image
notion image
신수영
{ "printWidth": 80, // 한 줄 최대 길이, 길이 초과 시 줄 바꿈 (기본값: 80) "tabWidth": 2, // 탭 간격 (기본값: 2) "semi": true, // 세미콜론 (기본값: true) "singleQuote": false, // quote 스타일 (기본값: false) "trailingComma": "es5", // 객체 등 마지막에 붙이는 , 여부 (기본값: es5) "endOfLine": "auto" // os마다 다른 마지막 줄 통일 (기본값: lf) "useTabs": false, // tab 사용 여부 (기본값: false) "bracketSpacing": true, // 객체 리터럴({}) 사이에 공백 설정 (기본값: true) "arrowParens": "avoid", // 화살표 함수의 인자에 괄호 여부 (기본값: always) }
  • preserve
    • const url = ("https://api.example.com/endpoint?param1=value1&param2=value2&" "param3=value3")
  • never
    • const url = "https://api.example.com/endpoint?param1=value1&param2=value2&param3=value3"
 
조익준
  1. prettier, eslint-config-prettier 패키지 설치
  1. .prettierrc 파일 생성
  1. 옵션 작성
{ // 쌍따옴표 대신 홑따옴표 사용 "singleQuote": true, // 모든 구문 끝에 세미콜론 출력 "semi": true, // 탭 대신 공백으로 들여쓰기 "useTabs": false, // 들여쓰기 공백 수 "tabWidth": 2, // 가능하면 후행 쉼표 사용 "trailingComma": "all", // 줄 바꿈할 길이 "printWidth": 80, // 객체 괄호에 공백 삽입 "bracketSpacing": true, // 항상 화살표 함수의 매개 변수를 괄호로 감쌈 "arrowParens": "always", // OS에 따른 코드라인 끝 처리 방식 사용 "endOfLine": "auto" }
  1. eslint와 충돌 방지 추가 .eslintrc.js 파일에서 수정
extends: [{기존 eslint 스타일}, 'prettier'] // 순서 잘 지키기, prettier가 가장 마지막이어야 함.

프리티어 옵션

https://prettier.io/docs/en/options.html
 

브랜치 전략

(각자 조사 및 정리)
윤호팀 FE 브랜치 전략
박수현
  • main (실제 배포용)
  • dev (코드 합체용)
  • 그 외 브랜치는 이슈별로 생성
  • 브랜치명 규칙
    • 커밋 컨벤션/#이슈번호
    • 예: feat/#1
    • 멘토님께서 슬래시(/)는 폴더 구조에서 많이 사용되기도 하고 에러가 발생할 수도 있어서 대시 또는 언더바를 권장한다고 말씀하셨다고 합니다..!
    • 에러 발생 블로그
배건호
  • main (실 배포용)
  • hotfixes
  • release branches (배포 전 최종 테스트)
  • develop
  • feature/ 주제 - 항목
    • ex) 해당 스프린트 기간동안 공통 컴포넌트의 Spinner 컴포넌트를 만든다고 가정할 때 ⇒ feature/Common-Spinner
 
 
신수영
  • git flow
    • main
    • feature
    • develop
    • release
    • hotfix
  • feature
  • develop
  • release
  • hotfix
  • main
    • github flow : main, feature
    • 이전 팀: main, dev, feature
      • 시맨틱 버전(Semantic Versioning)
      • major.minor.patch // 주.부.수

        Major

        • 대대적인 변화
        • 기존 버전과 호환되지 않는 API 변화

        Minor

        • 기존 버전과 호환되면서 새로운 기능 추가
        • 기존 기능이 변경되거나 API 변경

        Patch

        • 기존 버전과 호환되면서 버그 수정
        • API 변화 없음
        • 기존 클라이언트가 알아차리지 못할 정도의 작은 변화
         
     
    조익준
    • 2차 팀에서는 git-flow 전략에서 약간 변형해서 사용 release 브랜치 미사용
       
       

      상태 관리 라이브러리

      (각자 조사 및 정리)
      박수현
      • Recoil
        • 장점
          • 러닝커브 낮음
          • 자식 컴포넌트를 모두 리렌더링하는 Context API에 비해
          • 구독된 컴포넌트만 렌더링하기 때문에 성능상 이점
        • 단점: 업데이트 된지 오래 됨 (안정성 이슈)
      • Zustand
        • 장점
          • 러닝커브 낮음
          • recoil과 마찬가지로 성능상 이점
          • recoil의 store와 action이 분리된 단점을 해결할 수 있음
        • 단: 공부할 수 있는 최신 한글 자료가 많이 없다고 함
      배건호
      zustand, react-qeury
       
      상태관리에 대한 공부도 좋지만, 추가적인 기능을 조금 더 만들어보는 것도 좋다고 생각합니다.
       
      때문에 프로젝트에 대한 목적을 정하고 난 후 상태관리를 선택하는 것은 어떠실까요 ?
       
      • Zustand vs Jotai 고민 중이심!
      • Jotai
        • 러닝커브 낮음
        • bottom-top은 Jotai (Atomic)
          • 장: 자유도 굳
          • 단: 어디서든 변경될 수 있음
        • top-bottom은 zustand (Flux)
       
      신수영
      • 공통점: TS 지원, 최적화
      ㅤ
      Redux-Toolkit(RTK)
      Recoil
      Zustand
      개발
      Dan Abramov
      페이스북
      일본 개발자 jotai
      사용 기업 수 (codenary)
      105
      27
      5
      특징
      - 점유율이 높다 - 액션으로 상태 변경→상태 쉽게 예측 가능, 유지보수 하기 좋다 - Redux Devtools 제공→디버깅이 편리하다
      - hook 기반 - Selector로 비동기 처리가 가능하다
      - redux 기반 - hook 기반 - Redux Devtools 제공 → 디버깅이 편리하다 - Provider가 필요 없다 → 불필요한 리렌더링 최소화
      단점
      러닝 커브가 높다
      - Devtool이 없어 디버깅이 불편하다 - 어느 컴포넌트에서라도 상태를 변경할 수 있기 때문에 추적이 어렵다
      - 최신 한글 자료가 많이 없다.
      추천
      - 비동기 상태 관리 tanstackQuery - 새로고침 시 store state 증발→ redux-persist
      - 클라이언트 데이터 상태 관리 추천 - 새로고침 시 store state 증발→ recoil-persist
      ㅤ
      조익준
      https://velog.io/@iberis/상태관리-라이브러리-비교-Redux-vs-Recoil-vs-Zustand-vs-Jotai https://velog.io/@jaewoneee/번역-Zustand-vs-Redux
      notion image
      짧은 개발 기간(1달 반)을 생각했을 때 zustand나 recoil이 적합한 것 같고 업데이트를 생각해보면 zustand가 가장 최적이라고 생각이 듭니다…! redux도 꼭 알아야 하는거 같아요! 길게 잡고 공부를 해야 할 거 같습니다.
       
      emotion vs styled components
       

      Styled-Components (최종 결정)

      신수영
      styled-components vs Emotion
      • 기능: 거의 유사
      • 추세: styled-components가 우세
        • 해외 사용률: stateofcss에 의하면 styled-components 50% emotion 21%
        • 국내 사용 기업 수: codenary에 의하면 styled-components 156개 emotion 33개
      • 성능: styled-components가 emotion에 비해 가볍고 빠르다고 하지만 거의 차이는 없다.
      • 결론: 뭘 써도 상관없을 것 같다. 취업 용도 styled-components가 유리해 보인다.
      조익준
      https://80000coding.oopy.io/7ad296c7-8832-4951-9cf7-074a196d42ea 큰 차이는 없으나 label을 통한 emotion의 디버깅 지원 기능이 나름 괜찮은거 같다!
      박수현
       
      배건호

      CSS 라이브러리

      React Bootstrap, MUI, Ant Design 등
      신수영
      Material UI(MUI)
      - 컴포넌트 단위 개발에 유용하다. - 가장 인기와 성숙도가 높다. - 예제가 많다. - 완전한 커스텀 스타일링이 어렵다.
      Ant Design
      - 중국 프로덕트라서 동양적인 사이트에 어울린다. - 어드민 페이지 개발에 유용하다.
      React Bootstrap
      - 컴포넌트 단위 개발에 유용하다. - 디자인 변경 시 인라인 속성으로 css를 넣는다. 가상선택자는 사용할 수 없다. - Slider가 없다.
      참고: MUI, Antd, tailwind
      조익준
      notion image
      notion image
      • 테일윈드를 사용하지 않기로 한 이상 MUI, Ant design, react-bootstrap은 다운로드 수로는 고만고만합니다.
      • 대신 가장 업데이트가 활발히 되고 있는건 Ant design입니다.
      • 가장 커뮤니티가 활발하고 안정성 있는 건 MUI입니다.
      • MUI 나 Ant design 중에 선택하면 좋을 거 같습니다.
      ㅤ
      MUI
      Ant Design
      장점
      - Google의 Material Design을 기반으로 풍부한 디자인 보유(안정성 갑) - 컴포넌트의 일관성과 다양성, 문서화가 잘 되어 있음. - 크고 활발한 커뮤니티에 따른 다양한 지원과 확장성
      - 최신 트렌드가 잘 적용되어 있음. - 컴포넌트가 다양하고 광범위한 기능이 있음 - 중국꺼라 업데이트가 활발함
      단점
      - 지나치게 디자인에 대한 일관성이나 제한이 있을 수 있음. - 디자인 표준화에 대한 호불호가 갈림
      - 디자인이 중국스러울 수 있음 - 문서화가 좀 덜 되어 있음 - 커스터마이징이 힘들 수 있음

      npm (최종 결정)

      • 노드 버전 맞춰야 함
       
      코드 컨벤션
      조익준
      • eslint와 prettier로 대략적인 코드 컨벤션은 완성이 된 거 같아서 함수명 및 변수명과 같은 네이밍 규칙과 같이 정하지 않은 부분들을 체크해보았습니다.
      • 중첩 레벨 if문과 같은 조건문을 사용할 경우 몇 단계 중첩까지 허용할 것인지 결정 → return, continue를 이용해서 중첩 피하기 권장 코드 리뷰에서 즉각적으로 피드백 가능하기에 굳이 빡빡하게 정할 필요가 없을 수도 있음
      • 함수의 위치 컴포넌트 파일에서 함수의 위치를 어디에 둘지?
        • 수영, 수현: styled-components, hook(상태), 상수, 변수, 함수, jsx
          // 화살표 함수 사용: 선언문이 항상 위에 있어야 함 // --- 헬퍼 함수 --- let 헬퍼함수에만 = 0; const setHandler = (elem) => { ... } const createElement = () => { ... } // 헬퍼 함수를 사용하는 코드 let elem = createElement(); setHandler(elem); walkAround();
           
      • JSDoc 사용 복잡한 함수나 컴포넌트의 사용법 및 매개변수나 return 값들에 대한 타입들을 명시하기 좋아서 사용해보면 좋을 것 같습니다. 레퍼런스, 타입스크립트를 위한 JSDOC 레퍼런스, 공식문서
        • /** * @brief 전체 사용자 목록을 불러옵니다. * @details 디폴트 값은 offset = 0, limit = 10 입니다. * @params {number} offset - 현재 위치 * @params {number} limit - 불러올 최대 개수 * @return Promise<UserType[] | never> * 반드시 {} 중괄호 내부에 offset, limit 설정해야 합니다. */ export const getUsers = async ({ offset = 0, limit = 10, }: GetUserListRequestType): Promise<UserType[] | never> => { ... }; @brief : 간략하게 함수를 소개합니다. @details : 함수에 대해 상세하게 설명 합니다. 로직이 복잡한 경우 함수의 로직을 간단히 설명합니다. 해당 함수를 사용하며 주의 해야할 사항이 있다면 적어주는 것이 좋습니다. 매개변수와 리턴값에 대한 자세한 설명을 해도 좋습니다.
       
      • 네이밍 컨벤션
        • 변수명, 함수명 : carmelCase 최대 길이 및 함수명은 동사 + 명사 형태가 보편적 4음절 이상 ex) addButtonChangeHandler 동사에 대한 팀만의 규칙도 있으면 좋음. (ex. get, fetch 등)
        • 상수명: SNAKE_CASE, 구분은 언더스코어(_ ) 사용, I_AM_SHANGSOO
        • 컴포넌트명: PascalCase가 일반적
        • 이벤트 함수 네이밍
          • prop -> onChangeHandler // 컴포넌트 넘겨줄 때 func -> handleChange // 이벤트 함수 연결
            const handleChange = () => { } return( <Avatar onChange={handleChange} /> <Button onChange={handleButtonChange} /> <Input onChange={handle기능} /> ); return( <Child onChangeHandler={handleChange} /> )
            interface props
            interface AvatarProps { } export default Avatar(props: AvatarProps){ }
             
            Styled components 규칙
          • Styled prefix
            • import Styled from './Avatar.styled'; const Avatar = styled.div`~` export default Avatar(props: AvatarProps){ // 컴포넌트 return( <Styled.Avatar> <Styled.Title>...</Styled.Title> </Styled.Avatar> ) }
               
          • ✅ 개별 export
            • import { AvatarWrap, Title } from './Avatar.styled'; const AvatarWrap = styled.div`~` export default Avatar(props: AvatarProps){ // 컴포넌트 return( <AvatarWrap> <Title>...</Title> </AvatarWrap> ) }
             
           
      신수영
      • 축약형, 풀네임 여부 ex) btn, button
        • *길지만 모두가 아는 param의 경우 허용하는 방향 - 축약형은 레퍼런스 표 정리 필요하다는 의견
      • TypeScript 타입, 인터페이스 용도 구분
        • 타입 : 유니언 타입, 유틸리티 타입
        • 인터페이스 : 나머지
        • type FruitsType = 'apple' | 'banana'; type FruitsType = string | number; // Omit과 같은 유틸리티 타입은 type을 사용해야 함 type FruitsType = Omit<BasketProps, 'count'>; interface BasketProps { fruits: FruitsType; count: number } const Basket = (props: BasketProps) => {...}
      • 주석 삭제 방법 여부 → 멘토님 질문! ex) - feature 주석 삭제 후 dev merge할지 - PR 전 주석 삭제할지 - 나중에 dev에서 배포 전 일괄 삭제할지
      이전 파일 구조
      /public -> favicon, logo 등 이미지 /src │ /api | | /queries | /assets | /component | | /Login -> 고유한 컴포넌트 (단일 페이지 내에서 사용) | | /common -> 복수 페이지에서 사용, 다른 컴포넌트에서 사용되는 컴포넌트 | | | /Layout | | | /Navigator | | | /Post | | | | /modules | | | | | /PostPhotoBox | | | | | /index.ts | | | | /Post | | | | /index.ts | | | /Card | | | | /Card.styles.ts | | | | /Card.tsx | | | | /index.ts | | | /Header | | | /Button | /hooks | /constants | | /index.ts -> 길어지면 분기 | /pages | | /profilePage/Post | /types | | / index.ts | /utils -> 유틸리티 함수 | /styles | | /Theme.ts | | /GlobalStyle.ts
      박수현
      • 컴포넌트만 함수 선언식으로!
        • 컴포넌트: 함수 선언식 export default function Main(){}
        • 그 외 함수: 함수 표현식 export const Fn = () ⇒ {}
        • *스니펫 찾아보기
      • src 경로 alias 설정 (tsconfig.json, vite 설정 필요)
        • @/components ✅
      • 상수 관리
        • constants 폴더에 ts 파일 선언 후 사용
        • 폴더구조
          • src/constants/api.ts
            • API_ENDPOINT BASE_URL
      • 컴포넌트 및 페이지 작업 방식 (디렉토리)
        • 컴포넌트 파일: 디렉토리이름.tsx
        • styled 파일: 디렉토리이름.styled.ts
          • index.tsx, styled.ts로 작업하면 디버깅 어려운 문제 😭
          📦 src └── 📂 components (컴포넌트) └── 📂 Avatar . ├── Avatar.tsx (<- index.tsx: 컴포넌트 파일)    └── Avatar.styled.ts (<- styled.ts: styled 파일)
      배건호
      분류
      규칙
      예시
      상수
      UPPER_SNAKE_CASE
      const MAX_USERS = 10;
      변수
      camelCase boolean은 접두사 사용
      let userName = 'JohnDoe'; let isActive = true; let hasLoggedIn = false;
      함수
      camelCase, 동사+명사
      const getUserProfile = () ⇒ { ... }
      이벤트 핸들러
      camelCase handle+명사+동사 props는 on 사용
      낙타의 경우 const handleButtonClick = () ⇒ { ... } <button onClick={handleButtonClick}>Click me</button>
      컴포넌트
      PascalCase
      const UserList = () ⇒ { ... }
      type 별칭
      Type 접미사
      type UserResponseType = ... type ButtonClickType = ...
      interface
      PascalCase
      const IButton {}
      styled-component
      ㅤ
      ㅤ
      함수 인자 구조분해
      규칙 없음 (모든 컨벤션 무시)
      const createUser = ({ userName, userEmail }) ⇒ { ... }
      디렉터리 구조
      • 조익준
        • Component 별 폴더를 생성할지? ComponentName - index.tsx, style.ts, type.ts 와 같은 구조?
        • 디렉터리 구조 레퍼런스
          • https://bttrthn-ystrdy.tistory.com/91?category=641971
      • 박수현
        • Component 폴더 내부에서 관심사별로 폴더 생성하는 것 좋습니다!
        • 컴포넌트에서 사용하게 되는 type은 주로 props일 것 같아서 type.ts 폴더 없이 index.tsx, style.ts 두 가지 파일만 가져가도 괜찮을 것 같아요!
        • 그리고 익준님이 적어주신 폴더구조로 가는 것 동의합니닷
      • 배건호
        • type.ts의 경우 interface 갯수가 많아지면 별도의 파일에 분리하는 것이 좋아보입니다만, 크게 많아질 것 같진 않아 컴포넌트명.tsx 와 style.ts로 가면 좋을 것 같습니다.
      • 신수영
        • common 컴포넌트는 components/common 폴더
        • 익준님 폴더구조 의견 동의합니다
        • 파일/폴더 이름 Case
          • 컴포넌트는 컴포넌트명과 동일하게 PascalCase.tsx 그 외 소문자.ts
      PR 컨벤션
      조익준
      • assignee는 자기 자신, reviewer는 전체 팀원
      • 제목 : 대표적인 작업으로 축약하여 한 줄 요약, 이슈번호까지 같이? ex. #1 초기 환경 설정, #17 메인 페이지 구현
      • 설명: 구체적인 설명을 기술
        • 주요 작업사항 및 변경사항 : 관련 커밋 링크 첨부해주면 좋을듯
      • 레퍼런스 출처
        • <!-- 제목은 `[(키워드)] (작업한 내용) - (PR 순서)` 로 작성해 주세요 키워드 예시: feat/qa/sentry 등 --> ## 설명 ### 작업 티켓 or 동기 <!-- (Optional) 작성한 작업에 대한 티켓 번호나, 티켓이 없는 경우라면 작업을 왜 하게 되었는지 서술합니다. --> ### 스크린샷 <!-- (Optional) UI가 변경되었다면 사진이나 Gif를 추가해 주세요. --> ### 작업 내용 <!-- PR 본문을 입력하세요. --> ### 주안점 <!-- (Optional) 리뷰 시에 유심히 봐주었으면 하는 부분을 설명합니다. --> ## 연관 PR <!-- (Optional) 이 PR과 연관되어있는 다른 PR을 기입합니다. 예) - meshkorea/prime-api-client#15 : 연관된 API 변경점 --> ## 연관 티켓 <!-- (Optional) 이 PR과 연관되어있는 에픽 링크, 연관되어있는 QA 이슈 등을 기입합니다. 예) - 에픽 티켓: PP-9999 --> ## 체크리스트 - [ ] 무엇을 변경했는지 충분히 설명하고 있나요? - [ ] 새로운 기술을 사용했다면, 그 기술을 설명하고 있나요? - [ ] 이해하기 어려운 비즈니스 로직에 관해서 부연 설명을 하고 있나요? - [ ] 팀원 두명을 Assign하고, Review Request에는 web-front 팀을 추가했나요? - [ ] 작업을 설명하는 Jira 티켓을 추가했나요? - [ ] 작업 범위에 대해서 테스트를 작성하셨나요? - [ ] 인프라 작업, 릴리즈 PR이라면, Review Skip 레이블을 추가했나요?
      배건호
      • assignee는 자기 자신, reviewer는 전체 팀원, label도 같이
      • PR 네이밍 : 맨 앞에 feat, fix, chore 등을 붙이고 #17 한줄요약?
      ## 개요 <!-- 작업 티켓 or 동기처럼 PR을 작성하게 된 계기에 대하여 기술할 수 있는 부분입니다. --> ## PR 유형 <!-- 팀원이 어떤 작업을 하였는지 쉽게 알아볼 수 있게 도와주는 부분입니다. --> [] 새로운 기능 추가 [] CSS 등 사용자 UI 디자인 변경 [] 코드 리팩토링 [] 파일 혹은 폴더명 수정/삭제 [] 기타 ## 주안점 <!-- 리뷰 시에 유심히 봐주었으면 하는 부분을 설명합니다. --> ## etc <!-- 작성한 내용 외 정보들을 기입할 수 있습니다. -->
      박수현
      1. PR 템플릿 내용
          • 기능 설명
            • UI 구현 등 필요한 경우에 이미지 첨부
          • 변경 사항
            • 체크리스트
      1. PR 템플릿 규칙
          • assignee는 본인, reviewer 팀원들 모두로 설정하기
          • Label 만들어서 설정 (FEAT, FIX, DOCS 등)
          • n명 이상 approve하면 머지 가능 (과반수인 2명으로 해볼까요?!)
           
      신수영
      PR규칙
      • assignee, reviewer 설정
      • Label : Feat, Fix, Refactor 등
      • 2명 이상 approve하면 merge
        • merge는 2명 째에서 approve 하는 사람이 merge할지(저는 여기), merge 담당자를 따로 정하는 게 나을지
      PR 템플릿
      • PR 작성 시간을 고려하여 간략하게 설명, 작업내용, PR포인트 외 선택사항으로 두는 방안
      ## 설명 <!-- PR에 대한 설명입니다. --> 이 부분은 PR에 대한 설명입니다. ### 작업 내용 - 작업 내용입니다. - 작업 내용입니다. - 작업 내용입니다. ### 사용방법(선택) <!-- 공용 컴포넌트 작업 시 사용 방법을 알려줄 수 있습니다. --> ### 스크린샷(선택) <!-- 이해를 돕기 위한 스크린샷을 첨부할 수 있습니다. --> ## PR 포인트 <!-- PR 리뷰 시 공유 사항 또는 유심히 보면 좋을 부분을 설명합니다. -->
       
      깃허브 이슈, 프로젝트 칸반보드 사용
      박수현

      Github 이슈

      • 이슈도 PR 컨벤션이랑 동일한 내용으로 가져가면 작성할 때 편할 것 같아요!
      • 이슈 생성 ~ PR 생성 ~ Merge 흐름
          1. 이슈 생성 (템플릿 이용)
          1. 우측 하단의 Development 항목의 create a branch 클릭
              • feature/#이슈번호-기능 규칙으로 브랜치 생성
          1. 해당 브랜치로 개발한 내용 push
            1. # 브랜치 전환 방법 git fetch origin // 원격 저장소와 연동 git checkout -t origin/feature/#이슈번호-기능 // 해당 원격 브랜치를 로컬에 만들고 해당 브랜치로 이동
          1. PR 생성 (템플릿 이용)
          1. 코드 리뷰 후 n명 이상 approve 시 Merge
              • 개발 중에는 dev 브랜치로 병합

      Github 칸반보드

      • 레포의 Project 탭에서 칸반보드를 생성하면 됩니다!
      • 이슈, PR 생성할 때마다 오른쪽의 Projects 항목에서 등록을 해주어야 하는 것으로 알고 있어요
        • 생성할 때마다 자동으로 등록하게 하는 방법이 있을 것 같은데 저번에는 못찾고 그냥 진행했어유 ㅠ
      • 한 번만 등록해주면 Closed시에 자동으로 칸반보드도 Done 상태로 변경됩니다