[Monad] 사용 예제 - Option : 존재하지 않음을 표현하기

모나드는 많은 방식으로 사용되지만, 그중에서 Option 타입부터 설명하도록 하겠다. 그 이유는 Option 타입이 가장 기본적인 모나드이고, 가장 많이 사용되는 모나드이기 때문이다. Option 타입은 Haskell 및 몇몇 언어에서는 Maybe 모나드로 불리고, 언어 대부분에서는 Option 타입이라고 불린다. 이 글에서는 그냥 많이 사용되는 Option 타입이라는 이름을 쓰도록 하겠다.

Option 타입이 해결하고자 하는 문제는 값이 존재하지 않음을 런타임 에러가 발생할 가능성 없이 표현하는 것이다. C++, C#, Java 등 기존의 많은 언어는 값이 존재하지 않음을 표현하기 위해서, null point를 사용하였다. 그리고 이 null point 문제는 컴파일 타임에 잡을 수 없는 NullPointerException을 발생시키기 때문에 조심해서 사용해야 했다.

이런 문제를 해결하기 위해 아무런 동작을 하지 않는 객체를 만드는 Null Object pattern 같은 디자인 패턴을 이용하거나, null check를 한 겹 감싼 클래스를 만들거나 해서 문제를 최소화하고 있으나, 여전히 문제를 완벽하게 해결할 수는 없었다. Option 타입은 이에 대한 완벽한 해결책을 제공한다.

Option 타입은 하나의 타입 파라미터를 받아, 그 타입의 값을 가지고 있을 수도 있고, 없을 수도 있다. Int 타입을 타입 파라미터로 받았다면, 타입은 Option[Int]가 되며, String 타입을 타입 파라미터로 받았다면, Option[String]이 된다. 즉, T 타입을 타입 파라미터로 받은 OptionOption[T]가 된다. 이를 간단히 표현하기 위해서 T?같은 방식으로 표현하기도 한다.

Option[T] 타입의 값은 T 타입의 값을 가지고 있을 수도 있고, 아무런 값이 없을 수도 있다. 이렇게 말하면 단순한 nullable과 다를 게 없어 보인다. 하지만 Option은 두 상태를 다른 타입으로 분리함으로써 nullable보다 안전한 방법을 제공한다.

Option 타입은 두 타입의 sum type이다. 하나는 값이 존재하지 않음을 나타내는 None이라는 타입이고, 다른 하나는 무언가 값이 있음을 나타내는 Some이라는 타입이다. sum type을 지원하는 F#, rust, Haskell 같은 언어에서는 이를 sum type으로 표현하고, Scala나 전통적인 객체지향 언어에서는 Option이라는 interface의 구현체로 SomeNone이 있는 것으로 표현한다.

sum type을 표현할 방법이 없어 Scala처럼 상속관계로 표현하였다.

None은 아무런 값도 가지고 있지 않음을 나타내는 타입이다. None 타입의 값에 bind operator를 호출해도 아무 일도 일어나지 않는다. 인자로 넘겨진 함수는 실행되지 않고, bind operator의 결과는 언제나 None이다.

Some 타입은 무언가 값을 가지고 있음을 나타내는 타입이다. 어떤 타입의 값을 가졌는지 나타내기 위해 타입 파라미터를 받는다. T 타입의 값을 가지고 있는 Some 타입은 Some[T]라고 표현한다. Some[T] 타입은 반드시 T 타입의 값을 들고 있어야 한다. Some 타입이면서 내부적으로 값을 들고 있지 않는 상황은 올 수 없다.1) Some 타입은 반드시 값을 가지고 있기 때문에 bind operator는 언제나 NullPointerException 없이 원하는대로 실행된다.


1) Scala는 언어적으로 이것을 금지하지 않는다. 하지만 Somenull을 가지고 있도록 작성한 코드는 잘못된 코드이다. 이런 경우는 반드시 None을 써야 한다.


댓글

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

RAII는 무엇인가

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API