[인턴쉽] 프론트엔드 인턴쉽 회고 - 문서화 아카이빙📃

YUZAMIN
Hello, World! I'm YUZAMIN, a diligently endeavoring frontend developer 🐤💦
[인턴쉽] 프론트엔드 인턴쉽 회고 - 문서화 아카이빙📃

프론트엔드 인턴쉽 회고👩🏻‍💻

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, ...)
    • 이벤트 핸들러: handle + 명사 + 동사
      • ex) handleButtonClick()
      • 추가로, 이벤트 핸들러를 받는 prop의 이름은 on + 이벤트명
        • ex) onClick

중괄호

  • 원활한 이해를 위해 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" // 화살표 함수의 괄호 사용 방식
}