Bracket Pattern

구경회·2021년 1월 2일
3
post-thumbnail
post-custom-banner

자원을 다루는 법

파일 입출력, 네트워크 소켓 등 자원을 다룰 때 그 자원을 해제해주는 것은 매우 중요하다. 하지만 코드는 녹이 슬고, 사람들은 실수를 한다. 그래서 많은 디자인 패턴이 이 방법을 강제하기 위해 노력한다.

java에서 파일을 열고, 닫는 등 어떤 자원을 가지고 하는 행동을 다루는 일반적인 패턴은 다음과 같다.

위 예시 코드는 코드의 실행이 끝난 후 자동으로 close를 해 준다. 많은 보일러플레이트를 줄일 수 있다.

Rust, C++등은 RAII 패턴을 제시한다. 사실 Java로 작성한 위의 코드도 일종의 RAII 패턴이라고 볼 수 있다. RustC++RAII가 bracket pattern보다 좀 더 나은 대안이라는 주장도 있다.

아무튼, 위와 비슷한 일을 하기 위해 scala같은 함수형 프로그래밍 언어들은 bracket pattern을 도입한다. 이에 대해 살펴보자.

Bracket Pattern

생명주기는 두 개의 action으로 이루어진다. 각각 acquire, release로 불린다. 앞선 액션 acquire가 실행된 후에 realease가 실행됨이 보장되어 있다. 취소나 에러가 발생했을 경우에도 말이다.

Cats-Effect

MonadCancel

MonadCancel은 취소가 가능한 모나드이다. MonadError를 상속받아 그 성질들을 이용할 수 있다. cats-effect-3에서는 따로 bracket을 구현하지 않고 여러 타입 클래스의 메소드로 구현되어 있다. MonadCancel은 다음과 같이 bracket을 구현한다.

둘 다 bracketFull에 의존하는 구현임을 확인할 수 있다. 이제 bracketFull을 보자.

우선 safeRelease라는 취소할 수 없는 release를 만든 후, 순차적으로 적용하는 것을 확인할 수 있다. 오류가 발생했을 때에는 Outcome.Succeeded대신 Outcome.Errored로 주는 것도 확인할 수 있다.

bracketCasebracketFull을 사용하지 않고 다음과 같이 구현할 수도 있다.

참고한 글

profile
즐기는 거야
post-custom-banner

0개의 댓글