"Gregor Hohpe의 횡성수설"이라는 글 모음 중 하나를 번역했습니다. 소프트웨어 설계에 대한 훌륭한 통찰(insight)를 일상생활을 통해 얻을 수 있다는 깨달음을 주는 훌륭한 글입니다. 데이터베이스 관련 기술을 이야기 하고 있지만, 동기/비동기 처리 방식을 왜 구분하고, 어떻게 써야 하는지에 이해하는데 도움이 됩니다.
원문 사이트 : Starbucks Does Not Use Two-Phase Commit
스타벅스는 2단계 커밋을 사용하지 않는다.
Hotto Cocoa o Kudasai (ホットココアください, Hot Cocoa, please, 핫 코코아 주세요.)
방금 2주간의 일본 출장을 마치고 돌아왔습니다. 출장 중에서 접한 익숙한 광경 중 하나는 신주쿠와 록본기 주변의 말도 안될만큼 많은 스타벅스 커피숖들이었습니다. 주문한 "핫 코코아"를 기다리면서 스타벅스가 어떻게 음료 주문을 처리하는지를 가만히 생각해보기로 했습니다. 스타벅스는 대부분의 다른 기업들처럼 주문 처리량을 극대화하는데 매우 큰 관심을 가지고 있습니다. 많은 주문은 많은 수익을 의미하죠. 결과적으로 그들은 비동기 처리 방식(asynchronous processing)을 사용합니다. 당신이 주문을 하면, 점원은 커피 한잔의 주문을 입력하고 대기열(queue)에 추가합니다. 대기열 혹은 큐(queue)는 문자 그대로 에스프레소 기계의 상단에 늘어서 쌓여 있는 빈 커피 컵들을 의미합니다. 이 대기열은 점원과 바리스타를 분리시키고 바리스타(barista)가 잠시 동안 숨을 돌리거나 반대로 매우 바쁜 경우에도 점원이 주문을 계속 받을 수 있도록 해줍니다. 이런 방식은 카페가 바쁜 시간에 다수의 바리스타들을 "경쟁적인 처리자(Competing Consumer)" 시나리오대로 움직이게끔 합니다.
상관 관계 (Correlation)
비동기 일처리 방식의 잇점을 선택함으로써 스타벅스는 비동기 방식이 근본적으로 가지고 있는 문제를 다룰 수 밖에 없게 됩니다. 예를 들자면, 상관관계입니다. 음료 주문은 2가지 이유 때문에 반드시 주문한 순서대로 처리해야 할 필요가 없습니다. 첫째, 바리스타들이 서로 다른 도구를 이용해 음료를 만든다는 점입니다. (드립 커피용 도구와 에스프레소 머신 등등) 또, 혼합 음료(blended drink)는 드립(drip) 커피 보다는 만드는데 시간이 더 걸립니다. 둘째, 바리스타들은 처리 시간을 최적화한 일괄(batch) 작업을 통해 한번에 여러가지 음료들을 만들 수 있습니다. 결과적으로 스타벅스는 상관관계라는 문제를 안고 있는 것입니다. 음료는 주문 순서에 상관없이 만들어지겠지만, 그것을 주문한 고객에게 정확히 전달 되어야 합니다. 스타벅스는 이러한 문제를 메시징 아키텍쳐(messaging architectures)에서 사용하는 상관관계 식별자(Correlation Identifier) 패턴으로 해결하고 있습니다. 대다수의 미국 스타벅스 매장에서는 명확한 상관관계 식별자인 고객의 이름을 컵에 쓰고, 커피가 완성되면 컵에 적힌 고객의 이름을 부릅니다. 다른 나라들에서는 음료의 종류를 이용해 상관 관계를 식별합니다.
예외 처리 (Exception Handling)
비동기 메시지 시나리오(asynchronous messaging scenario)에서 예외 처리는 어려운 문제입니다. 현실 세계에서 예외(문제)를 처리하는 최적의 사례를 살펴보려면 스타벅스가 문제를 해결하는 방식을 관찰해 보면 됩니다. 만일 당신이 마치 지갑을 깜박 잊고 있었다면, 스타벅스의 점원들은 어떻게 대응할까요? 이미 음료를 만들었다면 치워 버릴 것이고, 아직 만들기 전이라면 주문 목록(대기열 혹은 큐)에서 제외할 것입니다. 만일, 당신이 주문한 음료를 마음에 들어하지 않거나 주문하지 않은 음료를 내놓았을 경우에는 음료를 다시 만들어 낼 것입니다. 만일 커피 머신이 고장나서 주문한 커피를 제공할 수 없다면, 환불해 줄 것입니다. 각각의 시나리오는 제각기 다른 상황이지만, 일반적인 오류 처리 전략(error handling strategy)에 대해 설명하고 있습니다.
가격 인하 혹은 취소 (Write-off) - 다양한 오류 처리 전략 중에서 가장 단순한 것입니다 : 아무 것도 하지 않거나, 이미 벌어진 일을 취소하는 것입니다. 썩 좋아 보이지는 않지만 실전 비즈니스에서는 그럭저럭 수용할만한 선택입니다. 손실이 작을 경우, 제대로 일처리하기 위해 오류 정정 시스템을 구축하는 것이 오히려 더 많은 비용을 지출하는 것일 수도 있습니다. 예를 들자면, 제가 컨설팅을 수행했던 여러 ISP(Internet Service Provider)사업자들은 과금(billing) 및 프로비저닝(provisioning) 싸이클(cycle)에서 발생하는 에러를 이런 방식으로 처리했습니다. 결과적으로, 고객은 비용을 청구받지 않고 서비스를 누리게 되는 것입니다. 이런 방식을 도입할지라도 수익 상의 손실은 사업을 유지하는데 있어 지장이 없을 만큼 작았습니다. 주기적으로, "무료(free)" 계정을 찾아 정리하기 위한 "조정 보고서"를 작성하는 작업을 수행하고, "무임승차"한 고객들을 처분합니다.
재시도 (Retry) - ("트랜잭션"이라고 부르는) 큰 작업 그룹을 실행하는 중에 오류가 발생했을 때, 우리는 기본적으로 두 가지를 선택할 수 있습니다. 이미 수행된 작업을 취소하는 것 혹은 실패한 작업들을 재시도하는 것입니다. 재시도가 현실적으로 성공할 가능성이 있다면 그럴싸한 선택입니다. 예를 들어 비즈니스 규칙을 위반한 것이라면, 재시도는 성공할 수 없을 것입니다. 그렇지만, 외부 시스템이 일시적으로 응답하지 않는 상황이라면 재시도는 성공할 가능성이 있습니다.
단, 특별한 경우는 멱등 수신기(Idempotent Receiver : 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 가진 경우)입니다. 이러한 경우는 성공한 수신 처리 이후에 반복되는 메시지는 모두 무시되기 때문에, 간단히 모든 작업을 다시 시도할 수 있습니다.
보상 처리(Compensating Action) - 마지막 옵션은 일관성 있는 상태로 시스템을 돌려놓기 위해 이미 수행된 작업을 취소하는 것입니다. 통화(금융) 시스템을 다루는 경우 이러한 "보상 처리""는 잘 작동하는데, 인출된 돈을 "얼마든지" 재입금할 수 있기 때문입니다.
이러한 전략들은 분리된 준비와 실행 절차에 의해 동작하는 "2단계 커밋(2 phase commit)"과는 다릅니다. 스타벅스의 사례에 접목해보면, "2단계 커밋"은 점원(cashier)이 커피가 완성될 때까지 한 고객만을 바라보며 영수증과 돈을 테이블 위에 올려놓고 기다리는 것과 같습니다. 마지막으로 음료가 준비되면, 영수증과 돈으로 일거에 교환하는 것입니다. 이런 상황에서는 점원뿐만 아니라 고객까지도 "트랜잭션(거래)"이 끝날 때 까지 자리를 떠날 수 없게 됩니다. 이러한 "2단계 커밋" 방식을 적용하게 되면 일정 시간에 서비스 할 수 있는 고객 수는 극적으로 감소할 것이고, 스타벅스의 비즈니스를 확실하게 망하게 만들 것입니다. 이것은 2단계 커밋이 일상을 좀 더 단순하게 만들 수는 있지만, 메시지들의 자유로운 흐름을 방해하게 된다(그리고 확장성을 해친다)는 사실을 일깨워 주는 사례입니다. 왜냐하면, 비동기의 다중 작업 흐름 속에서 트랜잭션의 상태를 관리해야 하기 때문입니다.
대화 (Conversations)
커피숖 상호작용 사례는 간단하면서 일반적으로 대화 패턴(Conversations pattern)입니다.
두 그룹(고객과 커피숖)간의 상호작용은 짧은 동기 상호작용(주문과 지불)들과 하나의 긴 비동기 상호작용 (음료 만들기와 받기)로 구성됩니다. 이러한 대화(혹은 작동방식)는 구매 시나리오에는 매우 일반적인 것입니다. 예를 들어, 아마존(Amazon) 인터넷 쇼핑몰에서 주문할 경우, 주문 번호 발행과 그에 따른 처리 절차(신용카드 지불 요청, 포장, 발송) 등은 짧은 동기적 상호작용이지만, 전체 흐름은 비동기적으로 처리됩니다. 추가적인 단계들이 처리될 때마다 (비동기적으로) 이메일을 통해 통보 받을 수 있습니다. 만일 어떤 것이라도 잘못 처리되는 것이 있다면 아마존은 보상(신용카드 결제를 취소하는 등)하거나, 재처리(분실된 물품을 다시 배송하는 등)를 해줄 것입니다.
요약하면 실제 세계에서 벌어지는 일들은 대게 비동기적으로 동작한다는 것을 알 수 있습니다. 우리의 일상생활은 조화롭지만 비동기적인 상호작용(이메일을 읽고 쓰는 것, 커피를 사는 것 등등)들로 이루어져 있습니다. 이것이 의미하는 바는 비동기적인 메시지 아키텍쳐가 이러한 상호작용을 수행하는데 있어서 가장 자연스러운 방식이라는 것입니다. 또한 우리는 일상적인 생활 속에서 성공적인 메시징 솔루션을 설계할 수 있는 아이디어를 얻게 된 것입니다. 도모 아리가또 고자이마스. (Domo arigato gozaimasu! 감사합니다.)
참고 : 호토 코코아를 검색하면 , 일본 애니메이션 "호토 코코아"가 나오는 군요.