FE 코딩 컨벤션

Hyeon·2024년 1월 29일
0

Intro

해당 컨벤션은 회사 동료분과 함께 정의하였습니다.

기본적으로 프로젝트에 ESLint 규칙과 Prittier 의 포멧팅이 반영되어 있지만, 개발자가 지켜야할 프론트엔드 파트의 컨벤션을 정의했습니다.

좋은 코드 퀄리티와 원활한 프론트엔드 개발자의 협업을 위해서 아래의 코딩 컨벤션을 준수해주시기 바랍니다.


들여쓰기

  • 들여쓰기는 space 2문자를 사용합니다.

문자열

  • 특별한 경우를 제외하고 문자열은 작은 따옴표를 사용합니다.
var text = '123';
var html = '<a href="#">link</a>';
var style = {
  'left': '100px',
  'top': '100px'
}

문장의 종료

  • 한 줄에 하나의 문장만 허용하며, 문장의 종료 시에는 반드시 세미콜론 ; 을 사용합니다.

식별자 Naming Convention

  • 직관적으로 의미를 파악할 수 있도록 가급적이면 약어를 사용하지 않습니다.
  • 한글을 직번역한 변수명을 사용하지 않습니다.
// Bad
const BunYukByunSoo = '번역변수';
  • 공백을 허용하지 않습니다.
  • 언어에서 사용하는 예약어 를 사용하지 않습니다.
  • 변수, 함수는 소문자 카멜 케이스로 선언합니다.
  • 배열은 복수형으로 선언합니다.
  • private 변수는 _ 를 접두사로 선언합니다.
  • HTML 태그는 소문자로 작성합니다.
// Good
<div></div>

// Bad
<DIV></DIV>
  • 상수는 스네이크 케이스를 활용해 대문자와 _ 를 사용해 선언합니다.
const THIS_IS_CONSTANT = 'string';
  • props 로 전달되는 핸들러 함수는 on 으로 시작합니다.
interface IProps {
  onClick: (event) => void;
}

function Component(props: IProps) {
  return <></>;
}

const Component = (props: TProps) => <></>;
  • 컴포넌트 내부에서 직접 정의하는 이벤트 핸들러 함수는 handle 로 시작합니다.
function Component(props) {
  const handleClick = (event) => console.log(event);

  return <></>;
}
  • Boolean 타입 변수의 식별자 명은 가급적이면 부정형으로 선언하지 않는 것을 권고합니다. 또한 Boolean 타입의 변수의 식별자는 is, has, can 의 접두사를 사용하여 선언합니다.
const isNotBoolean = false; // 옳지 않은 선언
cosnt isBoolean = true; // 옳은 선언
const canOpen = true;
const hasChildren = true;
// 잘못된 선언
enum FORM_MODE {
  CREATE = 'create',
  EDIT = 'edit',
  ADD = 'add',
}

// 컨벤션을 지킨 선언
enum FormMode {
  Create = 'create',
  Edit = 'edit',
  Add = 'add',
}
  • Interface 선언은 접두사 I 를 붙여 정의합니다.
interface IServer {
  title: string;
  value?: string;
}
  • type 선언은 접두사 T 를 붙여 정의합니다.
type TServer = {
  title: string;
  value?: string;
}

React and Typescript

  • 컴포넌트는 항상 파스칼 케이스로 선언합니다.
  • Inline Style 을 하지 않습니다.
  • 스타일 변수는 기본적으로 분리해서 사용합니다. ( Component.style.ts )
  • 기본적인 컴포넌트는 function 으로 선언합니다.
function Component(props) {
  return (<div></div>);
}
  • children 을 props 로 포함 할 경우 React.ReactNode 로 타이핑 합니다.
type TProps = {
  children: React.ReactNode;
}

function Component(props: TProps) {
  return <div>{props.children}</div>;
}
  • 정말 타입이 난해하지 않는 경우를 제외하고는 any 를 사용하지 않습니다.
    • any 사용시 eslint warning을 무시할 수 있도록 아래의 주석을 명시합니다.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
  • 묵시적인 타입 캐스팅을 사용하지 않습니다. 타입 캐스팅은 항상 명시적으로 합니다.

Style


Css in JS

  • Emotion 의 css 를 선언 시 식별자 명은 변수의 카멜 케이스로 선언합니다.
  • css 를 사용할 땐 가급적 object 가 아닌 template string 을 활용합니다.
const textFieldCss = css`
  font-size: 14px;
`;
  • Emotion 의 styled 를 활용해 스타일링을 할 때 변수명은 컴포넌트와 마찬가지로 파스칼 케이스로 선언합니다.
const Wrapper = styled.div``;
cosnt FormRow = styled.section``;

Sass

  • 클래스명 선언 규칙 (BEM 을 기초로 코딩)
  • 소문자, 숫자 만을 조합
  • 조합은 -(하이픈)으로 연결하여 작명
// 기본적으로 .을 사용함
className={styles.test}

// class name에 - 이 포함될 경우 아래와같이 사용
className={styles[‘test-test’]}

Function

  • 함수의 식별자명은 항상 시멘틱하게 선언합니다. (어떤 기능을 하는 함수인지 함수명을 보고 알 수 있도록 선언합니다.)
  • Typescript 를 활용해 리턴 타입과 매개 변수를 정확하게 타이핑 해줍니다.
  • 이벤트를 핸들링 하는 함수는 handle 접두사를 이용합니다.
  • 반환값이 boolean 인 함수는 is 접두사를 활용하며, 어떤 값을 리턴하는 함수는 get 접두사를 활용합니다.

변수 선언 키워드

  • var 키워드를 사용하지 않고 constlet 을 사용하여 변수를 선언합니다.

전역변수

  • 네임스페이스를 사용하여 전역변수를 최소화하며 암묵적인 전역변수는 절대로 사용하지 않습니다.

배열과 객체

  • 배열과 객체는 반드시 리터럴 로 선언합니다. 배열 복사 시 순환문 을 사용하지 않습니다.

배열

// Good
var emptyArr = [];
var arr = [1, 2, 3, 4, 5];

// Bad
var emptyArr = new Array();
var arr = new Array(1, 2, 3, 4, 5);
var items = [1, 2, 3, 4];
var len = items.length;
var itemsCopy = [];

// Bad
for (var i = 0; i < len; i++) {
  itemsCopy[i] = items[i];
}

// Good
const arr = [...items];

객체

// Good
var emptyObj = {};
var obj = {
  pro1: 'val1',
  pro2: 'val2'
};

// Bad - 객체 생성자 사용
var emptyObj = new Object();
var obj = new Object();

함수

  • 함수는 함수 선언식과 표현식을 사용하여 선언합니다. 함수 표현식과 함수 생성자로 선언된 함수는 호이스팅 시 값이 할당되지 않습니다. 선언 이전에 사용 시 오류가 발생 하므로 함수는 사용 전에 선언해야 합니다. 함수 선언문은 변수 선언문 다음에 옵니다.
// Good(1)
function doSomething(param1, param2) {
  return param1 + param2;
}

// Good(2)
var doSomething = function(param1, param2) {
  return param1 + param2;
};

// Good(3) - 이름있는 함수 표현식
var doSomething = function doSomething(param1, param2) {
  return param1 + param2;
};

// Bad(1) - 함수 생성자 사용
var doSomething = new Function('param1', 'param2', 'return param1 + param2;');

// Bad(2) - IIEF
(function() {
  ...
}());
  • 함수표현식 대신 Arrow function을 사용합니다.
// Good
[1, 2, 3].map(x => {
  const y = x + 1;
  return x * y;
});

[1, 2, 3].map(function (x) {
  const y = x + 1;
  return x * y;
});
  • 함수의 본체가 하나의 식이면 중괄호 를 생략하고 암시적 return 을 이용합니다.
[1, 2, 3].map(number => `A string containing the ${number}.`);

Destructuring

  • 객체에서 여러 프로퍼티에 접근할 때는 Destructuring 을 이용합니다.
function Template({var, const, ...args}) {
  cosnt A = var;
};
  • 배열도 Destructuring 이 가능합니다.
const arr = [1, 2, 3, 4];

// Good
const [first, second] = arr;

// Bad
const first = arr[0];
const second = arr[1];

템플릿 문자열

  • 문자열을 생성하는 경우 template string 을 사용합니다.
// Good
function sayHi(name) {
  return `How are you, ${name}?`;
}

// Bad
function sayHi(name) {
  return 'How are you, ' + name + '?';
}

// Bad
function sayHi(name) {
  return ['How are you, ', name, '?'].join();
} 

조건 확인하기

값이 있는가?

[문자열]: 빈 문자열이 아닌가?

// Good(1)
if (string) ...

// Bad
if (string !== "") ...

[배열]: 순회할 요소가 있는가?

// Good(1)
if (array.length) ...

// Bad
if (array.length > 0) ...

[객체]: 순회할 속성이 있는가?

if (Object.keys(object).length) ...

값이 비어있는가?

[문자열]: 빈 문자열인가?

// Good(1)
if (!string) ...

// Bad
if (string === '') ...

[배열]: 빈 배열인가?

// Good(1)
if (!array.length) ...

// Bad
if (array.length === 0) ...

참조변수가 참(true)인가?

// Good
if (variable) ...

// Bad
if (variable === true) ...

참조변수가 거짓(false)인가?

// Good
if (!variable) ...

// Bad
if (variable === false) ...

반환하기

  • 특정 값을 반환해야 하는 경우, 함수의 맨 마지막에서 한 번만 return 합니다. 단, 예외 처리로 빠져나가기 위해 사용하는 return; 은 위 룰에서 제외됩니다.
  • 함수 내에서 if 문이 여러 번 호출되면, 함수로 분리해야 합니다.
// Good
function getResult() {
  var resultData;
  if (condition) {
    resultData = someDataInTrue;
  } else {
    resultData = someDataInFalse
  }
  return resultData;
}

// Allow
function foo(isValid) {
  if (!isValid) {
    return;
  }
  return someDataInTrue;
}

// Bad
function getResult() {
  if (condition) {
    return someDataInTrue;
  }
  return someDataInFalse;
}

순회하기

배열

const array = [1, 2, 3];

// Good
array.forEach((number) => {...});

// Bad
for (var i = 0; i < array.length; i++) ...

// Worse
for (var i in array) ...

객체

// Good
Object.keys(object).forEach(key => {...});

// Bad
var key;
for (key in object) ...

주석

  • 주석은 설명하려는 구문에 맞춰 들여쓰기 합니다. 문장의 끝에 주석을 작성할 경우, 한 줄 주석을 사용하며 공백을 추가 합니다.
  • 사용하지 않거나 의미 없는 주석은 항상 제거해서 커밋 합니다.

공백

  • 키워드, 연산자와 다른 코드 사이에 공백이 있어야 합니다.
// Good
var value;
if (typeof str === 'string') {
  value = (a + b);
}

// Bad
var value;
if(typeof str==='string') {
  value=(a+b);
}
  • 콤마 다음에 값이 올 경우 공백이 있어야 합니다.
// Good
var arr = [1, 2, 3, 4];

// Good
someFunction(a, b, {
  prop1: 1,
  prop2: 2,
  prop3: 3
});

// Bad - 괄호 안에 공백
if ( typeof str === 'string' )

// Bad - 괄호 안 공백, 콤마 뒤 공백 없음
var arr = [ 1,2,3,4 ];

// Bad - 객체의 닫는 괄호 다음에 개행
someFunction(a, b, {
        prop1: 1,
        prop2: 2,
        prop3: 3
    }
);

삼항 연산자 사용

  • 간단한 if 문의 경우 삼항 연산자 사용 합니다.
condition ? 'a' : 'b'

null 병합 연산자

  • 데이터에서 undefined 나 null 이 있을거라고 예상되는 경우, null 병합 연산자를 활용합니다.
const data = undefined;

const result = a ?? 'a'; // a 가 undefined 이거나 null 일 경우 'a' 를 리턴

옵셔널 체이닝

  • 서버 데이터가 undefined 일 경우를 예측하며 코딩 합니다.
const { data: subscription } = useSubscription();

<div>{subscription?.count}</div>

Boolean 캐스팅

  • Boolean 으로 타입 캐스팅이 필요한 경우 Wrapper 클래스를 활용하지 않고 !! (double negation) 를 활용합니다.
// Good
const condition = !!array.length;

// Bad
const conditon = new Boolean(array.length);

Number 캐스팅

  • Number 타입으로 캐스팅이 필요한 경우엔 Wrapper 클래스인 Number 를 활용할 수 있습니다.
const number = Number('1');
cosnt number = +'1';

조건문

  • if 문을 통해 조건 제어를 사용할 땐 항상 중괄호 를 사용합니다.
// Bad
if (condition) return;

// Good
if (condition) {
  return;
}

데이터형 확인하기

  • 암묵적 캐스팅으로 인한 혼동을 막기 위해 완전항등연산자인 ===, !== 만을 사용합니다.

  • 예외: null 또는 undefined를 한번에 확인

//[문자열]
typeof variable === 'string'

//[숫자]
typeof variable === 'number'

//[불린]
typeof variable === 'boolean'

//[객체]
typeof variable === 'object'

//[배열]
Array.isArray(arrayObject)

//[널 Null]
variable === null

//[미할당 Undefined]
typeof variable === 'undefined'
variable === undefined

//[null || undefined]
variable == undefined

//[엘리먼트 노드]
element.nodeType === 1

절대 안 됨

  • 원시 래퍼 생성자는 절대 사용하지 않습니다. (Boolean, String, ...)
    • Number 클래스는 예외적으로 사용을 허용합니다.
  • eval 을 절대 사용하지 않습니다.
  • with 문 을 절대 사용하지 않습니다.

0개의 댓글

관련 채용 정보