인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

wnsqud70님의 프로필 이미지

작성한 질문수

실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기 (Java 프로젝트 리팩토링)

23강. Boolean에도 Enum 활용하기 - 책 반납 로직 수정

enum질문

작성

·

40

1

안녕하세요 선생님

enum에 관해서 질문이 있는데 enum을 Intger로 바꿔서 저정하는 경우도 현업에서 많이 봤는데

혹시 선생님은 어느쪽을 선호하시나요??

각자 장단점이 있는건 인지하고 있고 선생님의 선호하는 방향이 궁금합니다!

감사합니다

답변 1

0

최태현님의 프로필 이미지
최태현
지식공유자

안녕하세요! wnsqud70님! 🙂 좋은 질문 감사합니다.

 

결론부터 말씀드리면 저는 Enum타입을 문자열 varchar에 매핑하는 것을 매우 선호합니다.

 

그 이유는 말씀해주신 것처럼 enum의 ordinal을 (즉 정수를) DB에 매핑할 수도 있지만, 그렇게 되면 두 가지 단점이 있는데요

 

  1. Enum의 순서를 편하게 바꿀 수 없다.

개발 과정에서, 그리고 운영을 하다보면 Enum값은 쉽게 늘어나고 줄어들 수 있습니다. 이런 경우에 ordinal을 DB에 매핑하게 된다면 제가 임의로 바꾼 순서 때문에 정말 큰 일이 날 수도 있어요

예를 들어 상태가 A, C, D만 존재했는데

enum class XXStatus {
  A,
  C,
  D
}

이제 B가 추가된다고 해보겠습니다. 비즈니스 흐름상 당연히 B가 A와 C 사이에 위치해야 하기 때문에 A, B, C, D 순서로 Enum을 배치하게 되면.. 문자열인 경우에는 문제가 전혀 없지만,

숫자를 사용하고 있었다면 A = 0, C = 1, D = 2 에서 A = 0, B = 1, C= 2, D = 2로 바뀌게 되며 DB에 들어 있던 1값과 2 값의 의미가 완전히 달라져 데이터가 틀어지게 됩니다.

가장 큰 문제는 이런 위험요소가 어떠한 컴파일타임 혹은 런타임의 인지 방법 없이 발생할 수 있다는거에요

 

  1. 운영 상의 어려움

또 하나의 문제는 운영상의 어려움인데요, 상태가 5개, 10개를 넘어가게 되면 운영 대응을 해야 할 때 숫자 7이 무슨 상태인제 12는 또 어떤 상태인지 모두 기억하기는 무척 어렵습니다. 만약 문자열로 DB에 저장되어 있었다면 이런 불필요한 변환을 줄이고 조금 더 효율적인 운영 대응이 가능합니다.

 

저는 이런 두 가지 이유로 문자열을 조금 더 선호하는 편입니다. 답변이 도움이 되었으면 좋겠습니다. 감사합니다. 🙇

wnsqud70님의 프로필 이미지
wnsqud70
질문자

enum class ApplicationStatus(
    val applicationStatusName: String,
    val number: Int,
) {
    ACCEPTED("신청", 0),
    CANCELED("취소", 1);

    companion object {
        fun toApplicationStatus(number: Int): ApplicationStatus {
            return entries.first { it.number == number }
        }

        fun toInt(status: ApplicationStatus): Int {
            return status.number
        }
    }

}

저는 보통 이런식으로 짜는데 이럴 경우에는 1번문제는 해결될것 같고 Db저장 크기나 이런데서 이점을 볼것같은데... 가독성은 어쩔수 없겠군요..

최태현님의 프로필 이미지
최태현
지식공유자

중간에 변환을 해주는 쪽으로 생각해주셨군요! 잘 아시겠지만 Converter까지 사용하면 직접 변환해줄 필요 없이 EnumType그대로 저장, 사용하는 것처럼 보입니다.

저 역시 (0, 1, 2, 3처럼 들어 있거나 A, B, C,D 처럼 들어 있는...) 레거시 테이블을 매핑해야 할 때 비슷한 기법을 사용하는 편입니다.

 

말씀해주신 것처럼 Enum을 저장하게 되면 이득을 볼 수 있는데요..!

  • tinyint는 1바이트

  • 문자는 평균 10글자 * 알파벳 (1byte) + varchar (1byte) = 11바이트

한 row당 10byte 정도 이득을 볼 수 있다고 하면, 데이터가 1억건 들어갔을 때 약 1GB 정도 디스크 저장 공간 차이가 발생합니다.

개인적으로는 핵심 테이블이 아니라면 1억건씩 데이터를 쌓을 일이 국내 서비스에서는 그렇게 많지 않기도 하고, 1GB에 대한 비용 절감보다는 DB에 붙어 직접 작업해야 하는 리소스 혹은 새로운 분들께 기존 도메인을 이해시키는 리소스가 더 크다고 생각해서 말씀드린 것을 장점으로 생각하고 있습니다! 🙇

감사합니다.

wnsqud70님의 프로필 이미지

작성한 질문수

질문하기