개발을 하다보면 코드표를 사용하여 값을 처리해야하는 경우가 있다. 이 경우 enum 클래스를 사용하곤 한다. Spring boot - kotlin에서 이를 구현하자.
1. enum class 만들기 (feat. complie constant, 컴파일 상수)
포트원의 은행 코드표를 예시로 사용한다.
https://faq.portone.io/1dae5145-1feb-4ef2-87ef-4b0e8a984945
가상계좌 은행코드표
포트원을 통해 확인가능한 은행명 & 코드
faq.portone.io
enum class BankCode( val bankCode: String, ) {
BANKCODE("020") // 우리은행
}
그 뒤 @Service에 enum을 사용하여 이름을 부여하고자한다.
@Service(BankCode.BANKCODE)
...
이 경우 @Service에서 컴파일 에러가 발생한다. String형이 필요한데 BankCode 형태가 전달됐다는 이유다.
BankCode.BANKCODE.bankcode를 하면 해결될 줄 알았는데 이번엔 다른 컴파일 에러가 발생한다.
an annotation argument must be a compile-time constant
Kotlin에서는 애노테이션의 인자로 컴파일 타임 상수만 허용한다. 하지만 BankCode.JYNAME.code는 런타임에서 결정되는 값이므로 컴파일 타임 상수(constant expression) 가 아니어서 에러가 발생한다.
이를 해결하려면 다음과 같은 방법을 사용할 수 있다.
enum class BankCode(val bankcode: String) {
BANKCODE("020");
companion object {
const val BANK_CODE = "020"
}
}
@Service(BANKCODE.BANK_CODE)
class MyService
...
왜 저런 코드가 나오는지에 대해서도 이해를 해보자
2. ENUM 이해해보기
주석을 달아보면 이렇다.
enum class BankCode(val bankcode: String) {
BANKCODE("020"); // (1) Enum 생성자의 파라미터로 "020" 전달
companion object {
const val BANK_CODE = "020" // (2) const val을 사용함으로써, 컴파일 타입 상수로 "020" 선언
}
}
2-1. 그러면 enum에 왜 생성자의 파라미터를 전달해야하는 것인가?
생성자가 없을 경우 enum 클래스는 아래 같은 모습이 된다.
enum class BankCode {
WOORI,
SHINHAN,
HANA
}
위처럼 생성자 없이 선언하면 JYNAME, KIMCODE, PARKCODE 같은 이름만 가질 수 있다.
이렇게 하면 각 Enum 값에 추가 정보("020", "010" ...)를 넣을 방법이 없다.
2-2. companion object만 관리하면 안되나요
enum class BankCode(val bankcode: String) {
companion object {
const val BANK_CODE = "020"
}
}
enum class 내부에는 최소 하나 이상의 Enum 값이 필요하다.
하지만 위 코드는 Enum 값이 하나도 없기 때문에 컴파일 에러가 발생한다.
companion object는 Enum 내부에서 정적(Constant) 데이터를 관리하는 용도로 사용될 수 있지만,
Enum 값 없이 단독으로 존재할 수는 없다.
3. enum을 안 쓰고 object를 사용하기
만약 Enum 값이 필요 없다면 Enum을 사용할 필요가 없다.
대신 object 또는 companion object를 활용하면 된다.
object BankCode {
const val BANK_CODE = "020"
}
이제 Enum이 필요 없으므로, object를 사용해 정적인 데이터를 관리할 수 있다.
BankCode.BANK_CODE로 접근 가능하다.
4. 그럼 그냥 object쓰면 되는 거 아니야? object와 Enum은 무슨 차이가 있지?
포스팅하면서 많이 찾아봤는데 진짜 솔직히 모르겠다. enum은 when을 쓸 수 있다는 것 정도...
이런 object와 enum이 있다고 할 때 enum은 when을 사용할 수 있다.
이 부분에 대해서는 코틀린 공식문서를 좀 더 읽어봐야겠다.
https://tistory-pencilcase.tistory.com/358
enum클래스와 생성자 https://tistory-pencilcase.tistory.com/422