AI 상담을 Claude API 직접 호출로 전환하고 FAQ 주입
목차
외부 서비스를 끼고 쓰던 AI 상담을 Claude API 직접 호출로 바꿨다. 작업 규모 자체는 크지 않았는데, 바꾸고 나서 생각보다 달라진 게 많아서 정리해둔다.
외부 래퍼 서비스를 쓰던 이유는 처음엔 단순했다. 빠르게 붙이고 싶었고, 직접 API 관리 부담을 줄이고 싶었다. 근데 시간이 지나면서 문제가 쌓이기 시작했다. 프롬프트를 세밀하게 제어하고 싶어도 중간 레이어가 가로막고, 레이턴시는 외부 서비스 사정에 따라 들쭉날쭉하고, 뭔가 이상하게 나와도 디버깅하기가 애매했다. 결국 직접 붙이는 게 낫겠다 싶어서 전환했다.
구조는 단순하게 잡았다.
사용자 질문
→ 내부 클래스 (API 호출)
→ Claude API (messages endpoint)
→ 응답 파싱
→ 채팅 UI 렌더링
중간 레이어가 없어지니 레이턴시가 눈에 띄게 줄었고, 응답 포맷이나 시스템 프롬프트를 원하는 대로 바꿀 수 있게 됐다. API 버전 고정도 직접 관리하니까 외부 서비스가 내부적으로 모델을 교체했는데 우리만 모르는 상황도 없어졌다.
FAQ 주입 방식
직접 호출로 바꾼 가장 큰 이득 중 하나가 시스템 프롬프트 제어였다. 여기에 FAQ 목록을 주입해서 자주 묻는 질문에 일관된 답변이 나오게 했다. FAQ를 DB나 파일에서 로드해서 매 요청 시 시스템 프롬프트에 붙여넣는 구조다.
이 방식을 쓸 때 주의할 점이 있다.
- FAQ가 너무 길면 컨텍스트 윈도우를 낭비하고 응답 품질이 오히려 떨어진다. 50개짜리 FAQ를 통째로 넣는 것보다 카테고리 분류해서 관련 항목만 선택적으로 주입하는 게 낫다.
- FAQ 항목이 서로 충돌하면 모델이 둘 사이에서 어중간한 답을 내기도 한다. 주입 전에 중복/충돌 검증 로직을 거치는 게 좋다.
- FAQ 업데이트 주기와 캐싱 전략을 같이 생각해야 한다. 매 요청마다 DB를 읽으면 불필요한 쿼리가 늘어난다.
AI 상담사 이름과 역할 소개 문구도 이번에 같이 정리했다. 처음 접속 시 "뭘 물어봐도 되는지" 안내가 있어야 사용자가 어색하지 않게 쓸 수 있다. 이건 UX 얘기지만, 시스템 프롬프트에서 페르소나를 잘 잡아두면 안내 문구와 실제 응답 톤이 일치하게 만들기 쉬워진다.
보안 처리: 경고-정지-블랙리스트 자동화
AI 상담을 붙이면서 보안 레이어도 같이 손봤다.
| 단계 | 동작 |
|---|---|
| 로그인 체크 | 비로그인 요청 즉시 차단 |
| 경고 | 부적절 요청 감지 시 경고 메시지 노출, DB 카운트 증가 |
| 정지 | 누적 경고 임계치 초과 시 30분 접근 정지 |
| 블랙리스트 | 반복 공격 감지 시 자동 등록 및 즉시 차단 |
경고와 정지 횟수를 DB에 저장하는 건 나중에 패턴 분석하거나 수동 검토할 때도 쓰인다. 그냥 메모리에 들고 있으면 서버 재시작 때 초기화되니까 영속성 있게 저장하는 게 맞다.
블랙리스트 자동 등록은 실시간 대응 속도를 올리려고 넣었는데, 몇 가지 트레이드오프가 있다. 오탐 가능성이 있어서 로드 테스트나 배치 작업이 봇으로 오해받지 않도록 예외 처리가 필요하다. 영구 차단보다는 TTL을 설정해서 오탐 복구 경로를 남겨두는 쪽이 운영 편하다. 자동 차단이 발생하면 슬랙이나 디스코드로 알림이 가게 연동해두면, 새벽에 튀는 요청도 다음날 아침에 놓치지 않고 확인할 수 있다.
돌아보면, 이번 작업에서 실제로 시간이 걸린 건 API 전환 코드 자체가 아니라 "얼마나 엄격하게 차단할 것인가" 기준을 정하는 부분이었다. 너무 느슨하면 어뷰징이 쌓이고, 너무 타이트하면 정상 사용자를 막는다. 지금 기준이 맞는지는 운영하면서 데이터 보고 조정해야 한다. 작업 규모는 작았지만, 이런 기준 설정이 실제 운영 안정성에 직결되는 부분이라 고민이 더 길었던 것 같다.
댓글 0
첫 댓글 달아줘.