의논할 내용
- tailwind를 깔끔하게 써보기.
- tanstack-query에서 query-key-factory로 querykey랑 queryFn 잘 묶어서 옵션만 공유하는 방식으로 깔끔하게 적용해보기.
기술 스택
커스텀 prettier 설정
{ "printWidth": 80, "tabWidth": 2, "semi": true, "singleQuote": true, "jsxSingleQuote": false, "bracketSpacing": true, "bracketSameLine": false, "arrowParens": "always", "singleAttributePerLine": true, "trailingComma": "none", "quoteProps": "as-needed", "endOfLine": "lf" }
이상훈
{ "printWidth": 120, "tabWidth": 2, "useTabs": false, "semi": true, "singleQuote": true, "jsxSingleQuote": false, "quoteProps": "as-needed", "trailingComma": "none", "bracketSpacing": true, "arrowParens": "always", "proseWrap": "preserve", "endOfLine": "auto", "bracketSameLine": false // 적용은 안해봤지만, 세진님 규칙을 보고 저도 평소에 import하는 순서를 적어볼게요! "importOrder": [ "^react(.)", "^react-router-dom(.)" "^react-error-boundary(.)" "^react-hook-form(.)" "<THIRD_PARTY_MODULES>", "^@apis/(.)$", "^@hooks/(.)$", "^@store/(.)$", "^@utils/(.)$", "^@components/(.)$", "^@routes/(.)$", "^@type/(.)$", "^@constants/(.)$", "^@pages/(.)$", "^@styles/(.)$", "^[./]" ], }
차세진
{ "tabWidth": 2, "printWidth": 80, "singleQuote": true, "trailingComma": "all", "semi": true, "bracketSpacing": true, "arrowParens": "always", "singleAttributePerLine": true, "endOfLine": "auto", "bracketSameLine": true, // 이 아래는 import 관련 내용입니다! "plugins": ["@trivago/prettier-plugin-sort-imports"], "importOrder": [ "^react(.)", "<THIRD_PARTY_MODULES>", "^@pages/(.)$", "^@components/(.)$", "^@apis/(.)$", "^@hooks/(.)$", "^@store/(.)$", "^@storage/(.)$", "^@utils/(.)$", "^@routes/(.)$", "^@styles/(.)$", "^@type/(.)$", "^@constants/(.)$", "^[./]" ], "importOrderSortSpecifiers": true }
박나연
{ "semi": true, "singleQuote": true, "endOfLine": "lf", "printWidth": 80, "tabWidth": 2, "singleAttributePerLine": true, "bracketSameLine": true, "trailingComma": "none", "arrowParens": "always", "bracketSpacing": true, "jsxSingleQuote": true, "importOrder": [ "^@api/(.*)$", "^@components/(.*)$", "^@constants/(.*)$", "^@hooks/(.*)$", "^@lib/(.*)$", "^@pages/(.*)$", "^@store/(.*)$", "^@styles/(.*)$", "^@types/(.*)$", "^@utils/(.*)$", "^@views/(.*)$", "^[./]" ], "importOrderSeparation": "true", "importOrderSortSpecifiers": "true" }
노성래
{ 딱히 없어용 }
코드 컨벤션
1-1 네이밍
변수명, 함수명
변수명, 함수명은
camelCase
로 한다.// bad const this_is_my_object = {} const this_is_my_function = () => {} // good const thisIsMyObject = {} const thisIsMyFunction = () => { // ... }
상수
상수명은
UPPER_CASE
로 한다.// bad const myConstants = "상수" // good const MY_CONSTANTS = "상수"
컴포넌트, 객체, 클래스
컴포넌트, 객체, 클래스는
PascalCase
로 한다.// bad const myReactComponent = () => { // ... } class person() { // ... } // good const MyReactComponent = () => { // ... } class Person() { // ... }
축약
축약하여 네이밍을 하지 않는다.
// bad const myBtn = document.querySelector('.my-button') const myFn = () => { // ... } // good const myButton = document.querySelector('.my-button') const myFunction = () => { // ... }
이벤트 핸들러
컴포넌트 내부의 이벤트 핸들러를 작성할때는 handle로 시작하고
function App(){ const handleClick = ()=>{} <button onClick={handleClick}></button>; }
상위 컴포넌트에서 받는 이벤트 핸들러는 on으로 시작
function App(){ const doAnything = () =>{} <Button onClick={doAnyThing}/>; } function Button({onClick}){ const handleClick = () =>{ onClick && onClick() } <button onClick={handleClick}></button>; }
path alias
path alias는 /src 만
@
로 하타1-4. 타입
interface
interface
는 다음의 상황에서 사용된다.- 확장 가능성이 높은 타입
- api의
input
,output
값처럼 외부로 연결 또는 확장되는 경우
type vs interface
타입의 보강, 확장이 필요한 경우는 제외하고는
type
를 사용한다.확장자
jsx
문법을 다루는 경우 tsx
, 그렇지 않는 경우 ts
로 작성한다.컴포넌트의 선언
컴포넌트는
화살표 함수
로 선언한다.// allowed but does not use function MyComponent() { // ... } // good const MyComponent = () => { // ... }
컴포넌트의 props
- props의 개수 상관없이 하나라도 있으면 타입을 만들어 명시한다.
- 컴포넌트 props의 타입명은
Props
로 한다.
- props는
구조분해할당
으로 가져온다.
interface MyComponentProps { // ... } const MyComponent = ({ a, b }: MyComponentProps ) => { // ... }
컴포넌트의 export default
- 컴포넌트(혹은 custom hook)를 내보낼 때에
export default
를 사용한다.
export
는 사용하지 않는다. 사용이 된다면 파일 분리를 고려한다.
export default MyComponent
컴포넌트 파일
- 하나의 컴포넌트 파일에는 로직이 포함된 컴포넌트는 하나만 들어갈 수 있다.
react event handler
reactEventHandler를 사용한다.
someFunction: React.MouseEventHandler<HTMLButtonElement>;
API
api 함수를 만들때
api method
를 어두에 작성한다. api method
가 아닌 단어는 어두에 작성하지 않는다.// bad const userGet = () => { // ... } const searchUser = () => { // ... } // good const getUser = () => { // ... }
단, 다양한
api method
를 추상화 해야 하는 경우에는 fetch
를 어두에 작성한다. api method
에 대한 구분은 인자로 한다.// bad const getPostUser = () => { // ... } // good const fetchUser = () => { // ... }
- custom hook의 접두사는
use
로 시작한다.
// bad const getPostUser = () => { // ... } // good const useUserQuery = () => { // ... }
상수 범위
다음과 같은 종류 변수는
상수
로 한다.- api url
- route path name
- 매직 넘버
- 서비스 메세지(errorMessage, successMessage)
- 스타일 (디자인 확정 후 논의 예정)
- UI Text (디자인 확정 후 논의 예정)
index 파일의 용도
- components랑 pages에서는 index 파일 자체에 컴포넌트 정의.

PostViewer/index.tsx
⇒ PostViewer 컴포넌트
PostViewer/components/index.ts
⇒ 종속 컴포넌트 export 용도
- 그 외의 곳에서는 export 하는 용도
export { useArchives } from '@hooks/useArchives'; export { useCurrentPage } from '@hooks/useCurrentPage'; export { useScrollToTop } from '@hooks/useScrollToTop'; export { useWindowWidth } from '@hooks/useWindowWidth';
파일 이름 네이밍
- 컴포넌트나 페이지 등
tsx
파일의 이름은 파스칼 케이스를 사용합니다.
- 그 외의 로직에 해당하는
ts
파일은 카멜 케이스를 사용합니다.
- 커스텀 훅의 이름은
use
접두사로 시작합니다.
- HOC 컴포넌트의 이름은
with
접두사로 시작합니다.
앞으로 나눠볼 내용
- 디렉토리 구조
- import order
- Git 컨벤션 (Issue, 커밋 규칙, PR 방식 등등..)