
이해관계자 관점에서의 시나리오 및 기대효과
이번 문제를 다루기 전에 먼저 이 기능이 어떤 이해관계자에게 어떤 영향을 줄 수 있는지를 상상해봤다.
FastAPI 기반 TTS 기능은 단순 테스트용 기능이 아니라, 향후 AI 상담원, 시각장애인 지원 서비스, 고객 서비스 등 다양한 실사용 서비스에 접목될 수 있는 핵심 기능이다.
그런데 만약 지금처럼 파일명이 고정되어 있고, 클라이언트 캐시 문제가 발생하는 상태로 서비스가 운영된다면 다음과 같은 리스크가 발생할 수 있다.
- 고객 사용자: AI 상담원이 안내하는 음성이 이전 문의 내용으로 반복 재생된다면, 고객은 시스템을 신뢰하지 않게 되고 불편을 겪게 된다.
- 시각장애인 사용자: 잘못된 안내 음성이 반복 재생될 경우 정보 접근성이 심각하게 저하되며, 서비스 신뢰도도 붕괴된다.
- CS 운영팀: 동일 문제에 대한 반복 문의가 발생하고, 기술적 원인 파악과 대응에 과도한 리소스가 낭비된다.
- 외부 파트너사: 서비스 품질 이슈가 발생하면 파트너사와의 협력 관계 신뢰도도 떨어질 수 있다.
따라서 이번 트러블슈팅 과정은 단순히 기술적 오류를 수정하는 것을 넘어,
서비스 품질과 신뢰를 유지하고, 이해관계자의 혼란과 불만을 예방하기 위한 중요한 문제 해결 과정이었다.
문제 현상 요약
FastAPI 기반으로 구현한 Text-To-Speech(TTS) 기능에서 문제가 발생했다.
처음에는 API 호출이 정상적으로 동작하고 200 OK 응답을 주었기 때문에 서버 코드에는 문제가 없다고 판단했다.
하지만 클라이언트에서는 새로운 텍스트를 입력해도 항상 동일한 음성이 재생되었고, 파일 접근 시 404 오류가 발생했다.
서버에서는 mp3 파일이 정상적으로 저장되었음에도 클라이언트에서는 다른 결과가 발생하는 괴리 상황이 혼란을 키웠다.
원인 분석
분석 과정에서 확인한 주요 원인은 다음과 같았다.
- FastAPI에서 정적 파일을 /uploads 경로로 제공했지만, 실제 mp3 파일은 다른 위치에 저장되고 있었음
- mp3 파일명이 openai_tts_output.mp3로 고정되어 있어 클라이언트가 매번 같은 파일을 참조했음
- 클라이언트 브라우저가 이전 파일을 캐시하고 있었음에도 이를 간과하고 서버만 원인으로 의심함
결과적으로 서버 파일 경로 불일치, 클라이언트 캐시, 파일명 고정이라는 세 가지 문제가 동시에 발생한 상황이었다.
이번 과정을 통해 API 응답만으로 정상 동작을 판단하기보다는,
클라이언트 체감 관점, 파일 접근 흐름, 브라우저 캐시까지 포함한 종합적 관점으로 문제를 바라봐야 한다는 점을 새롭게 인식했다.
해결 과정
우선 가장 급했던 서버의 파일 경로 불일치 문제를 먼저 해결했다.
mp3 파일 저장 위치를 FastAPI의 StaticFiles가 바라보는 /uploads 디렉터리로 일치시켰고, 브라우저에서 404 오류는 해소되었다.
클라이언트는 /uploads/openai_tts_output.mp3 파일을 정상적으로 불러올 수 있게 되었지만,
여전히 파일명이 고정되어 있어 캐시 문제나 다중 사용자 충돌 문제는 구조적으로 남아 있다.
이는 특히 외부 고객 대상 서비스에서는 사용자 경험 저하와 서비스 신뢰도 하락으로 이어질 수 있으며,
향후 개선 과제로 UUID 기반 고유 파일명 생성과 캐시 무효화 전략 적용이 반드시 필요하다는 점을 확인했다.
최종 코드
from fastapi import APIRouter, HTTPException, Form
from app.services.tts_service import text_to_speech
import os
router = APIRouter()
# 출력 파일 저장할 uploads 폴더 경로
UPLOAD_DIR = os.path.join(os.path.dirname(__file__), "uploads")
os.makedirs(UPLOAD_DIR, exist_ok=True)
@router.post("/")
async def tts_endpoint(text: str = Form(...)):
try:
file_name = "openai_tts_output.mp3"
output_path = os.path.join(UPLOAD_DIR, file_name)
# 실제 TTS 생성 처리
file_path = text_to_speech(text, output_path) # 내부 저장용 절대경로
# 클라이언트용 웹 경로 반환
return {
"message": "TTS 처리 완료 (OpenAI TTS)",
"file_path": f"/uploads/{file_name}" # 웹 경로만 전달
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
결론 및 회고
이번 트러블슈팅은 코드 디버깅만으로는 해결되지 않는 복합적인 문제였다.
클라이언트, 서버, 파일 시스템, 브라우저 캐시가 서로 영향을 주고받는 복잡한 상황을 실제로 경험하면서, 시스템을 좀 더 전체적으로 바라보는 훈련이 필요하다는 점을 절감했다.
현재 코드는 클라이언트 접근 경로 일치와 404 오류 해소에 그쳤으며, 다중 사용자 환경, 캐시 무효화, 파일명 고유성 확보 등 품질 안정성 확보 측면에서는 여전히 보완이 필요한 상태이다.
향후 AI 상담원, 고객 CS 시스템, 시각장애인 지원 서비스 등 다양한 이해관계자에게 TTS 기능을 제공하는 상황에서는 파일명 정책, 캐시 무효화 전략을 포함한 설계 안정성 확보가 필수라는 점을 이번 경험을 통해 팀 차원에서도 인식하게 되었으며, 이를 기반으로 후속 개선을 적극 추진해야 한다!
'생각정리' 카테고리의 다른 글
AI 시대, 벡터 DB는 어떻게 진화할까? (1) | 2025.05.09 |
---|---|
MSA와 클라우드, AI 서비스에 대한 실용적 혜안 (2) | 2025.04.10 |
저자님께 책 선물을 받았다(이게 바로 성덕..?) (2) | 2025.03.31 |
트러블 슈팅: 딥러닝 모델 서빙(w/FastAPI) (0) | 2025.03.21 |
누군가 내 코드를 베꼈다 (8) | 2024.10.07 |