API의 오류 처리는 상태 코드만 맞는다고 끝나지 않는다. 오류 본문의 Content-Type, 서버 로그 기록, 스트림이 실패했을 때의 응답 종료까지 클라이언트와 운영에 영향을 준다. NestJS 12.3.0에는 이 경계를 다루는 수정이 여럿 포함돼 있어, HTTP API를 운영한다면 살펴볼 만하다.

HTTP 오류 변환과 로그

Express 어댑터에는 http-errors 예외를 Nest의 HttpException으로 매핑하는 수정이 들어갔다. Fastify 쪽에도 4xx http-errors 오류를 HTTP 예외로 매핑하는 변경이 있다.

동시에 두 어댑터 모두 5xx 오류는 로그에 남도록 매핑하지 않는 수정이 포함됐다. Express는 http-errors의 5xx 오류, Fastify는 Fastify의 5xx 오류가 대상이다. 예외 변환과 서버 오류 기록을 함께 확인해야 하는 이유다.

업데이트를 검토할 때는 오류 응답의 상태 코드와 본문뿐 아니라 서버 로그도 같이 보는 편이 좋다. 특히 별도 예외 필터를 사용한다면, 기존에 기대한 응답 형식과 로그 기록이 유지되는지 점검할 항목으로 잡을 수 있다.

오류 본문과 Content-Type

Fastify 어댑터는 객체 형태의 오류 본문을 JSON Content-Type으로 보내도록 수정됐다. Express 어댑터에는 오류를 감싼 예외에 표준 본문을 보내는 수정이 들어갔다.

Express에서 지원하지 않는 multipart Content-Type을 415로 매핑하는 변경도 있다. 파일 업로드 API라면 정상 업로드뿐 아니라 지원하지 않는 형식으로 요청했을 때의 응답도 확인할 만하다.

이 변경들을 모든 오류 응답 형식이 같아진다는 뜻으로 읽을 필요는 없다. 각 어댑터의 수정 대상을 기준으로, 서비스에서 실제 사용하는 오류 경로를 골라 확인하는 것이 적절하다.

스트림 실패와 빈 HEAD 응답

공통 모듈에는 StreamableFile 전송이 도중에 실패하면 응답을 중단하는 수정이 포함됐다. Express에는 비어 있는 StreamableFile의 HEAD 응답을 종료하는 수정도 있다.

파일 다운로드 API를 운영한다면 두 경우를 구분해서 살펴볼 수 있다. 전송 중 실패했을 때 응답이 어떻게 끝나는지, 빈 파일에 HEAD 요청을 보냈을 때 종료되는지를 각각 확인하는 식이다.

이번 릴리스의 HTTP 관련 변경은 예외 변환, 응답 표현, 연결 종료에 걸쳐 있다. 업그레이드 점검도 정상 응답만 확인하고 끝내기보다, 사용하는 어댑터에 맞춰 4xx·5xx 오류와 파일 응답의 실패 경로까지 포함하는 편이 좋다.

참고한 원문

이미지 분석과 도구 호출을 함께 쓰는 서비스라면 모델의 입력 형식과 추론 설정을 같이 살펴볼 필요가 있다. Transformers v5.22.0에 추가된 Mistral Large 4는 텍스트·이미지 입력을 받고, 요청마다 추론 강도를 조절할 수 있는 모델이다.

무엇이 추가됐나

Mistral Large 4는 지시 수행, 추론, 코딩, 에이전트 작업을 하나의 가중치로 처리한다. 텍스트와 이미지를 입력받으며 출력은 텍스트이다. 이미지 생성 모델로 이해하면 안 된다. 비전 인코더는 서로 다른 이미지 크기와 종횡비를 처리하도록 학습됐다.

구조는 전체 약 1조 파라미터의 MoE이다. 토큰당 활성 파라미터는 490억이며, 임베딩과 출력 계층을 포함하면 약 520억이다. 라우팅 대상 전문가 128개 중 토큰마다 4개가 활성화되고 공유 전문가 1개가 함께 구성된다. 전체 파라미터 수와 활성 파라미터 수를 구분해서 읽어야 한다.

지원 컨텍스트 길이는 100만 토큰이다. 긴 문서나 이미지가 포함된 작업을 검토할 만하지만, 릴리스 설명만으로 실제 배포에 필요한 메모리나 처리 속도를 산정할 수는 없다.

추론 강도는 명시적으로 선택한다

reasoning_effort는 low, medium, high를 지원하며 기본값은 high이다. 릴리스에서는 빠른 채팅 응답에 low, 일상적인 사용에 medium, 복잡한 프롬프트와 에이전트 작업에 high를 권장한다.

다음은 권장값을 정리한 설정 예시이다. 실행용 API 호출 코드는 아니다.

request_settings = {
    "reasoning_effort": "medium",
    "temperature": 1.0,
    "top_p": 0.95,
}

샘플링 권장값은 추론 강도와 관계없이 temperature=1.0, top_p=0.95이다. 서비스에서는 기본값에 맡기기보다 요청의 용도에 맞춰 추론 강도를 지정하는 편이 의도를 드러내기 쉽다.

도구 연결과 라이선스 확인

네이티브 함수 호출, JSON 출력, 엄격한 JSON 스키마 적용도 지원한다. 시스템 프롬프트에는 실행 환경과 사용 목적, 도구 사용 지침을 명확히 적고 도구 수는 필요한 최소한으로 제한하라는 권장이 함께 제시됐다.

배포를 검토한다면 라이선스도 확인해야 한다. Mistral Ecosystem Open-Weight License는 MIT를 수정한 라이선스로 상업·비상업 사용을 허용하지만, Model-as-a-Service 사업 운영에는 Mistral과 별도 상업 라이선스가 필요하다. 모델을 서비스로 제공할 계획이라면 이 조건을 먼저 살펴봐야 한다.

참고한 원문

입력창이 화면에 잘 보인다고 누구나 폼을 사용할 수 있는 것은 아니다. 키보드로 이동하거나 스크린 리더로 읽을 때도 입력 목적과 오류 원인을 이해할 수 있어야 한다. web.dev의 폼 접근성 가이드를 기준으로 마크업에서 챙길 부분을 정리한다.

레이블 연결부터 시작한다

폼 컨트롤에는 목적을 설명하는 <label>을 연결한다. label의 for와 입력 요소의 id를 맞추면 스크린 리더가 레이블을 읽고, 레이블을 클릭하거나 터치했을 때 해당 입력창에 포커스가 이동한다. 작은 입력창만 정확히 누를 필요도 줄어든다.

겉모양이 같아도 contenteditable을 붙인 div가 기본 입력 요소의 기능을 그대로 갖는 것은 아니다. <input>은 입력 컨트롤이라는 의미를 전달하고 폼 제출에 참여한다. 적절한 type이나 inputmode는 화면 키보드에 표시할 문자 구성에도 도움을 준다.

입력 규칙을 화면과 마크업에 함께 적는다

minlength로 길이 제한을 설정해도 사용자가 그 규칙을 미리 아는 것은 아니다. 입력창 아래에 조건을 설명하고 aria-describedby로 연결하면 보조 기술에도 설명의 관계를 전달할 수 있다.

다음은 가이드의 연결 방식을 적용한 예시이다.

<label for="account-name">계정 이름</label>
<input
  type="text"
  id="account-name"
  name="accountName"
  minlength="8"
  aria-describedby="account-name-hint"
  required
>
<p id="account-name-hint">8자 이상 입력한다.</p>

핵심은 검증 속성과 안내 문구의 역할을 나누는 것이다. 브라우저에는 입력 규칙을 지정하고, 사용자에게는 어떤 값을 넣어야 하는지 설명한다.

오류는 색상만으로 표시하지 않는다

잘못된 입력에 빨간 테두리만 표시하면 색상을 구별하기 어려운 사용자는 상태를 알아차리기 힘들다. 오류 문구에 ‘오류:’ 같은 접두어나 아이콘을 함께 사용한다. 직접 만든 오류 메시지도 aria-describedby로 해당 필드와 연결할 수 있다.

오류가 나타나는 순간 읽도록 aria-live="assertive"를 사용할 수도 있다. 다만 여러 필드에서 동시에 오류가 생기면 첫 오류만 안내되는 경우가 있어, 전체 오류를 묶어 알리거나 필드에 포커스가 왔을 때 개별 오류를 안내하는 방식도 검토해야 한다.

화면 순서와 키보드 순서를 맞춘다

CSS로 배치만 바꾸면 화면의 입력 순서와 DOM을 따르는 키보드 이동 순서가 어긋날 수 있다. 폼을 수정할 때는 배치와 DOM 순서를 함께 살핀다.

포커스 표시도 현재 입력 위치를 찾는 단서이다. 기본 스타일을 바꾼다면 일반 상태와 확실히 구분되게 하고, 필요하면 :focus-visible을 활용한다. 마지막으로 키보드만 사용한 입력, 스크린 리더 탐색, 페이지 200% 확대 상태에서 폼을 끝까지 작성할 수 있는지 점검한다.

참고한 원문

Next.js 패치 버전을 검토할 때는 새 기능보다 현재 프로젝트와 맞닿은 수정 항목을 먼저 보는 편이 유용하다. 16.4.3에는 Google Fonts URL 처리, proxy.ts의 런타임 로딩, Turbopack 관련 변경이 포함됐다. 해당 경로를 사용하는 프로젝트라면 업데이트 후 확인할 지점을 잡기 좋다.

새 기능보다 버그 수정 중심

16.4.3은 버그 수정을 백포트한 릴리스이다. 릴리스 노트에서도 canary에 대기 중인 기능과 변경을 모두 포함하지 않는다고 명시한다. 따라서 canary에서 본 동작이 이 버전에도 들어왔을 것이라고 가정하면 안 된다.

업데이트를 검토할 때는 필요한 수정이 목록에 있는지부터 확인하면 된다. 이번 버전의 성격은 기능 도입보다 기존 동작의 오류를 바로잡는 쪽에 가깝다.

폰트 URL과 런타임 로딩

폰트 관련 항목은 확장자가 없는 Google Fonts URL을 두 번들러에서 처리하도록 수정한 내용이다. 이런 URL을 사용하는 프로젝트라면 업데이트 전후에 폰트 로딩과 빌드 결과를 확인할 항목으로 삼을 수 있다. 모든 폰트 문제를 해결했다는 의미로 읽을 필요는 없다.

런타임 로딩 변경도 있다. proxy.ts에서 app-page 런타임을 로드하지 않도록 했고, 서버 부트스트랩에서는 별도의 React를 로드하지 않도록 수정했다. 두 항목 모두 로딩 대상에 관한 변경이다. 릴리스 노트에는 성능 수치나 구체적인 재현 조건이 없으므로, 속도 개선을 단정하기보다 관련 경로의 동작을 점검하는 근거로 보는 편이 맞다.

Turbopack은 되돌림도 확인

Turbopack에서는 앞서 적용한 ‘loader change invalidation’ 변경을 되돌렸다. 수정 목록에 이름이 올라왔다고 해서 해당 동작이 새로 강화된 것은 아니다. 로더를 사용하는 프로젝트라면 로더 변경 뒤 결과가 갱신되는 흐름을 업데이트 점검에 포함할 만하다.

이 밖에 OpenTelemetry의 요청 트레이스를 함께 유지하는 수정도 들어갔다. 요청 추적을 사용한다면 관련 트레이스가 이어지는 모습을 확인할 항목이다.

프로젝트에서 확인할 점

검토 범위는 실제 사용 중인 기능에 맞춰 좁히면 된다. Google Fonts를 쓴다면 폰트 로딩을, proxy.ts가 있다면 해당 요청 경로를, Turbopack 로더를 쓴다면 변경 반영 흐름을 살펴보는 식이다. 릴리스 노트에는 재현 코드나 설정 예제가 없으므로, 각 프로젝트의 기존 실행·빌드 절차로 관련 동작을 확인하는 것이 자연스럽다.

참고한 원문

+ Recent posts