🐳 배경
현재 제가 맡은 프로젝트는 Express와 ORM 없이 쌩 Query를 사용 중입니다!
그리고 enum을 사용하지 않고 common_code를 사용해 DATABASE에 code값과 code_name을 저장해 사용 중입니다.
가령 OC0001 = '위원회' 이런 식입니다.
이 점 참고해서 읽어주시면 감사하겠습니다.
누군가 작성한 아래와 같은 코드를 보자!
let query =
`SELECT
*
FROM STUDENT
WHERE STUDENT_TYPE = 'SC0001' `
무슨 말인지 이해가 가십니까...?
이 쿼리문이 무엇을 조회하기 위한 쿼리문인지는 SC0001 code 값이 무엇을 의미하는지 DB에 들어가 common_code에서 값을 읽어야지만 알 수 있을 것입니다.
그렇다면 나~중에 이 코드를 읽는 사람은 IDE와 DB를 오가며 코드를 해석하기 위해 노력하겠죠
그리고 비슷한 코드들이 계속 반복될 테니 ( SC0001 , SC0002, CMT0001 이런 식으로 말이죠... 절~~~대 경험담이 아닙니다 )
각각의 코드들이 무엇을 의미하는지 정말 헷갈리게 될 것입니다.
그래서 저는 제가 맡은 부분부터는 Enum을 도입하기로 마음먹었습니다!
🐳 Enum 적용 목표
적용하기 전에 목표한 것이 있습니다.
- 기존 구조를 헤치지 않기
- 오직 코드만 보고 의미를 이해하기 ( 기존에는 DB와 CODE를 함께 봐야 했기 때문에 )
1. 기본 구조를 헤치지 않기
처음에 회사에서 common_code라는 방법을 봤을 때는 생소하기도 했고 Enum을 쓰면 되지 않나 라는 생각이 많이 들었다.
이름을 가지고 올 때도 DB에서 Join 해서 가지고 와야 하고 여러모로 불편한 부분이 많았기 때문이다.
하지만 프로젝트라는 것은, 그리고 회사의 시스템이라는 것은 공동의 약속이기 때문에 상의 없이 마음대로 바꿔버려서는 안 된다고 생각했기 때문에 기본 구조를 헤치지 않으면서 Enum을 도입하려고 했다. ( 그리고 다음에는 Enum을 사용하기로 팀 내에서 얘기가 되었다! )
2. 오직 코드만 보고 의미를 이해하기
이 부분이 프로젝트에서 힘들었던 부분이었다.
누군가 기존에 작성한 코드를 이해하려면 IDE에서 나가 DB를 찾아보고... 여간 불편한 게 아니었다.
그래서 나 이후의 사람은 그러지 않았으면 해 Enum을 도입하려고 마음도 먹었다.
🐳 Enum 적용
저기요 그런데 Javascript는 Enum 없는데요?
하지만 javascript는 객체의 왕국 아닌가.
모든 것을 객체로 해결할 수 있게 만들었다. ( 당연히 공식 지원해 주면 좋겠지만 )
그래서 나는 아래의 코드처럼 객체를 활용해 Enum을 구현해 봤다.
export const STUDENT_TYPE = {
ELEMENTARY_SCHOOL: 'SC0001',
MIDDLE_SCHOOL: 'SC0002',
HIGH_SCHOOL: 'SC0003',
};
우선 SCREAMING_SNAKE_CASE 을 사용해 이름을 지었다.
그리고 객체의 값에 설명이 아닌 사용될 common_code 값을 사용했다.
이런 질문이 있을 수도 있다.
"근데 이게 도대체 뭐가 바뀐 거죠 ?"
🐳 Enum 적용의 장점
다시 한번 처음에 봤던 코드가 어떻게 변하는지 살펴보자!
// 위에서 작성한 enum 파일을 import 해옵니다.
const STUDENT_TYPE = require("../studentType.enum")
let query =
`SELECT
FROM STUDENT
WHERE STUDENT_TYPE = 'SC0001' `
let query =
`SELECT
FROM STUDENT
WHERE STUDENT_TYPE = '${STUDENT_TYPE.ELEMENTARY_SCHOOL}' `
위의 처음 코드와 아래의 바뀐 코드를 살펴보자!
위의 코드는 SC0001이 의미하는 바를 DB에 들어가서 봐야지만 알 수 있었다.
하지만 아래의 코드는 어떤가?!
바로 "아 초등학생을 조회하는 쿼리구나" 하고 알 수 있다!
그리고 STUDENT_TYPE.ELEMENTARY_SCHOOL = SC0001 이기 때문에
기존의 common_code 구조를 바꾸지 않고 가독성만 향상할 수 있었다.
이런 식으로 javascript 객체를 통해 Enum을 사용하니
가독성이 좋아졌다.
그리고 그에 따라 업무 효율도 늘어났다.
꽤나 만족스러운 도입이었다!!
🐳 Enum 도입 후기
우리 회사는 NestJS를 사용하는 프로젝트와 ExpressJS를 사용하는 프로젝트로 나뉜다.
백엔드 모듈 회의에 들어가 NestJS 코드를 보면서 ExpressJS에도 비슷한 방법을 도입할 수 있지 않을까라는 생각을 했고
가장 먼저 Enum을 도입하기로 마음먹었다.
문제를 만났을 때 문제 해결을 위해 새로운 기술을 도입하는 것도 좋지만
기존의 기술의 새로운 활용을 통해 해결하는 것도 좋은 방법이라고 생각했기 때문이다.
Enum 타입을 도입한 것이 엄청난 일은 아니지만
ExpressJS에 도입을 했다는 점
그리고 회사 내에서 2년간 아무도 시도하지 않았던 일을 시도했다는 점에서
나를 칭찬해 주고 싶다.
( 하지만 이 Enum 객체가 사용되는 일은 없었다. 이후 모든 프로젝트는 NestJS로 진행되었기 때문에... )
🐳 추가 후기 ( 오픈 카톡방 피드백 )
어느 분야든 나누고 서로 피드백을 주고받을 때 실력이 느는 게 아니겠는가?!
NestJS 오픈 카톡방에 위에 작성한 글을 공유했고 피드백을 받았다!
응애 개발자들을 위해서 다들 많은 피드백을 주셨다.
그중에서도 지적해 주신 부분은 MySQL의 enum 타입을 사용하는 게 좋지 않다는 것이었다!
🐳 DB Column에 enum 사용하지 않기
enum column을 사용할 경우 당연하게도 데이터 일관성을 유지하기 좋다! 내가 지정한 데이터 외에는 넣을 수 없으니 말이다.
그런데 왜 DB column에 enum을 사용하면 좋지 않을까?
변화에 유연하지 못하다.
현재 사이드 프로젝트로 진행하는 아내를 위한 출석부를 예로 들어 보자! ( NestJS와 MySQL을 사용 중이다 )
학생들의 출석 상태는 출석 / 결석 / 지각 총 세 가지의 상태이다.
그래서 MySQL DB에 status를 enum('출석', '결석', '지각')으로 저장했다고 해보자!
이 상태에서 지각이라는 명칭을 늦출이라는 명칭으로 수정한다고 해보자.
그러면 아래와 같은 단계를 거쳐야 한다.
1. enum('출석', '결석', '지각', '늦출')로 enum을 변경한다.
2. NestJS 서버에서 DTO를 수정한다. ( 지각 -> 늦출 )
3. DB에서 지각 -> 늦출 로 수정한다.
4. enum('출석', '결석', '늦출')로 column을 수정한다.
새로운 상태 보강을 추가해 보자!
1. enum에 새로운 타입 보강을 추가한다.
2. 코드레벨에서 enum 타입에 보강 데이터를 추가한다.
두 경우 모두 간단해 보일 수도 있지만 문제점은 DB와 함께 코드도 수정해야 한다는 문제점이 발생한다.
이로 인해 DB와 코드의 상태가 같은 상태인지 확인하고 관리해야 한다는 문제가 발생한다.
그리고 이런 문제점은 필연적으로 실수를 발생시키기 쉬운 구조가 된다!
그렇다면 어떻게 해결할 수 있을까?
enum column을 새로운 Table로 분리하는 것이다!
그리고 enum column 자리에 새로운 Table에 외래키로 설정해 주면 될 것이다.
![]() |
![]() |
왼쪽처럼 ENUM 타입으로 존재하던 status를 Record_Status 테이블로 정규화하고 Record 테이블은 FK로 recordStatusId를 가지도록 했다.
그러면 ENUM과 반대로 이렇게 정규화하면 어떤 장점이 있을까?
🐳 정규화의 장점
위의 예시처럼 테이블을 분리하게 되면 어떤 장점이 있을까?
enum의 단점을 설명할 때처럼 지각 -> 늦출 로 명칭을 수정한다고 해보자.
정규화한 후에는 어떻게 하면 될까?
아래 표를 Record_Status 테이블이라고 생각해 보자
id | name |
1 | 출석 |
2 | 지각 -> 늦출 |
3 | 결석 |
위의 예처럼 Record_Status의 지각 데이터의 이름을 늦출로 바꿔주면 끝이다 !
다른 수정사항은 필요 없다 !
그리고 이 상태에서 새로운 데이터를 추가한다고 생각해 보자
그냥 Record_Status Table에 새로운 데이터를 추가해주기만 한다면 끝이다!
그리고 Record를 생성할 대는 recordStatusId에 새로운 id값을 파라미터로 보내주기만 하면 된다.
너무 쉽지 않은가?
🐳 그렇다면 DB의 enum column은 무조건 사용하지 않는 것이 좋을까 ?
은탄환은 없다는 말처럼 세상에 모든 문제를 해결하는 방법은 없다.
공학도라면 장단점을 파악하고 현재 필요한 상황에 맞는 알맞은 기술을 사용해야 할 것이다.
가급적 DB Column에 Enum 타입은 사용하지 말자 !
대신에 DTO와 DAO 등을 통해서 DB자체에 들어가는 값들을 통제해 주는 것이 좋을 것이다.
DB Column에도 Enum을 지정하게 되면 변화에 대응하기 어렵기 때문이다.
변하지 않는 것은 "변하지 않는 것은 없다 !"라는 사실 뿐이다 !
사용자의 요구가 빈번하게 변화하는 곳에는 정규화를 사용하자!
그렇기 사용자의 요구가 자주 변하는 곳에는 정규화를 통해 데이터를 관리하는 것이 좋을 것이다.
하지만 이는 이 글의 처음 상황처럼 DB와 코드를 같이 읽어야 하는 가독성 문제가 발생할 수 있다.
그럴 때 처음 문제의 해결법처럼 Enum을 value를 정규화한 테이블의 PK 값으로 사용하는 방법을 사용해 볼 수 있을 것 같다.
각각의 장점을 생각해 적재적소에 Enum과 정규화를 잘 활용해 보자!
🐳 후기
처음 javascript에서 enum을 사용하는 방법에 관해 글을 쓰고 나서는 이 글이 굉장히 잘 쓴 글인 줄 알았다.
하지만 오픈카톡을 통해 사람들의 의견과 피드백을 통해
Enum이 만능이 아니라는 것 장단점이 있고 각각을 잘 활용해야 한다는 것을 알게 됐다.
역시 사람은 공유를 통해 더 발전하는 것 같다!
'Node.js' 카테고리의 다른 글
[PrismaORM] upsert 사용 시 Unique constraint failed on the fields 문제 해결 (0) | 2024.08.23 |
---|---|
TypeORM v0.3에서 Repository 구현 및 테스트 코드 구현 (0) | 2023.07.08 |
Typescript로 Jest 사용하기 (0) | 2023.07.06 |
Layered Architecture 구현하기 (0) | 2023.07.05 |
TypeORM + TypeScript + Express 개발환경 세팅 (0) | 2023.07.03 |