[좌충우돌 개발기] Golang 에서 enum 자료형 사용후기

이번 글에서는 Golang enum 사용후기와 개선점에 대해서 이야기 하겠습니다.

정의

In computer programming, an enumerated type (also called enumeration, enum, or factor in the R programming language, and a categorical variable in statistics) is a data type consisting of a set of named values called elements, members, enumeral, or enumerators of the type. The enumerator names are usually identifiers that behave as constants in the language.

위키피디아에서는 enum 자료형식별성을 갖는 상수로 정의하고 있습니다.

Golang 에서 enum을 사용하기

Effective Go에는 enumConstants로 정의 한 후 iota라는 enumerator를 제공합니다. iota를 통해 값을 할당받은 변수들은 행이 바뀔때 차례로 증가 하고 정수로써 다루어 집니다.

1
2
3
4
5
6
7
8
9
10
11
12
type ByteSize float64
const (
    _           = iota // ignore first value by assigning to blank identifier
    KB ByteSize = 1 << (10 * iota)
    MB
    GB
    TB
    PB
    EB
    ZB
    YB
)

문자열로 표현된 enum을 사용하고 싶다!

  • 지정된 값만 사용하기
  • 의미를 알 수 있도록 선언하기
  • 타입으로 유효성을 검사하기

이러한 이유 때문에 const로 선언된 변수에 문자열을 할당하고 싶었습니다.

1
2
3
4
5
6
type Status string
const(
    Shipment = "Shipment"
    Receipt = "Receipt"
    ...
)

하지만 이렇게 하면 지정되지 않은 값을 사용해도 에러가 발생하지 않습니다. 왜냐하면 할당된 값이 특정타입을 나타내지 않는 string이기 때문입니다.  이러한 문제를 보완하기 위해서 Type에 값을 할당 할 수 있습니다.

1
2
3
4
5
6
type Status string
const (
  Shipment = Status("S")
  Receipt = Status("R")
  ...
)

이렇게 하면 지정되지 않은 값을 사용 할 때 IDEA에서 미리 지정된 상수 인지 알 수 있습니다.

Screen Shot 2020-04-11 at 4.42.51 PM

한가지 기능이 더 필요한데..

  • 배민의 블로그를 보면 상태와 행위를 함께 관리 하는 방법이 나옵니다.
  • Aggregate Root에 관한 글데이터의 무결성을 위해 Repository를 Aggregate Root로 제한하는 방법이 나와 있습니다.

이러한 글들을 읽고 enum을 적극적으로 활용해 보고 싶었습니다. 이런 관점으로  지난 글수불 시스템을 살펴보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type Delivery struct {
    Id                  int64           `json:id`
    WaybillNo           string          `json:waybillNo`
    BoxNo               string          `json:boxNo`
    ShipmentLocationId  int64           `json:shipmentLocationId`
    ReceiptLocationId  int64            `json:receiptLocationId`
    Status              string          `json:status`
    Committed           `xorm:"extends"`
}
type Stock struct {
    Id                  int64           `json:id`
    LocationId          int64           `json:locationId`
    SkuId               int64           `json:skuId`
    Qty                 int64           `jsog:qty`
    Committed           `xorm:"extends"`   
}

사용자 행동에 의해 생성된 데이터는 수불 데이터이고, 그에 영향을 받은 데이터는 재고 수량 입니다. 이 부분에 enum을 할용하여 수불의 상태 마다 재고계산을 하고 싶었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type Status struct {
	Code            string          `json:"code"`
	CalculateStock  func(locationId, skuId, qty int64) error
}
const (
  Shipment = Status{
        Code: "S",
        CalculateStock: func(shipmentLocationId, skuId, qty int64) error {
            ...
        }
  }
  Receipt = Status{
      Code: "R",
      CalculateStock: func(receiptLocationId, skuId, qty int64) error {
            ...
      }
  }
)

하지만 이렇게 하면 IDEA 에서 에러가 발생 합니다.

struct 형으로 const 선언 못함

Screen Shot 2020-04-02 at 11.59.55 PM

동료의 리뷰

Java에서는 enum도 독립된 class이기 때문에 상태와 행위를 함께 묶을 수 있습니다. 그런데 Golang을 사용하는 우리 팀은 상태와 행위를 함께 관리 하기위해 임시방편으로 var를 사용했었고 코드 리뷰를 통해 오사용을 방지 하고 있습니다. 그렇지만 변경될 여지가 있어서 2% 부족 합니다.  이런 한계점을 해결하기 위해서 Golang 커뮤니티에서도 enum이 필요하다는 제안이 있었습니다. 빠른 시일내에 반영되었으면 좋겠습니다.


Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.