| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 |
- 아키텍처
- 웹워커
- radixui
- Webworker
- 리팩토링
- context.api
- 자바스크립트
- 에세이
- CustomHook
- Web
- provider 패턴
- MFA
- CRA
- 이것저것
- Function Region
- virtaullist
- 프론트엔드
- TypeScript
- 회고
- 리액트
- 합성 컴포넌트
- 오블완
- 클린코드
- 티스토리챌린지
- MicroFrontEnd
- vite
- react
- sharedworker
- JavaScript
- frontend
- Today
- Total
Lighthouse of FE beginner
[클린코드] 반복되는 값, 리터럴 본문
Overview
프론트엔드에서 프로젝트를 진행하다보면 반복되는 문자열 형식의 값이 존재합니다.
보통 반복되는 값은 다음과 같은 경우입니다.
1. 반복되는 문구로 사용자에게 노출할 텍스트
2. 서버와 약속을 해 프로젝트 자체에서 사용하는 텍스트
3. 프론트엔드 프로젝트에서만 사용하는 상수 값
2번의 경우 보통 코드라는 단어로 부르게 되고, 3번의 경우 프로젝트에서 상수라고 부르게 됩니다.
반복되는 값, 리터럴
반복 되는 값은 리터럴 그 자체를 매번 사용하는 것이 아닌 특정 변수에 담아서 사용해야 합니다.
예를 들면 다음과 같은 코드가 있습니다.
예시를 들기위해 서버에서 특정 에러 케이스를 200 응답에 status라는 필드를 통해 알려주고 있다고 가정합니다.
fetch('api').then((res) => {
const { status } = res;
if (status === 'NOT_EQUAL') {
console.log('NOT_EQUAL');
} else if (status === 'NOT_INTEGER') {
console.log('NOT_INTEGER');
} else if (status === 'SUCCESS') {
console.log('SUCCESS');
}
});
위와 같은 상황의 status 값은 서버와 약속한 값인 코드입니다.
서버와 클라이어언트가 서로 약속한 문자열을 지키지 않은 경우 프로그램은 실행 도중 장애 상황을 마주칠 수 있습니다.
이런 경우 특정 상황에서 사용하는 문자열들을 Map 형식의 객체 (집합)에 담아서 사용할 수 있습니다.
const RESPONSE_CODE = {
NOT_EQUAL: 'NOT_EQUAL',
NOT_INTEGER: 'NOT_INTEGER',
SUCCESS: 'SUCCESS'
} as const;
// 코드의 key를 타입으로 사용할 수 있습니다.
type ResponseKey = keyof typeof RESPONSE_CODE; // 'NOT_EQUAL' | 'NOT_INTEGER' | 'SUCCESS'
// 객체의 프로퍼티를 통해 접근합니다.
const key: ResponseKey = RESPONSE_CODE.NOT_EQUAL;
// 잘못된 프로퍼티를 사용하기 때문에 컴파일 에러가 발생합니다.
const keys = RESPONSE_CODE.NOTEQUAL;
작성된 코드를 살펴봅시다.
먼저 리터럴을 특정 객체의 프로퍼티로 사용해줍니다.
객체의 변수명을 정확히 해서 해당 코드들이 어떤 상황에서 사용하는 코드 값들인지 명확하게 표현해줍시다.
작성된 객체의 키를 타입으로 뽑아서 사용할 수 있습니다.
마지막으로 해당 키를 사용할 땐 객체의 프로퍼티에 접근해 사용하면 됩니다.
fetch('api').then((res) => {
const { status } = res;
if (status === RESPONSE_CODE.NOT_EQUAL) {
console.log(RESPONSE_CODE.NOT_EQUAL);
} else if (status === RESPONSE_CODE.NOT_INTEGER) {
console.log(RESPONSE_CODE.NOT_INTEGER);
} else if (status === RESPONSE_CODE.SUCCESS) {
console.log(RESPONSE_CODE.SUCCESS);
}
});
위의 API 성공 후 핸들링 코드를 리팩토링 했습니다.
리터럴 그 자체가 하드코딩 됐던 부분이 변수를 사용하도록 대체가 됐습니다.
이 경우 누릴 수 있는 이점은 다음과 같습니다.
이점
관리 포인트 일원화
만약 프로젝트 여러 파일에서 해당 코드를 사용한다고 가정합시다.
서버와 약속된 코드의 값이 바뀐다면 모든 파일을 순회하며 코드 값을 변경해야 합니다.
위와 같이 객체로 코드를 작성한다면 관리 포인트가 일원화 되어서 하나의 값만 변경해도 프로젝트 전역에서 변경되는 이점을 누릴 수 있습니다.
휴먼 에러 방지
리터럴 그 자체를 사용할 경우 IDE의 도움을 받을 수 없습니다.
하여 NOT_EQUAL을 NOTEQUAL로 사용한다던지, NOT_EQAUL로 사용한다던지 하는 휴먼 에러가 발생할 수 있습니다.
협업하기 좋은 코드
변수로 코드를 사용한다면 특정 리터럴에 이름을 붙여줘 어떤 역할을 하는지 명확하게 알려줄 수 있습니다.
이는 다른 사람과 협업하는 프로젝트에서 엄청난 효과를 발휘합니다.
먼저 해당 코드가 어떤 코드인지 물어보지 않아도 됨으로써 커뮤니케이션 비용이 감소합니다.
그리고 프로젝트에서 재사용 해서 사용할 수 있는 값이기 때문에 코드 중복을 감소시킨다는 이점도 있습니다.
Enum or Map type object
TypeScript를 사용할 때 위와 같이 리터럴을 enum 형식으로 사용하고 싶다면 TypeScript에서 제공하는 자료 구조인 enum 을 사용하는 방식과 JavaScript 문법인 Object를 활용해서 구현하는 방식이 있습니다.
enum은 JavaScript에서 제공하는 자료구조가 아닌 TypeScript에서 직접 만들어서 제공하는 자료구조 입니다.
결국 TypeScript 컴파일이 된 후 JavaScript의 Object로 변환이 됩니다.
하지만 TypeScript의 enum은 Tree-Shaking이 안된다는 단점이 존재합니다. 해당 글에서 이유를 살펴보기엔 글의 주제에 벗어나고, 라인의 테크 블로그에서 정확하게 설명해준 글이 있으니 링크를 첨부해드리겠습니다.
TypeScript enum을 사용하지 않는 게 좋은 이유를 Tree-shaking 관점에서 소개합니다.
마치며
오늘 포스팅은 클린 코드의 시리즈 글로써 반복되는 리터럴을 효과적으로 사용하는 방법에 대해서 알아봤습니다.
다음에도 클린 코드를 위한 좋은 주제로 찾아오도록 하겠습니다.
읽어봐주셔서 감사합니다.
'클린코드' 카테고리의 다른 글
| [클린코드] 함수의 클린코드 (3) | 2024.11.20 |
|---|---|
| [클린코드] TypeScript `any` (0) | 2024.08.15 |
| [클린 코드] 가독성 좋은 코드 - 변수 (3) | 2024.06.17 |