Swift Enum의 활용 (구조체 또는 클래스 대신 열거형으로 정리해봐요)

Enum은 특정한 이름을 정의하고 값 대신에 사용하는 기능으로 아래와 같이 사용하는 경우가 많습니다.

Enum Coffee  {
    case Macchiato
    case Espresso
}

Enum에 대해 공부하고 있는데요. 그 중에 실전에서 활용하면 좋은 몇가지를 나누어서 소개해 드리려고 합니다.

 

구조체 또는 클래스 대신 열거형으로

예를 들어 채팅 앱을 만드는 상황이라고 가정하고

채팅 메시지에 대한 구조체를 아래와 같이 정의 해보았습니다.

struct Message {
    let userId: String
    let contents: String?
    let date: Date

    let hasJoined: Bool
    let hasLeft: Bool

    let isBeingDrafted: Bool
    let isSendingBalloons: Bool
}

 

그리고 해당 구조체에 대한 인스턴스를 생성 하였습니다.

let message = Message(userId: "1", contents: "안녕하세요", date: Date(), hasJoined: true, hasLeft: false, isBeingDrafted: false, isSendingBalloons: false)

 

여기서 구조체를 Enum을 활용해서 그룹화 해보겠습니다.

Enum Message {
    case text(userId: String, contents, date: Date)
    case draft(userId: String, date: Date)
    case join(userId: String, date: Date)
    case leave(userId: String, date: Date)
    case balloon(userId: String, date: Date)
}

 

인스턴스 생성

let textMessage = Message.text(userId: "2", contents: "Hello !", date: Date())
let joinMessage = Message.join(userId: "2", date: Date())

 

Bool값으로 메시지에 대한 타입을 구분하는 것이 아니라 Enum을 활용하여 미리 메시지를 그룹화 하여 표현했습니다. 개인적으로 코드가 굉장히 명확해지고 Bool값으로 코드가 지저분해지는 경우도 최소화 된다고 생각합니다.

 

또한 채팅방에서 상황에 따른 알림 메시지를 채팅창에 띄우고자 하는 상황에서도 간단하게 switch문을 이용하여 메시지 타입을 구분하고 알림을 보내주는 함수를 구현할 수 있습니다.

 

logMessage(message: joinMessage) // 유저 두 명이 방에 들어왔습니다.
logMessage(message: textMessage) // 유저 두 명이 메시지를 보냈습니다.

func logMessage(message: Message) -> String {
    switch message {
    case let .text(userId: id, contents: contents, date: date) :
        return "[\(date)] User \(id) sends message: \(contents)"
    case let. draft(userid: id, date: date):
        return "[\(date)] User \(id) is drafting a message"
    case let .join(userId: id, date: date):
        return "[\(date)] User \(id) is has joined the chatroom"
    case let .leave(userId: id, date: date):
        return "[\(date)] User \(id) is left the chatroom"
    case let .balloon(userId: id, date: date):
        return "[\(date)] User \(id) is sending balloons" 
}

 

if 문을 이용해서 단일 처리도 가능 합니다.

if case Message.text(userId: id, contents: contents, date: date) = textMessage {
    // 원하는 처리
}

 

"_" 를 이용해서 유저 아이디와 날짜는 신경 안쓰도록 처리할 수도 있겠습니다.

if case Message.text(userId: _ contents: contents, date: _) = textMessage {
    // 원하는 처리
}

 

정리

작은 예시를 통해서 구조체를 열거형으로 전환하여 데이터 모델링을 해보았습니다.

다만 단일 사례에서 패턴 일치를 자주 발견한다면 구조체나 클래스의 사용이 더 나은 선택이라 생각합니다.

또한 속성에 대한 초기화 처리가 제공되지 않아 수동으로 처리해야 합니다.

이러한 상황들이 존재하지만 데이터 모델링을 하는데 있어 좋은 후보라고 생각이 듭니다.

실전에서 많은 도움이 되었으면 하는 바램에서 정리 해보았습니다.