-
[TS] enum과 object의 차이가 무엇인가요? 꼭 enum을 사용하면 안되나요?카테고리 없음 2024. 3. 5. 17:09728x90
[TS] enum과 object의 차이가 무엇인가요? 꼭 enum을 사용하면 안되나요?
아래 코드에 이런 코드리뷰가 달렸다.
"support view 도 enum class로 관리할 수 있다면 더 좋을 것 같습니다."
import styled from '@emotion/styled'; export const Controller = styled.button<{ view: 'PC' | 'TABLET' }>` border: none; z-index: 1; cursor: pointer; transition: background-color 0.3s ease-in-out; background-color: ${({ theme }) => theme.gray[0]}; `; export const PrevController = styled(Controller)` margin-right: ${({ view }) => (view === 'PC' ? '3.125rem' : '1.875rem')}; `; export const NextController = styled(Controller)` margin-left: ${({ view }) => (view === 'PC' ? '3.125rem' : '1.875rem')}; svg { transform: matrix(-1, 0, 0, 1, 0, 0); } `;
나는 enum이 좋지 않다는 말을 어디선가 들어서, 평소에 코드를 작성할 때 enum을 사용하지 않고 있었다. 하지만 정확한 이유는 알고 있지 않았고, enum을 사용해 보니 javascript 객체와 흡사하여 어떤 차이점이 있는지 궁금해졌다.
그래서 오늘은 enum에 대해 정확히 알아보겠다.
enum
enum은 Enumeration의 약자로 열거라는 뜻을 가지고있다.
즉, 열거라는 뜻대로 상수들을 비슷한 종류끼리 묶어놓은 것이다.
const PC = 'PC'; const TABLET = 'TABLET'; const MOBILE = 'MOBILE';
이러한 상수들이 따로따로 있으면 불편하니 관심사에 맞게 묶어놓은 것이 enum이다.
먼저 javascript에서 enum이 어떻게 사용되는지 알아보자.
javascript에서의 enum
사실 자바스크립트에는 enum이라는 형태가 공식적으로 존재하지 않는다.
따라서 개발자들은 object를 이용하여 enum처럼 사용했다.
const Device = { PC: 'PC', TABLET: 'TABLET', MOBILE: 'MOBILE', } console.log(Device.PC); //'PC'
굳이 이렇게 enum을 사용하려고 했던 이유는 enum 사용 시 안정적이며, 가동석이 좋고 오류 발생 위험도 적기 때문이다.
typesciprt에서의 enum
타입스크립트에는 enum이 공식적으로 존재한다.
아래와 같이 enum 키워드를 사용하여 선언할 수 있다. 사용하는 방법은 객체와 같다.
enum Device { PC = 'PC', TABLET = 'TABLET', MOBILE = 'MOBILE', } console.log(Device.PC); //'PC'
그럼 왜 enum이 존재하는 것일까? 어차피 객체로 사용 가능한데 말이다.
그 이유는 바로 원시타입과 참조타입에 있다.
객체는 기본적으로 참조타입이기 때문에 값이 아닌 메모리의 주소를 저장한다. 따라서 const로 선언하더라도 내부 값을 변경할 수 있다. 참조타입과 원시타입이 궁금하다면 아래 게시글을 확인하자.
[JS] string 타입은 원시타입인데 어떻게 메서드 호출을 지원할까? 원시타입과 참조타입
[JS] string 타입은 어떻게 메서드 호출을 지원할까? 원시타입과 참조타입 javascript는 dynamic type 언어이기 때문에 변수를 선언할 때에 변수의 타입을 명시할 필요는 없다. 하지만 그렇다고 타입이 존
frorong.tistory.com
그런데 타입스크립트에는 as const라는 것이 존재한다. 더불어 자바스크립트에도 Object.freeze가 존재하여 객체 고정이 가능하다.
const Object1 = {} as const; const Object2 = {}; Object.freeze(Object2);
심지어 enum을 쓰면 안 되는 이유를 알아보면 tree shaking이 거론된다. tree shaking은 사용하지 않는 코드를 삭제하는 기능인데, enum을 사용하면 tree shaking이 되지 않는다.
그 이유는 typescript에서 지원하는 enum을 javascript로 트랜스파일하면 즉시 실행 함수가 생성되는데, 번들러가 이를 제거할지 말지 판단할 수 없어 tree shaking이 되지 않는다.
결국 사용하지 않는 enum이 존재하더라도 최종 번들에서 제거되지 않는다. enum 사용은 번들의 사이즈 문제로 이어지는 것이다.
이를 해결하기 위해 const enum을 사용한다면, enum의 내용이 트랜스파일 시점에서 인라인으로 확장되기 때문에 코드의 양을 조금이나마 줄일 수 있다.
그래서 enum을 사용해야 할지, 말아야 할지에 대해서는 다양한 의견이 존재한다. 나는 enum이라는 키워드가 가져와주는 의미가 크다고 생각한다. 또한 enum이 갖고 있는 또 다른 장점이 있다.
바로 아래와 같이 타입 지정이 가능하다는 것이다.
enum Device { PC = 'PC', TABLET = 'TABLET', } export const Controller = styled.button<{ view: Device }>`
이렇게 하면 view의 타입이 Device enum으로 지정된다. 하지만 그렇다고 'PC' | 'TABLET'가 되는 것이 아니다. Device.PC | Device.Tablet이 되면서, 안정성 측면에서의 이점이 있다.
마치며
이러한 enum을 사용하여, 처음에 나온 코드는 아래와 같이 변경되었다. Device는 다른 파일에서도 자주 사용되어 utils 디렉토리로 분리하였다. enum에 대한 단점과 안 좋은 의견이 많지만, 이 프로젝트에서는 enum의 단점이 생길 이유가 없다. 선언만 되어있고 사용하지 않는 enum이 있다면 오류가 발생하도록 구성되어 있기 때문이다.
'NewEnum' is declared but never used.ts(6196)
enum을 사용하여 훨씬 깔끔하고 아름다운 코드가 되었다. 역시 진리는 없다. 상황에 맞게 대처하자.
import styled from '@emotion/styled'; import type { Device } from 'utils'; enum Margin { PC = '3.125rem', TABLET = '1.875rem', } export const Controller = styled.button<{ view: Device }>` border: none; z-index: 1; cursor: pointer; transition: background-color 0.3s ease-in-out; background-color: ${({ theme }) => theme.gray[0]}; `; export const PrevController = styled(Controller)` margin-right: ${({ view }) => Margin[view]}; `; export const NextController = styled(Controller)` margin-left: ${({ view }) => Margin[view]}; svg { transform: matrix(-1, 0, 0, 1, 0, 0); } `;
728x90