Back to notes
    회고작성 · 2026-08-11

    그때 조금 더 우겼어야 했을까?

    아키텍처 단순화에서 구현 비용만큼 검증 비용이 중요한 이유.

    목차

    부메랑을 기획할 때 계약서 OCR 처리 구조로 처음 고려했던 것은 Redis 기반 Worker였다.

    각 계약서의 업로드와 OCR 처리를 독립적인 Job으로 만들고 Worker에서 처리하면 작업 상태를 분리해서 관리할 수 있고 여러 문서를 병렬로 처리하기도 쉬웠다. 이후 OCR 작업이 늘어나더라도 Worker를 추가하는 방식으로 확장할 수 있다는 장점도 있었다.

    문제는 개발 시간이었다.

    실제 구현 시간은 약 30시간의 해커톤 현장이 전부였다. Redis와 Worker까지 도입하는 것은 현재 규모에 비해 오버엔지니어링이라는 의견이 있었고, 나 역시 충분히 타당한 지적이라고 생각했다.

    결국 Redis Worker 대신 Thread 기반 병렬 처리를 사용하기로 했다.


    우리가 예상했던 사용자 흐름

    부메랑은 STT가 진행되는 동안 사용자가 계약 관련 문서를 미리 올릴 수 있도록 기획했다.

    예상했던 처리 흐름은 다음과 같았다.

    부동산 계약은 보통 수십 분 동안 진행된다.

    따라서 사용자가 대화하고 있는 동안 계약서 업로드와 OCR 처리를 같이 수행하면 계약이 종료될 시점에는 LLM 분석에 필요한 대부분의 데이터가 이미 준비되어 있을 것이라고 판단했다.

    계약 종료 후에는 LLM 분석 정도만 수행하면 되기 때문에 약 1분 수준에서 결과를 제공할 수 있을 것으로 예상했다.

    실제로는 모든 작업이 계약이 끝난 뒤 시작됐다

    해커톤 당일에는 구현 시간이 부족했고 Thread 기반 처리 구조를 충분히 테스트하지 못했다.

    최종적으로 실제 서비스에서 동작한 흐름은 예상과 달랐다.

    병렬 실행을 전제로 했던 작업이 사실상 직렬화되었다.

    문서 하나의 처리가 끝나야 다음 문서가 처리되는 구조가 되어 계약이 끝난 이후에 모든 대기 시간이 그대로 사용자에게 노출됐다.

    S3 업로드도 별도의 대용량 전송 구조 없이 기본적인 데이터 흐름으로 구현되어 있었기 때문에 업로드 시간까지 병목에 포함됐다.

    결과적으로 약 1분 정도로 예상했던 최종 결과 생성 시간이 경우에 따라 10분 가까이 걸렸다.


    Redis Worker를 사용했어야 했을까?

    프로젝트가 끝난 직후에는 처음 생각했던 Redis Worker 구조를 더 강하게 주장했어야 하는 것이 아니었을까 생각했다.

    하지만 다시 돌아보면 문제의 핵심은 Redis를 사용했느냐가 아니었다.

    Thread 기반 구조로도 우리가 원했던 사용자 경험을 구현할 수 있었다.

    문제는 서비스 응답 시간을 결정하는 핵심 가정이었던 병렬 처리를 실제 환경에서 검증하지 않았다는 것이었다.

    아키텍처를 Redis Worker에서 Thread로 단순화했다면 최소한 다음 부분은 우선적으로 확인했어야 했다.

    • 여러 OCR Job이 실제로 동시에 실행되는가
    • 한 작업이 Blocking되었을 때 다른 작업은 계속 수행되는가
    • 각 Job의 완료 시점은 어떻게 확인하는가
    • 실패한 OCR이 전체 분석 흐름에 어떤 영향을 주는가
    • 계약 종료 시 아직 처리되지 않은 Job은 어떻게 기다릴 것인가
    • S3 업로드 자체가 전체 흐름의 병목은 아닌가

    우리는 구현 비용을 줄였지만, 단순화한 구조가 실제로 의도대로 동작하는지를 확인하는 검증 비용을 고려하지 못했다.

    오버엔지니어링의 반대가 항상 단순한 구현은 아니다

    이 경험 전에는 짧은 프로젝트에서 복잡한 구조를 도입하지 않는 것이 좋은 기술 선택이라고 생각하는 경향이 있었다.

    물론 여전히 불필요한 시스템을 추가하는 것은 피해야 한다고 생각한다.

    하지만 어떤 구조가 복잡해 보인다는 이유만으로 제거하는 것 역시 항상 좋은 결정은 아니었다.

    중요한 것은 그 구조가 어떤 문제를 해결하기 위해 존재하는가였다.

    부메랑에서 병렬 OCR은 단순한 최적화가 아니었다.

    계약이 끝난 뒤 사용자가 얼마나 기다려야 하는지를 결정하는 핵심 사용자 경험이었다.

    따라서 Worker를 사용할지 Thread를 사용할지는 두 번째 문제였다. 첫 번째로 확인해야 했던 것은 우리가 선택한 방법으로 계약 중 문서 처리가 실제로 병렬 실행되는지였다.

    구현 비용뿐 아니라 검증 비용까지 계산하기

    해커톤에서는 기능을 얼마나 빨리 구현할 수 있는지를 계속 계산하게 된다.

    하지만 이번 경험에서는 구현 속도만으로 기술의 비용을 계산하면 안 된다는 것을 배웠다.

    Thread 기반 병렬 처리는 Redis Worker보다 코드와 인프라가 적게 필요했다. 하지만 동시성 문제를 확인하고 실제 실행 순서를 추적하려면 충분한 로그와 디버깅, 테스트가 필요했다.

    구현 비용은 낮췄지만 그 선택을 검증할 시간을 확보하지 못한다면 결과적으로 더 위험한 구조가 될 수도 있었다.

    이후 기술을 선택할 때는 다음 네 가지를 함께 보려고 한다.

    사용자에게 주는 가치 × 제한된 시간 안에서의 구현 가능성 × 실패했을 때 핵심 플로우에 미치는 영향 × 구현 이후 검증에 필요한 비용

    부메랑에서 Live STT는 이 기준으로 비교했을 때 성공적인 선택에 가까웠다.

    반대로 OCR 병렬 처리에서는 구현 난이도를 낮추는 판단은 했지만, 변경된 구조를 검증하기 위한 비용을 충분히 확보하지 못했다.

    Redis Worker를 포기한 것 자체가 실패였다고 생각하지는 않는다.

    오히려 이 경험에서 가장 크게 남은 것은 아키텍처를 단순화했다면 그 단순화가 유지해야 할 핵심 가정부터 먼저 검증해야 한다는 것이었다.