HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
♥️
2기 최종 프로젝트 팀별 공간
/
💡
[팀 04] 동규라미
/
📊
코딩 컨벤션
📊

코딩 컨벤션

폴더 구조스타일드 컴포넌트CSS 프로퍼티 순서import 문 정렬네이밍타입핸들러 함수PrettierLint함수 정의Container? Wrapper?API 로직

폴더 구조

폴더가 너무 많아도 그리고 너무 중첩되어도 좋지 않다
타입이 중복되어 사용된다면 types 폴더 하나에서 관리할 수 있도록 하자
.d.ts 파일보다는 .ts 파일에서 export 를 이용하자
├── api ├── assets ├── components │ └── Button │ ├── Button.styles.ts │ ├── Button.tsx │ └── index.ts ├── constants ├── hooks ├── recoil ├── pages ├── styles ├── interfaces ├── types └── utils

스타일드 컴포넌트

백틱 형식을 오브젝트 형태로 통일하자
현재 common.ts 에 있는 컴포넌트를 components 폴더로 옮기자 ⇒ 이것도 또한 컴포넌트이기 때문에
Object Styles
Writing styles with objects is a powerful pattern built directly into the core of emotion. Instead of writing css properties in kebab-case like regular css, you write them in camelCase, for example background-color would be backgroundColor.
Object Styles
https://emotion.sh/docs/object-styles#with-styled
Object Styles

CSS 프로퍼티 순서

.selector { /* Positioning */ position: absolute; z-index: 10; top: 0; right: 0; /* Display & Box Model */ display: inline-block; overflow: hidden; box-sizing: border-box; width: 100px; height: 100px; padding: 10px; border: 10px solid #333; margin: 10px; /* Color */ background: #000; color: #fff /* Text */ font-family: sans-serif; font-size: 16px; line-height: 1.4; text-align: right; /* Other */ cursor: pointer; }

import 문 정렬

"import/order": [ "error", { "groups": ["builtin", "external", "internal", ["parent", "sibling"], "index"], "alphabetize": { "order": "asc", "caseInsensitive": true }, "newlines-between": "always" } ]
eslint-plugin-import/order.md at main · import-js/eslint-plugin-import
Enforce a convention in the order of require() / import statements. +(fixable) The--fix option on the [command line] automatically fixes problems reported by this rule. With the option set to ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"] the order is as shown in the following example: Unassigned imports are ignored, as the order they are imported in may be important.
eslint-plugin-import/order.md at main · import-js/eslint-plugin-import
https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md
eslint-plugin-import/order.md at main · import-js/eslint-plugin-import

네이밍

💡
컴포넌트명은 파스칼 케이스 ex) Header, Button 변수명, 함수명은 카멜 케이스 ex) isLogin

타입

파스칼 케이스로 Prefix 없이 정의한다.
Props는 해당 타입이 사용되는 파일 내부에 정의한다.
interface Props { name: String, password: String } const Login = ({ name, password }: Props) => { return (); }

핸들러 함수

Prefix로 handle을 사용한다.
const handleChange = () => {}
핸들러 함수의 타입은 React.ChangeEventHandler<HTMLInputElement> 와 같은 형태로 통일한다.
onChange: React.ChangeEventHandler<HTMLInputElement>

Prettier

🌺
코드 포맷팅을 위한 Prettier 설정은 아래와 같다.
{ "printWidth": 120, "tabWidth": 2, "singleQuote": true, "semi": true, "bracketSpacing": true, "bracketSameLine": false, "jsxSingleQuote": true, "trailingComma": "all", "useTabs": false, "singleAttributePerLine": true, "endOfLine": "auto" }

Lint

🛠
코드 린팅을 위한 ESLint 설정은 아래와 같다.
🚨
만약 새로운 룰이 필요하거나 기존 룰 중에서 사용하지 않아야 할 룰이 있는 경우 1. 추가하거나 삭제해야 하는 이유를 노션에 문서로 정리한다. 2. 정리한 내용을 바탕으로 팀원들과 상의 후 결정한다.
{ "root": true, "parser": "@typescript-eslint/parser", "parserOptions": { "tsConfigRootDir": "./", "project": "./tsconfig.json" }, "plugins": ["@typescript-eslint"], "extends": [ "next/core-web-vitals", "airbnb", "airbnb-typescript", "plugin:react/jsx-runtime", "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended-requiring-type-checking", "prettier" ] }

함수 정의

🔊
function 키워드 대신 화살표 함수를 사용한 함수 표현식으로 함수를 정의한다.
const handleSubmit = () => {}; const ComponentName = () => { return <div>hello</div>; }; export default ComponentName;

Container? Wrapper?

단일 요소를 감싸야 한다면 Wrapper
<Wrapper> <span>hi</span> </Wrapper>
2개 이상의 요소를 감싸야 한다면 Container
<Container> <img src='/img/good.png' /> <span>hi</span> </Container>

API 로직

// API 요청 함수 분리 const fetch = async (id: number) => { try { const { data: { data }, } = await axiosAuthInstance.get<Response<MatchRecord>>(`/api/matches/records`, { params: { userId: id }, }); return data } catch (error) { // 에러 처리 } } // 컴포넌트 내부 API 요청 React.useEffect(() => { setIsMatchLoading(true); (async () => { const matchRecord = await fetch(); setmatchRecord(() => matchRecord)); setIsMatchLoading(false); })(); }, [router.isReady])