[인턴쉽] 프론트엔드 인턴쉽 회고 - 문서화 아카이빙📃
Summary
프론트엔드 인턴쉽 회고👩🏻💻
Intern Record📼
작년 12월 말부터 올해 3월 말까지 스타트업 개발팀의 프론트엔드 인턴으로 근무하였다. 올해가 거의 다 지나간 시점에서, 올해 진행했던 큼직큼직한 프로젝트에 대한 기록을 남기는 게 좋을 것 같아서 조금 늦었지만 이렇게 회고록을 남기고자 한다. 사실 인턴쉽 전반에 대한 회고는 이미 인턴쉽 회고 에 작성을 하였기 때문에, 이번 기록에는 인턴으로 근무하면서 문서화를 해왔던 내용을 정리해두려고 한다.
개인 또는 팀 프로젝트들이 아닌 실사용되는 서비스를 개발하는 것이라 비록 근무하는 동안에는 협업할 다른 프론트엔드 개발자가 없었지만 추후 입사할 다른 프론트엔드 개발자들을 위해 명확한 규칙 하에 개발을 해야한다는 생각이 들었다. 내가 왜 이런 이름으로 변수나 함수를 만들었는지, 폴더별로 어떤 역할을 하는지 등을 빠르고 간편하게 확인할 수 있어야 한다는 필요성이 느껴졌었고, 나 또한 코드리뷰를 받을 수 없는 상황에서 일관적인 개발을 하려면 명시된 규칙이 꼭 존재해야 한다고 생각하였다. 개발팀 내에 프론트엔드 개발자가 나밖에 없었기 때문에 (당연히) 코드 컨벤션을 정하고 문서화를 하는 것도 나 혼자 작업해야 했다. 그러니까 사실상 자기자신 + 미래의 프론트엔드 개발자와의 약속이나 마찬가지인 내용들이었던 것이다. 그래서 나는 열심히 조사하여 최대한 성심성의껏 위키에 정리해두었고, 분명 미래의 나에게도 큰 도움이 될 것 같아서 이 블로그에 아카이빙을 해두고자 한다.
Document📄
Code Convention🔐
기본 규칙
- 줄임말 사용하지 않기
- 다른 개발자가 이름을 통해 정보를 바로 파악할 수 있도록 하기
- 반복 시 map() 함수 사용하기
- 절대경로 사용하기
네이밍 규칙
PascalCase
: 타입, 인터페이스, 리액트 컴포넌트 이름에 사용camelCase
: 변수, 자바스크립트 함수, 커스텀 훅, props 이름에 사용UPPER_SNAKE_CASE
: 상수 변수 이름에 사용-
(상태명과 관련된)명사 + Reducer
: 전역 상태 관리 시 상태 이름에 사용 - 함수명
- 기본적으로 3, 4 단어 구성, 그러나 상황에 따른 예외 허용
- 일반 함수: 동사 + 명사
- ex)
getUserId()
- 어떤 값으로부터 다른 값을 계산하여 도출해내는 함수:
get___From()
- ex)
getTodayDateFrom(date: Date, ...)
- ex)
- ex)
- 이벤트 핸들러: handle + 명사 + 동사
- ex)
handleButtonClick()
- 추가로, 이벤트 핸들러를 받는 prop의 이름은 on + 이벤트명
- ex)
onClick
- ex)
- ex)
중괄호
- 원활한 이해를 위해
for, if, function
등에서 중괄호를 생략하지 않음
Import
- 이 파일에서 어떤 것들이 필요한지 한 눈에 알 수 있도록 작성하기
- React17에서는
import React from 'react'
문을 넣지 않는 것을 권장 - 작성 순서
- node_modules
- util function
- 멀리 있는 컴포넌트
- 근처에 위치한 컴포넌트
- style 관련
Styled Components
- 모든 styled 변수는 사용되는 컴포넌트 파일 내에 정의하기
- 다른 컴포넌트와 공유 시
export
를 활용하기 - styled 정의부는 파일 하단에 모아두기
- 컴포넌트명은
Container
-Wrapper
-Box
-Item(Button, ProfileImage 등)
순으로 nested 하기
Initial Settings🧱
React.js + TypeScript + styled-components 환경에서의 초기 설정
Directory Structure📂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// react.js
📦src
┣ 📂assets
┃ ┣ (📂images)
┃ ┣ (📂icons)
┣ 📂components
┃ ┣ 📂pages
┣ 📂hooks
┣ 📂layout
┣ 📂locales
┣ 📂modules
┃ ┣ 📂actions
┃ ┣ 📂reducers
┃ ┣ 📂sagas
┣ 📂scheme
┣ 📂styles
┃ ┣ 📜globalStyle.ts
┃ ┣ 📜theme.ts
┣ 📂utils
┣ 📜App.tsx
┣ 📜i18n.ts
┣ 📜constants.ts
┗ 📜index.tsx
- App.tsx: routing을 위한 코드가 담긴 파일
- assets: 이미지, 아이콘 등 프로젝트에서 사용되는 자원들의 폴더
- components: 컴포넌트들의 폴더
- pages: 페이지 컴포넌트들의 폴더
- hooks: React의 custom hooks의 폴더
- layout: UI 공통 레이아웃 폴더
- locales: 다국어 지원을 위한 폴더
- modules: Redux & Redux-saga에 사용되는 파일들의 폴더
- actions: action creator 함수가 정의된 파일들의 폴더
- reducers: reducer 정의된 파일들의 폴더
- sagas: action을 인자로 받아 비동기적 data fetch 처리하는 generator function이 정의된 파일들의 폴더
- scheme: 개발 중 사용되는 각종 type, interface의 폴더
- styles: 전역적으로 사용되는 style을 위한 폴더
- GlobalStyle.js: style 초기화 또는 전역적으로 지정한 style을 위한 파일
- theme.js: 전역적으로 사용할 색상, 반응형 디자인을 위한 기기의 최소 폭 등을 정의하는 파일
- utils: 다양한 파일에서 사용할 util function을 위한 폴더
Basic Packages 📦
$ yarn add react-router-dom @types/react-router-dom
- routing을 위한 react-router-dom
$ yarn add styled-components @types/styled-components
- css styling을 위한 styled-components
$ yarn add styled-components.macro
- 개발자 도구 사용시 암호화되는 styled-components를 복호화된 상태로 보여주는 패키지
$ yarn add styled-reset
- 모든 css style을 reset하는 패키지
$ yarn add -D prettier eslint-plugin-prettier eslint-config-prettier
- TypeScript prettier
$ yarn add -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser
- TypeScript eslint
$ yarn add -D eslint-config-airbnb
- airbnb의 eslint를 사용하는 패키지
ESLINT Setting💎
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'prettier'],
extends: [
'plugin:import/errors',
'plugin:import/warnings',
'plugin:prettier/recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
],
rules: {
'linebreak-style': 0, // 일관된 줄바꿈을 위한 설정
'import/prefer-default-export': 0, // default export를 권장하는 설정
'prettier/prettier': 0,
'import/extensions': 0, // import path 관련 설정
'no-use-before-define': 0, // 선언되지 않은 식별자에 대한 참조 발생 시 경고
'import/no-unresolved': 0, // imported된 모듈의 resolve를 보장
'import/no-extraneous-dependencies': 0, // package.json에 선언되지 않은 외부 모듈을 import 해오는 것을 금지
'no-shadow': 0, // local scope에 속한 변수와 containing scope에 속한 변수가 같은 이름을 가질 때 발생하는 shadowing(혼란 발생, global 변수로의 접근이 불가능) 방지, shadowed된 변수 사용 금지
'react/prop-types': 0, // props의 누락 방지
'react/jsx-filename-extension': 'off', // 파일 확장자를 정확히 확정하기 위한 설정
'jsx-a11y/no-noninteractive-element-interactions': 0, // interactive하지 않은 element에 이벤트 핸들러를 지원하지 않음
},
}
Prettier Setting🔮
1
2
3
4
5
6
7
8
9
{
"singleQuote": true, // 작은따옴표 사용 여부
"semi": true, // 세미콜론 사용 여부
"useTabs": false, // Tab 사용 여부
"tabWidth": 2, // Tab 너비
"trailingComma": "all", // 여러 줄을 사용 시 마지막 항목 뒤에 후행 콤마 사용 여부
"printWidth": 120, // 줄바꿈할 폭의 길이
"arrowParens": "always" // 화살표 함수의 괄호 사용 방식
}