분석 결과는 평가 원본에서 만들어지지만, 두 데이터를 같은 것으로 보기는 어려웠습니다. 특히 분석 수식이 아직 검토 중이라면 원본은 유지하면서 결과를 다시 계산할 수 있어야 했습니다.
Phenokeyoh의 인지평가 백엔드를 개발하면서 평가 원본과 분석 결과를 분리해 저장했습니다. 처음에는 비동기 분석을 처리하기 위한 구조였지만, 연구와 제품 개발을 함께 진행하는 과정에서도 이 분리가 필요했습니다.
분석 결과가 아직 확정되지 않은 상태
인지평가가 제출되면 사용자가 수행한 문항과 반응에 대한 원본 데이터가 만들어집니다. 제품에서는 이 원본에 수식을 적용해 지표와 분석 결과를 제공해야 했습니다.
하지만 당시에는 분석 수식이 완전히 확정된 상태가 아니었습니다. 연구원이 실제 평가 결과를 확인하면서 수식이 의도한 값을 만드는지 검토해야 했고, 검토 과정에서 계산 방식이 달라질 가능성도 있었습니다.
분석 수식이 확정될 때까지 제품 개발을 미룰 수는 없었습니다. 현재의 수식으로 결과를 제공하면서도, 이후 수식이 달라졌을 때 같은 평가를 다시 분석할 수 있는 구조가 필요했습니다.
평가 원본과 분석 결과를 나누어 저장하기
평가 원본은 사용자가 실제로 수행한 기록이었습니다. 반면 분석 결과는 그 원본에 현재의 수식을 적용해 만들어진 값이었습니다.
두 데이터는 같은 평가에 속하지만 변경되는 이유가 달랐습니다. 평가 원본은 그대로 보존해야 했고, 분석 결과는 연구 과정에서 다시 만들어질 수 있었습니다.
그래서 사용자가 평가를 제출하면 원본 데이터를 먼저 저장했습니다. 저장된 평가의 식별자와 함께 분석 worker를 비동기로 호출하고, 응답이 오면 분석 결과를 별도로 갱신하도록 구성했습니다.
이 구조에서는 분석 방식이 달라져도 평가 원본까지 변경할 필요가 없었습니다. 현재 결과를 확정된 원본처럼 취급하지 않고, 다시 계산할 수 있는 값으로 다룰 수 있었습니다.
연구와 제품이 같은 원본을 사용하는 방법
연구원은 필요할 때 평가 원본을 바탕으로 Python에서 수식을 직접 검토할 수 있었습니다. 제품에서는 같은 원본을 분석 worker에 전달해 사용자에게 보여줄 결과를 만들었습니다.
연구와 제품은 사용하는 도구와 작업 속도가 달랐습니다. 연구에서는 여러 계산 방식을 빠르게 비교할 수 있어야 했고, 제품에서는 정해진 요청을 안정적으로 처리하고 결과를 저장해야 했습니다.
평가 원본을 중심에 두고 분석 결과를 분리하면서 두 흐름이 같은 데이터를 기준으로 움직일 수 있었습니다. 연구 과정에서 수식이 달라져도 사용자가 평가를 다시 수행하도록 요청할 필요 없이 기존 원본으로 결과를 다시 확인할 수 있었습니다.
실패 이후에도 다시 분석할 수 있게 하기
분석 worker는 별도의 시스템으로 동작했기 때문에 호출이 항상 성공한다고 가정하기 어려웠습니다. 원본을 먼저 저장해두면 분석이 실패하더라도 사용자가 제출한 평가까지 잃지는 않았습니다.
어드민에서는 분석 실패 여부를 확인할 수 있게 했습니다. 운영자가 특정 평가를 직접 선택해 재분석을 실행할 수도 있었습니다.
이 재분석 기능은 실패한 작업을 복구할 때만 사용되는 것은 아니었습니다. 연구원의 검토를 거쳐 수식이 변경됐을 때도 같은 원본으로 결과를 다시 계산하는 데 사용할 수 있었습니다.
재분석은 실패한 작업을 다시 실행하는 기능이면서, 확정되지 않은 분석 수식을 실제 데이터로 검토하기 위한 기능이기도 했습니다.
모든 분석 기준이 확정된 뒤에만 제품을 만들 수 있는 것은 아니었습니다. 연구와 제품 개발이 함께 진행되는 경우에는 현재의 분석 결과가 이후에도 그대로 유지될 것이라고 가정하기 어려웠습니다.
- 다시 얻기 어려운 평가 원본
- 수식에 따라 달라질 수 있는 분석 결과
- 분석의 성공과 실패 상태
- 운영자가 다시 처리할 수 있는 재분석 기능
평가 원본과 분석 결과를 분리한 것은 저장 구조만의 문제가 아니었습니다. 연구원이 분석 방법을 검토하는 과정과 제품이 결과를 제공하는 과정을 함께 이어가기 위한 선택에 가까웠습니다.
분석 로직이 바뀔 가능성을 없애기보다, 바뀌더라도 같은 원본에서 다시 시작할 수 있게 만드는 편이 연구 단계의 불확실성을 제품 안에서 다루는 데 도움이 됐습니다.