대규모 모델 추론을 위한 동적 라우팅 웹 게이트웨이 구축

핵심 목표: 성능과 안정성의 균형

본 프로젝트는 대규모 언어 모델의 추론 요청을 처리하는 HTTP 기반 게이트웨이를 2시간 내에 설계 및 구현하는 것을 목표로 했습니다. 핵심 과제는 KV 캐시 재사용률 증가단일 서버 과부하 방지 사이의 동적 균형을 유지하는 것입니다.

요청의 접두사(예: "질문: ")가 동일할 경우, 같은 백엔드 인스턴스로 라우팅하면 이전 계산 결과를 재활용하여 지연 시간을 줄일 수 있습니다. 그러나 모든 동일 접두사 요청이 한 인스턴스에 몰리면 과부하가 발생하고 대기 시간이 급증합니다. 이를 해결하기 위해 실시간 상태 기반의 스마트 라우팅 전략을 도입했습니다.

기술 스택 및 환경

  • 언어: Java 17
  • 프레임워크: Spring Boot 3.2
  • 빌드 시스템: Maven 3.8+
  • HTTP 클라이언트: Spring 6.1+ 내장 RestClient
  • 개발 환경: 온라인 IDE + AI 코드 보조

시스템 아키텍처

클라이언트 요청 → 게이트웨이 진입점 → 접두사 분석 및 라우팅 → 동적 부하 분산 → 백엔드 인스턴스 풀
                 ↓
           실시간 메트릭 수집 (캐시 성공률, 지연, 부하 분포)
  

주요 구성 요소 설계

모듈 구현 방식 설계 목적
접두사 기반 라우팅 정규 표현식 매칭 + 실패 시 폴백 전략 유사한 입력은 동일 인스턴스로 집중시키며, 과부하 시 자동 분산
동적 부하 분산 실시간 가중치 산출 알고리즘 성능과 부하 상태를 반영해 최적 인스턴스 선택
건강 상태 점검 주기적 연결 검사 + 장애 감지 후 자동 제거 장애 인스턴스는 즉시 배제되고 복구 시 재가입
메트릭 통계 슬라이딩 윈도우 기반 실시간 집계 P95 지연, 성공률, KV 캐시 미스율 등 실시간 모니터링

핵심 기술: 동적 가중치 알고리즘

간단한 정적 라우팅은 단일 인스턴스 과부하를 초래할 수 있으므로, 다음과 같은 조합 점수 기반 전략을 적용했습니다:

instance_score = 
  (cache_weight × historical_hit_rate) +
  (load_weight × (1 - current_load_ratio))
  • 가중치 조정 가능: cache_weight, load_weight는 외부 설정 파일에서 수정 가능
  • 과부하 감지: 동시 요청 수가 100 이상일 경우, 캐시 우선 전략의 영향력을 점진적으로 감소
  • 전략 교체 지원: 순환 방식과 비교하여 성능 차이를 직접 측정 가능

실제 압력 테스트 결과

테스트 시나리오 방법 결과
정상 트래픽 랜덤 접두사 동시 요청 캐시 성공률 ~40%, 부하 균형 양호
핫 접두사 80% 요청이 동일 접두사 사용 동적 가중치로 2~3개 인스턴스에 분산, 단일 과부하 방지
과부하 시나리오 단일 인스턴스 동시 요청 120+ 자동으로 가중치 감소, 다른 인스턴스로 전환
장애 주입 백엔드 인스턴스 수동 중지 즉시 제거 및 재시작 시 자동 복귀

코드 품질 관리 전략

단시간 개발에도 불구하고 다음의 공학적 원칙을 준수했습니다:

  • 설정과 코드 분리: 백엔드 목록, 임계값, 전략 파라미터는 application.yml에 분리
  • 예외 처리: 3초 초과 시 다른 인스턴스로 자동 재시도, 전체 실패 시 503 반환
  • 관측성 확보: 요청 수, 성공률, P95 지연, 캐시 효율, 부하 분포 실시간 출력
  • 코드 가독성: 핵심 클래스에 책임 설명 추가, 의존성 주입 사용으로 테스트 용이성 확보

AI 협업 경험

AI를 활용해 2시간 내에 완전한 시스템을 구현하면서 다음과 같은 통찰을 얻었습니다:

성공적인 접근 방법

  • 모듈별 분해: 먼저 라우팅, 부하 분산, 건강 체크 등의 모듈 목록을 작성한 후 각각을 별도로 요청 → 전체 일괄 생성보다 훨씬 안정적
  • 버전 관리 중요성: 첫 번째 버전 이후 디렉터리 구조 변경을 요청했지만, 중간 상태를 저장하지 않아 오류 발생. 이후부터는 매 모듈 완료 시마다 로컬 백업 필수
  • 상황 기억 유지: 대화가 10만 토큰을 넘으면 상세 정보가 사라짐. 필요 시 "이전에 정의한 구조를 기억하고 있나요?"처럼 리셋 명령 수행

주의해야 할 함정

  • 대규모 리팩토링 위험: AI에게 전체 코드를 한번에 변경하라고 하면 의도치 않은 결함 발생 가능성 높음
  • 의존성 충돌: 먼저 pom.xml 생성 후 검증 후 코드 생성 권장
  • 과도한 설계 유도: 간단한 기능에 복잡한 설정을 추가하는 경향 있음 → 항상 "필요한 것만" 강조

핵심 통찰

AI는 개발 속도를 획기적으로 향상시켰지만, 최종 코드 품질의 결정적 요소는 여전히 인간의 판단입니다.
어떤 시점에 분리할지, 예외 처리 경계는 어디인지, 실패 시 어떻게 대응할지 — 이러한 전략적 결정은 AI가 스스로 하지 않습니다.
AI는 실행자이며, 인간은 의사결정자이자 책임자입니다.

향후 개선 방향

  • 스트리밍 응답 지원: 현재는 동기식 전달. WebClientFlux를 활용해 실제 스트리밍 전달 구현
  • 더 정교한 접두사 매칭: 문자열 접두사 기반 근사 매칭 → Trie 트리 도입으로 정확도 향상
  • 분산 메트릭 집계: 현재 메트릭은 메모리 기반. Redis를 사용해 다중 게이트웨이 인스턴스 간 통합 모니터링 가능

결론

이 경험을 통해 다음과 같은 가치를 확인했습니다:

  • 기술적 깊이: 게이트웨이 설계, 부하 분산, 관측성 원칙에 대한 실질적 이해 심화
  • 협업 모델: "모듈화 → 단계적 구현 → 버전 관리 → 피드백 회수"라는 사람-기계 협업 프로세스 정립
  • 인식 변화: AI는 대체하지 않으며, 오히려 사용하는 개발자가 경쟁력 있는 존재가 됩니다. 핵심은 AI의 능력을 최대로 활용하면서도, 인간만이 할 수 있는 전략적 판단과 책임감을 유지하는 것입니다.

    최종적으로 말하고 싶은 것은: AI는 엔지니어를 대체하지 않지만, AI를 활용하는 엔지니어는 그렇지 않은 사람을 대체합니다.

태그: Spring Boot Java 17 Load Balancing KV Cache Dynamic Routing

7월 6일 02:02에 게시됨