본문으로 건너뛰기
뒤로

한곳에서 다음 단계를 정해 본다

초안아직 소유자가 검토하고 실습해 확인하지 않은 글입니다. 학습 기록이 아니라, 확인 전의 글입니다.

읽기 약 5분 · 실습 시간 별도

예약이 성공하면 변환하고, 변환이 끝나면 결과를 저장하고, 마지막에 예약을 확정한다. 이 순서를 하나의 조정 코드에 적으면 전체 업무의 정상 경로를 한곳에서 읽을 수 있다. 참여자들은 자신의 로컬 작업을 수행하고 결과를 돌려준다. 다음 단계를 선택하는 역할을 별도로 두는 것이 오케스트레이션이다.

중앙에서 순서를 관리하고 싶다는 이유는 충분히 검토할 만하다. 특히 승인 대기나 조건 분기, 여러 종류의 실패가 생기면 어느 단계로 진행할지 한곳에서 설명하기 쉽다. 다만 순서가 읽기 쉬워졌다는 사실과 프로세스 중단 뒤 안전하게 이어진다는 사실은 다르다. 간단한 Java 메서드로 순서를 모으는 것만으로 실행 관리가 완성되지는 않는다.

참여자의 책임은 유지한다

오케스트레이터가 예약 DB를 직접 수정할 필요는 없다. 예약 생성·조회·확정·해제는 해당 데이터를 소유한 참여자가 제공한다. 조정자는 그 계약을 호출하고 결과에 따라 다음 작업을 선택한다. 이렇게 구분하지 않으면 조정 서비스가 모든 데이터와 업무 규칙을 소유하게 될 수 있다.

reservation = reserve(requestId)
converted = convert(documentId, revision)
stored = saveResult(requestId, converted.reference)
confirm(reservation.id)

이 코드는 정상 순서만 보여 준다. 변환이 실패하면 예약을 해제할지, 일시 오류이면 얼마나 기다렸다 재시도할지, 저장 후 확정이 실패하면 결과를 공개할지 같은 규칙이 빠져 있다. 코드가 짧다는 이유로 코레오그래피보다 구현이 모두 끝났다고 평가하면 안 된다. 같은 실패 조건까지 넣어서 비교해야 한다.

판단조정자가 아는 것참여자가 지킬 것
변환 시작예약 성공 여부와 다음 단계같은 요청에 대한 예약 중복 방지
저장 재시도실패 분류와 남은 시도 정책중복 저장을 안전하게 처리
예약 해제업무를 더 진행하지 않기로 한 결정현재 예약 상태에 맞는 조건부 해제
완료 표시필요한 단계들이 끝났다는 결과각 로컬 결과의 정확성

조정자는 전체 순서를 알지만 참여자 내부의 모든 구현을 알 필요는 없다. 예를 들어 변환 서비스가 자체 파일 형식 검사를 어떻게 하는지까지 알아야 하는 것은 아니다. 반대로 참여자는 자신의 작업을 성공시킨 뒤 전체 업무가 무조건 완료됐다고 가정하지 않는다. 자기 단계의 성공과 전체 성공이 분리되어 있기 때문이다.

중앙 조정과 단일 프로세스는 같은 뜻이 아니다

오케스트레이션의 중앙성은 논리적 제어 흐름에 관한 말이다. 물리적인 실행은 여러 프로세스에서 나눠 맡을 수 있고 상태를 영속 저장할 수도 있다. 여러 인스턴스가 동일한 업무를 중복 처리하지 않도록 소유권과 재실행 규칙을 설계해야 하지만, 중앙 조정을 선택했다는 이유만으로 서버 하나에 모든 실행을 몰아야 하는 것은 아니다.

물론 조정자와 상태 저장소가 모두 멈추면 업무 진행이 중단될 수 있다. 그래서 가용성은 별도로 검증한다. 코레오그래피도 브로커와 참여자의 장애 영향을 받는다. 비교할 것은 ‘중앙이 있으니 위험하다’와 ‘분산됐으니 안전하다’라는 구호가 아니라, 어떤 구성요소가 멈추면 무엇이 기다리고 어떻게 복구되는지다. AWS의 오케스트레이션 설명은 조정 책임의 집중과 함께 장애·멱등성 등의 고려 사항을 다룬다.

통신 방식도 별도 선택이다. 조정자가 HTTP로 명령할 수도 있고 메시지로 명령과 응답을 주고받을 수도 있다. 이벤트 브로커가 있다는 이유로 반드시 코레오그래피인 것은 아니다. 핵심은 다음 업무 단계를 누가 결정하느냐다. Temporal을 공부할 때도 메시징 제품과 대립시키기보다 실행 순서와 복구 책임 중 무엇을 맡기는지 살펴봐야 한다.

같은 변환 실패로 비교한다

앞 글의 코레오그래피판에서 사용한 예약·변환·저장 함수를 유지한다. 바꾸는 것은 다음 단계를 정하는 코드다. 변환 함수가 동일한 오류를 발생시키게 하고 조정자가 예약 해제를 요청하게 만든다. 업무 식별자와 참여자의 최종 상태도 같게 유지해야 비교가 의미 있다. 여기서는 아직 실험을 실행하지 않았으며 정상·실패 결과는 직접 확인할 예정이다.

  1. 조정자가 예약 API를 호출하고 결과를 받는다.
  2. 변환에서 처리 불가능한 오류를 발생시킨다.
  3. 조정자가 예약 해제를 호출한다.
  4. 예약 원장, 조정자의 최종 상태, 실패를 추적할 때 읽은 코드 위치를 기록한다.

예상되는 차이는 실패 뒤 해제를 결정하는 코드가 조정자에 있다는 점이다. 참여자 내부의 원자성이나 해제의 멱등성이 자동으로 좋아지는 것은 아니다. 조정자가 해제를 요청했는데 응답을 받지 못하면 해제 결과를 모르는 상태도 여전히 생긴다. 그 상태에서 무작정 처음부터 실행하면 중복 효과를 만들 수 있다.

선택의 기준은 코드 줄 수보다 변경과 장애를 설명하는 데 필요한 책임이다. 승인 대기 하나를 추가할 때 어떤 계약이 바뀌는지, 중단된 업무의 현재 단계를 어디서 찾는지, 보상 실패를 누가 식별하는지 비교해 보자. 이런 요구가 커질 때 영속적인 실행 관리 도구를 검토할 이유가 생긴다.

이해 확인

오케스트레이터가 존재하면 예약 DB의 규칙도 그 안으로 옮겨야 할까? 여러 조정 프로세스를 배포했다고 같은 업무를 안전하게 이어 갈 수 있는 것은 아니라면, 별도로 저장하고 조정해야 할 정보는 무엇일까?

참고 자료



댓글