QA가 얘기했다.
"썼다 바로 지웠는데 결과가 나오고 있어요."
기술 책임이 얘기했다.
"너무 많이 호출되는 것 같아요."
기획자가 얘기했다.
"마지막에 호출이 한 차례 더 있는 것 같아요."
순식간에 프로젝트 채팅방은 실시간 요청에 대한 로직을 도마 위에 올려놓고 각자 자신이 상상한 칼로 썰어대고 있었다. 모두가 슈퍼바이저가 된 것 같았다. 음, 저들의 말은 모두 정답이 아니면서 또한 정답이었다. 애초에 엉성한 논리와 여러 욕구가 섞여버린 기획이었기에 각자의 눈에 그 교집합에서 터져 나오는 논리적 모순이 잘못된 것으로 보였을 것이다.
'그래. 처음부터 내가 교통정리를 했어야 했어. 내 잘못이다.'
로직을 올린 내 입장에선 어쨌건 모순을 해결해서 모두의 바람(?)을 만족시키는 ‘관대한’ 로직으로 변화시키고 싶었다. 정돈된 로드맵은 없을지언정 내 로직에 부족한 부분이 보인다는 것이 완벽주의적 성격에 아마 참을 수 없었을 것이다. 큰 스트레스가 느껴졌지만 요구를 각각 파악해서 하나씩 해결해 보기로 했다. 1대 다수로 싸워도 한 놈씩 조지다(?) 보면 체력이 다하거나 어디 한 군데 부러지지 않는 한 이길 가능성이 생기지 않겠는가?!
일단 QA의 얘기를 통해 로직을 보완할 부분을 생각해봤다. 가장 간단한 해결책은 '썼다 바로 지웠는데'라는 유저 행위 패턴에서 발생하는 이전/이후 변수 할당 값을 조합해 해당 경우에는 api 호출을 하지 않는 방법이 생각났다. 하지만 이내 머릿속에서 지웠다. 조건부 리턴은 앞서 한 차례 얘기했던 ad-hoc 가설이기 때문이다. 결과적으로 나의 논리가 틀렸음을 인정하는 예외 가설을 추가하는 일은 아주 바쁘거나, 혹은 도저히 그 해답을 알 수 없을 때 임시적(실은 영원히 지워지지 않을 TODO로 남는)으로 올려놓을 용도로서 사용해야 한다.
대신 해결책으로 요청 비동기 라이브러리의 interceptor를 사용하기로 했다. http 요청 단계별로 인풋 컴포넌트에 바인딩된 입력값의 상태를 확인하며 실시간으로 중간에 입력값이 지워졌을 시 그 요청 자체를 취소하거나, 혹은 요청이 이미 서버로 갔다가 들어왔다면 그 값을 abort(반영하지 않는) 하도록 했다. 비동기적으로 감시자를 세워 행위를 관찰하며 문제가 발생 시 이를 처리하도록 하는 방식은 문제를 해결하기에 충분했다(라고 생각했으나 또 모르지, 스트레스 테스트를 하다 보면 필시 예외가 발생할 것이다. 인간은 신이 아니지 않은가?!).
다음은 기술 책임이 제기한 문제를 살펴봤다. 일단 모호한 '너무 많이'라는 용어의 정의를 요청했다. 기획자와 기술 책임의 얘기가 오갔고 결과적으로 입력값 50자를 기준으로 1초/3초 동안 입력이 정지됐을 때 요청을 보내도록 하자는 결론이 나왔다.
'기존 언어 감지 + 300ms마다 유사 번역 호출+ 900ms마다 기계번역 호출’
기존 방식은 내가 생각해도 그 비용이 너무 비쌌다. 게다가 네트워크가 느린 환경에서는 전혀 ‘실시간’의 느낌이 안 날 것이기 때문에. 하지만 역설적으로 ‘너무 많은’ 요청을 줄이면 결국 ‘실시간’의 느낌이 사라지는 결과로 수렴하기 때문에 그 또한 별로라 생각됐다. 하지만 별수 있겠는가! 까라면 깐다. 솔루션으로 유저 입력에 바인딩된 메서드 호출부에 정의된 시간의 디바운스(debounce)를 붙여 번역 호출이 입력의 마지막에 붙도록 제어했다. 언어 감지에는 50자 기준으로 500ms/1초의 쓰로틀(throttle)을 붙여 유의미한 길이의 입력에서 언어를 확인하도록 했다. 추가로 세 종류의 비동기 요청 간에 충돌이 발생하지 않도록 상호 보완적 선후관계를 확인하는 로직을 만들어 요청들의 validation 프록시로 삼았다. 이 요구는 상대적으로 명확해 문제가 정확히 해결되었다. 추후 UX 팀에서 복사/붙여넣기 할 때 너무 한참 쉬고 호출 대기 UI가 나타나는 것 아닌가 라는 뒷북을 보내시길래 필살기, “기획입니다”를 시전 해주었다.
마지막으로 기획자의 요구를 확인했다. 불필요해 보이는 추가 호출이 보인다는 것인데 이는 자연치유가 됐다. 앞선 솔루션들을 적용하며 자연스레 논리적 모순이 없어진 것이다. 다행이라 생각했다. 실시간으로 수정 요구사항을 반영하는 일은 생각보다 많은 체력이 요구되는 일이었다.
로직을 배포한 이후 추가로 문제가 안 보였느냐? 안보였다면 거짓말이다. 완벽하다고 생각했던 논리 체계의 빈틈을 파고드는 유저의 행동은 인간의 다양성만큼 많았기에 어쩔 수 없이 나의 부족함을 인정할 수밖에 없었다. 하지만 물리학의 역사를 보면 날 위로해 줄 사실들이 굉장히 많다. 광속 영역에서 로렌츠 팩터로 인해 허무하게 무너지는 뉴턴 역학이라던지, 양자 영역에서 입자가 확률론적인 파동으로 변하며 완벽하게 무너지는 상대성이론이 그러했다. 그렇다. 이 엄청난 물리학의 거인들인 '뉴턴'과 '아인슈타인'의 논리도 모든 영역에서 다 들어맞진 않았단 말이다. 그들 역시 신은 아니었다. 나 역시 그렇다(그렇지만 정신 승리임을 또한 인정한다). 부족함을 인지하고 있기 때문에 이후에 조금 더 허점이 줄어든 논리를 세울 수 있지 않을까 하는 기대를 가져본다.