5.0 KiB
enum / constants 기준
목적
고정된 의미 집합은 문자열/정수 상수 남발 대신 enum으로 표현한다.
상수는 단순히 static final인 값이 아니라, 실제로 변경 불가능하고 의미가 분명한 값으로 관리한다.
공식 의미
- enum은 미리 정의된 상수 집합을 표현하는 특별한 클래스다.
- 각 enum constant는 해당 enum 타입의 고유 인스턴스다.
- enum은 필드, 메서드, 생성자를 가질 수 있다.
ordinal()은 대부분의 개발자가 사용할 용도가 아니며EnumSet,EnumMap같은 저수준 구조를 위한 값이다.name()은 선언된 정확한 이름을 반환한다.toString()은 더 사람이 읽기 좋은 문자열이 필요할 때만 재정의한다.- enum key/set에는
EnumMap,EnumSet같은 특화 구현을 우선 검토한다.
기본 규칙
1. 고정된 값 집합이면 enum 우선
다음과 같은 경우는 enum을 우선 검토한다.
- 상태
- provider 종류
- 역할 종류
- 모드
- 정책 선택지
- 결과 코드의 제한된 집합
금지 예:
"LOCAL","GOOGLE","KAKAO"같은 문자열 분기1,2,3같은 매직 넘버 상태값 분기
2. 값 집합이 열려 있으면 enum을 쓰지 않는다
외부 시스템이 임의 값을 추가할 수 있거나, 런타임에 확장 가능한 값이면 enum보다 다른 모델을 검토한다.
예:
- 자유 입력 태그
- 외부 설정으로 계속 늘어나는 코드값
- tenant별 커스텀 상태
3. ordinal() 의존 금지
다음 용도로 ordinal()을 사용하지 않는다.
- DB 저장값
- 외부 API/JSON 값
- 비즈니스 분기
- 배열 인덱스 계약
- stable code/wire number
안정적인 숫자/문자 코드가 필요하면 enum 필드로 명시한다.
4. name()은 내부 안정 식별자, 사용자 표시값은 별도 필드/메서드
- 내부 고정 식별이 필요하면
name() - 사용자에게 보이는 문자열은 별도 필드나 메서드
- API/DB/wire 값도 별도 필드로 분리
즉:
- internal name
- display label
- external code 를 섞지 않는다.
5. toString()은 신중하게
공식 문서상 toString()은 필요하면 더 programmer-friendly 한 문자열로 재정의할 수 있다.
하지만 프로젝트에서는 다음 기준을 따른다.
- 로깅/디버깅/개발자용 표현만 바꿀 때 제한적으로 허용
- 외부 계약, JSON, DB 저장값을
toString()에 의존하지 않는다 - 외부 계약값은 명시적 getter/field를 사용한다
6. enum 비교는 enum끼리 직접 비교
동일 enum 타입 비교는 enum 값 자체로 직접 비교한다.
비즈니스 의미 비교를 위해 문자열로 변환해서 비교하지 않는다.
금지 예:
status.name().equals("ACTIVE")provider.toString().equals(input)
7. enum set/map은 EnumSet / EnumMap 우선 검토
enum을 key/set element로 사용할 때는 다음을 우선 검토한다.
- 집합 ->
EnumSet - 맵 ->
EnumMap
비트 플래그용 int나 일반 HashSet/HashMap을 습관적으로 쓰지 않는다.
8. switch/분기는 enum 의미 중심으로 작성
enum 분기는 문자열/정수 코드가 아니라 enum 값 자체를 기준으로 작성한다.
또한:
- default로 조용히 삼키지 않는다
- 새로운 enum 값 추가 시 분기 누락이 드러나도록 작성한다
9. 상수는 진짜 immutable일 때만 상수로 취급
상수는 다음을 만족해야 한다.
static final- 값 자체가 immutable
- 내부 원소도 변경으로 의미가 흔들리지 않음
즉:
- mutable collection
- mutable object reference
- 변경 가능한 배열 은 상수처럼 다루지 않는다.
10. 관련 상수는 “상수 클래스”보다 소유 타입 근처에 둔다
다음 순서를 우선한다.
- enum으로 승격 가능한 값이면 enum
- 특정 클래스 책임이면 해당 클래스 내부 상수
- 여러 모듈에 걸친 진짜 전역 상수만 별도 위치
의미 없는 Constants, CommonConstants, AppConstants 집합소는 기본 금지다.
11. null enum 기본 금지
enum 값은 가능한 한 non-null로 다룬다. 부재 표현이 필요하면:
- Optional 반환
- nullable boundary 입력
- 명시적
UNKNOWN/UNSPECIFIED도입 여부를 신중히 검토
단, UNKNOWN이 실제 비즈니스 상태가 아닐 경우 null 회피용으로 남용하지 않는다.
12. persistence / serialization 계약은 별도 기준을 따른다
enum을 DB나 JSON에 노출할 때는 language 차원 기본 동작에 기대지 않고,
- 어떤 값을 저장/전송할지
- 호환성을 어떻게 유지할지 를 명시적 기준으로 정의한다.
프로젝트 기준 요약
- 고정된 의미 집합은 enum 우선
- 열린 값 집합은 enum 지양
ordinal()의존 금지- internal name / display label / external code 분리
- enum set/map은
EnumSet/EnumMap우선 - mutable 값은 상수처럼 다루지 않음
- 잡다한 constants class 기본 금지