안정적으로 통화가 연결된 경우만 초 단위로 비용 정산하기
엔코르의 핵심 기능은 영상·음성 통화입니다. 스트리밍은 Agora 를 써서 어려움이 없었지만, 정산 파이프라인은 직접 만들어야 하는 과제였습니다. 모바일은 통신 상태가 나빠지는 일이 잦은 만큼, 정상적으로 이루어진 시간만 정산해야 했고, 초 단위 청구까지 요구되었습니다.
먼저 '안정적인 통화'가 무엇인지 정해야 합니다. 이는 서버와 클라이언트가 주고받는 핑으로 정의했습니다. 어느 한 참여자라도 핑이 3번 누락되면 연결에 문제가 있다고 판단하고 정산을 중단합니다. 7번 누락되면 통화가 끊어졌다고 판단하고 세션을 종료하게 만들었습니다.
다음 문제는 매초 정산이라는 요구사항입니다. 처음에는 전체 통화 시간에서 불안정했던 시간을 빼고, 통화가 끝난 뒤 데이터베이스를 한 번 업데이트할 생각이었습니다. 그런데, 요구사항이 생각 이상으로 복잡했습니다. 통화 중에 캐시(앱 안의 재화, '클랩')를 충전할 수 있어야 했고, 충전한 캐시로 서로 선물도 할 수 있으며, 통화 가능 시간이 20초 미만으로 줄면 통화가 곧 끝난다고도 알려줘야 합니다. 충전, 소비, 조회가 모두 실시간으로 이뤄져야 하므로 남은 캐시를 읽기 쓰기가 가벼운 어딘가에 저장하고 처리하는 게 간단하겠다고 판단했습니다.
통화가 시작되면 발신자 캐시를 수정할 수 없게 만듭니다. 현재 캐시를 읽어 Redis 의 통화 세션에 복제해두면 이 값이 발신자가 쓸 수 있는 캐시의 원본이 됩니다. 매초 이 값을 줄여 정산하고, 충전이나 선물이 발생하면 이 값을 계속 업데이트합니다. 충전은 결제 기록을 남겨야 하므로 DB 에 추가로 남깁니다. 남은 통화 시간도 이 값을 바탕으로 계산해 클라이언트에 내려줍니다. 통화가 끝나면 DB 에 남은 잔액을 업데이트합니다. 충전·선물을 빼면 통화 한 건의 DB 조작은 시작과 끝 두 번뿐이라, 복잡한 로직을 직관적으로 구현할 수 있었습니다.