시스템은 복잡한 내부 흐름을 가진다. 하나의 사용자 요청에 대해 여러 단계의 처리가 순차적 또는 병렬적으로 진행된다. 아키텍처(Architecture)는 시스템 구성 요소들의 상호작용 방식과 실행 순서를 규정한다.
에이전트 기반일 경우, 더 복잡한 구조가 된다. 에이전트가 작업 계획을 수립하고, 계획에 따라 텍스트 요약 모델, 분류 모델, 외부 API 등을 호출하며, 외부 도구와 연동하여 연속적으로 작업을 수행한다. 이 과정에서 실행 상태를 추적하고, 중간 결과를 저장하며, 오류 발생 시 이전 단계로 복구할 수 있는 메커니즘이 필요하다.
호출
병렬 처리와 비동기 호출은 응답 시간을 단축하고 자원 효율성을 높인다.
- 병렬 처리 : 독립적인 작업들을 동시에 실행하는 방식으로 작업 간 의존성이 없을 때 효과적이다. 예를 들어 번역 요청 시 문법 검사와 용어 검증을 동시에 수행하면 처리 시간을 절반으로 줄일 수 있다.
- 비동기 호출 : 외부 API나 데이터베이스 조회처럼 응답을 기다리는 동안 시스템이 다른 작업을 수행할 수 있게 한다. 고객 문의 처리에서 상담 이력을 조회하는 동시에 FAQ 검색을 진행하는 식이다.
이러한 방식은 CPU나 GPU가 연속적으로 여러 작업을 동시에 처리하게 하여 하드웨어 활용률을 높이고, 사용자 측면에서도 응답성을 개선하며 서비스 안정성을 높인다.
흐름 설계
시스템 아키텍처는 크게 세 가지 관점에서 설계된다.
- 실행 순서 설계 : 사용자 요청부터 최종 응답까지의 전체 흐름을 정의한다. 문서 요약의 경우 '원문 분할 → 프롬프트 전달 → 결과 수신 → 출력’과 같은 단계별 역할과 순서를 정의한다.
- 조건부 흐름 설계 : 요청의 길이나 유형에 따라 실행 경로를 다르게 설정한다. 특정 키워드 포함 시 흐름을 전환하거나, 여러 모델을 호출해 가장 신뢰도 높은 결과를 선택하는 병렬 실행 및 오류 복구 경로를 포함한다.
- 안정성 및 재사용성 설계 : 세션 관리, 상태 관리, 컨텍스트 관리(Redis/DB 활용)를 통해 오류 발생 시 상태를 복원하고 중간 결과를 재활용할 수 있게 한다.
마이크로서비스 아키텍처
시스템은 하나의 시스템(Monolith)으로 구성하기보다 여러 독립적인 서비스로 분해하는 마이크로서비스 아키텍처(MSA, Microservice Architecture)를 적용하는 것이 효율적이다.
- 독립적 개발 및 배포 : 자연어 이해, 의도 분류, 지식 검색, 응답 생성 등으로 서비스를 분리하여 각 기능을 독립적으로 개발하고 배포할 수 있다.
- 확장성 : 특정 기능에 요청이 급증하면 해당 서비스만 추가 배포하여 처리 용량을 늘릴 수 있다.
- 최적화된 기술 스택 : 자연어 처리에는 Python을, 실시간 데이터 처리에는 Go를 사용하는 등 각 서비스의 특성에 가장 적합한 도구를 선택할 수 있다.
다만 서비스 간 통신 복잡성과 관리 부담이 증가하므로 서비스 분할의 적절한 수준을 결정하는 것이 중요하다.