얼쑤의 연주 분석에는 60초 제한이 있습니다. 이 시간은 세션이 PENDING이 된 시각부터 결과를 저장할 수 있는 마감까지 흐릅니다. 실행기에서 대기하는 시간, 녹음 다운로드와 디코딩, 음높이 추정과 채점, DB 쓰기가 모두 같은 예산을 사용합니다. 모델의 처리 시간만 재면 가장 먼저 늦어지는 단계가 어디인지 알 수 없습니다.
한 요청에 걸린 여러 제한
| 시간 제한 | 언제부터 재나 | 만료되면 |
|---|---|---|
| 백엔드의 결과 저장 마감 60초 | DB에 기록한 분석 시도 시작 시각부터 | 늦은 결과는 저장하지 않고, 마감이 지난 PENDING은 상태 조회에서 TIMEOUT으로 처리합니다. |
| 백엔드 HTTP 클라이언트의 읽기 제한 기본 65초 | AI 응답을 읽으면서 다음 응답 데이터를 기다릴 때 | 대기 시간을 넘기면 HTTP 읽기가 실패합니다. |
| 앱의 상태 무응답 제한 70초 | 상태 조회를 시작하거나 재개한 시점부터, 응답을 받으면 그 시점부터 | 앱이 시간 초과 화면을 표시합니다. |
HTTP 연결을 맺는 제한은 별도로 5초였습니다. 읽기 제한을 저장 마감보다 길게 둬, 느린 응답을 클라이언트가 먼저 끊어 서버 오류로 분류하는 경우를 줄이려 했습니다. HTTP 연결이 끊겨도 이미 실행 중인 AI 연산이 취소되는지는 별도의 문제입니다. 앱의 조회 간격과 무응답 경계는 가상 시계로 확인했습니다. 녹음 업로드 202 이후 앱이 기다리는 것
AI 서비스 안에서도 녹음을 받는 단계에는 별도 제한이 있습니다. HTTPX의 읽기 제한은 다음 데이터를 기다리는 동안 적용되므로, 조각이 계속 오면 다운로드 전체 시간이 더 길어질 수 있습니다. 다운로드를 시작할 때 단조 시계로 마감 시각을 잡고, 조각을 받을 때마다 그 시각을 확인했습니다. 검사에서는 이미 지난 마감을 주고 가짜 저장소에서 본문을 받았을 때 다운로드 오류가 발생하는지 확인했습니다. 이 방식은 조각을 기다리는 중간에 별도로 깨우지 않으므로, 마감 확인은 읽기가 돌아온 시점에 이루어집니다.
설정 파일의 30이 30밀리초가 된 이유
분석 제한 시간에 숫자만 적으면 초 단위로 받기로 했습니다. 그런데 당시 Spring Boot 바인더에 문자열 30을 넘기니 PT0.03S, 즉 30밀리초가 나왔습니다. 설정 객체를 Duration.ofSeconds(30)으로 만들어 검사했다면 실제 설정 파일을 읽는 이 과정이 빠졌을 겁니다. 초로 정한 필드에 @DurationUnit(ChronoUnit.SECONDS)를 붙였습니다. 90s처럼 단위를 쓴 값은 명시한 단위를 따릅니다. Spring Boot의 Duration 바인딩 문서
문자열을 바인딩해 결과 비교
| 바인더에 준 입력 | 관찰한 결과 |
|---|---|
분석 제한 30 | 수정 전 30밀리초, 수정 뒤 30초 |
응답 대기 40 | 수정 뒤 40초 |
분석 제한 90s, 응답 대기는 생략 | 계산된 응답 대기 95초 |
응답 대기를 따로 적지 않으면 분석 제한에 5초를 더합니다. 표는 문자열이 설정 객체에 들어갈 때 단위와 두 값의 관계를 확인한 결과입니다. 실제 처리 시간은 아래 실험에서 별도로 확인했습니다.
시작과 마감에 같은 UTC 시계
분석 재시도의 시작 시각과 만료 기준을 서버 UTC로 맞췄습니다. 시작 시각만 테스트용 고정 시계에서 가져오고 만료는 실제 시계로 판단하면, 방금 시작한 시도도 이미 마감이 지난 것으로 볼 수 있습니다.
구성 검사에서는 호출 직전과 직후에 서버의 UTC 시각을 읽었습니다. 재시도에 기록한 시작 시각은 그 사이에 있었고, 제한을 90초로 설정한 검사에서 만료 기준도 같은 방식으로 잰 범위를 90초 앞당긴 구간에 들어왔습니다. 이 범위 검사는 크게 어긋난 시각을 가려냅니다.
별도 HTTP·DB 검사에서 시작 시각은 MySQL의 DATETIME(6) 열을 거쳐 읽습니다. 저장할 때 마이크로초보다 작은 자리가 기본 설정에서 반올림될 수 있어서 호출 전후 범위를 양쪽 1마이크로초씩 넓혀 단언했습니다. MySQL의 소수 초 저장 규칙
pYIN 준비와 채점 시간 분리
운영과 같은 이미지와 6GiB 메모리 제한의 일회용 컨테이너에서 합성음으로 pYIN을 실행했습니다. 첫 번째 입력을 처리하기 전 짧은 신호로 pYIN을 부르는 준비에는 16.42초, 준비 뒤 15초 입력의 음높이 추정과 채점에는 2.49초가 걸렸습니다. 이어진 길이별 실행의 준비 시간은 약 3초였습니다. 첫 실행 수치에는 JIT 컴파일 준비가 포함되므로, 이미 준비된 계산 시간과 구분했습니다.
이 실험은 다운로드, 디코딩, 대기열, DB 저장을 재지 않았습니다. 별도의 배포 서버 확인에서는 1,450ms·20,118바이트짜리 정상 합성 AAC 한 건이 202로 접수된 뒤 20.44초에 DONE으로 관찰됐습니다. DB에 평가 한 건과 음표 결과 두 건이 저장됐고 API·로그의 결과와 일치했습니다. 20.44초는 서버에 올린 요청의 단건 관찰값이며, 앞의 단계별 측정과 입력과 경로가 다릅니다.
이 기록을 남긴 당시에는 운영의 60초 설정을 유지했습니다. 요청이 겹치는 경우나 여러 차례 실행했을 때의 지연 분포를 평가하려면 접수부터 저장까지 같은 조건으로 별도로 재야 합니다.

댓글
댓글과 반응은 GitHub 계정으로 로그인해 남길 수 있어요.