generated from ttipo/project-base
fix: 오류 사전 문구 18곳을 사람이 말하듯 다듬는다
2026-11-07 사용자가 "자연스러운 문구가 아니라 시스템, 설계 문구 형식"이라고 짚은 글을 고친다(규칙 9 · 10 — 화면 설명 · 번역투 빼기). "일시적인 시스템 오류가 발생했습니다" · "요청하신 정보나 페이지를 찾을 수 없습니다" · "허용 범위를 초과했습니다" 같은 안내문 말투를 무엇이 안 됐고 무엇을 하면 되는지로 바꾼다. 적용하며 셋을 더 다듬었다: REQ_001 은 가장 자주 보는 로그인 · 코드 실패 한도와 진행 중인 일에 함께 맞게, MAIL_003 은 용량이 휴지통도 세므로 휴지통 비우기까지, FILE_001 은 전달하는 원본 첨부에도 맞게. 코드 · 상태 · 뜻은 그대로이고, 웹 · 앱 사전은 sync 로 다시 만들었다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,30 +20,32 @@ export interface ErrorCodeDefinition {
|
||||
const COMMON_ERROR_CODES = {
|
||||
SYS_001: {
|
||||
status: HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
message: '일시적인 시스템 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.',
|
||||
message:
|
||||
'문제가 생겨 하던 일을 마치지 못했습니다. 잠시 뒤 다시 시도해 주세요.',
|
||||
},
|
||||
REQ_001: {
|
||||
status: HttpStatus.TOO_MANY_REQUESTS,
|
||||
message: '요청이 너무 많습니다. 잠시 후 다시 시도해 주세요.',
|
||||
message:
|
||||
'너무 여러 번 시도했거나 같은 일이 이미 진행 중입니다. 잠시 뒤 다시 시도해 주세요.',
|
||||
},
|
||||
AUTH_001: {
|
||||
status: HttpStatus.UNAUTHORIZED,
|
||||
message: '로그인이 필요한 서비스입니다. 로그인 후 이용해 주세요.',
|
||||
message: '로그인이 필요합니다. 로그인한 뒤 다시 시도해 주세요.',
|
||||
},
|
||||
AUTH_002: {
|
||||
status: HttpStatus.UNAUTHORIZED,
|
||||
message: '안전을 위해 로그아웃 되었습니다. 다시 로그인해 주세요.',
|
||||
message: '안전을 위해 로그아웃했습니다. 다시 로그인해 주세요.',
|
||||
// 세션 만료는 클라이언트가 "인증된 세션이 있었는데 401 을 받은" 상황에서 생성한다.
|
||||
clientOnly: true,
|
||||
},
|
||||
AUTH_003: {
|
||||
status: HttpStatus.FORBIDDEN,
|
||||
message: '해당 메뉴나 기능에 접근할 수 있는 권한이 없습니다.',
|
||||
message: '이 기능을 쓸 수 있는 권한이 없습니다.',
|
||||
},
|
||||
// 로그인 자격 증명 불일치 — 계정 없음/비밀번호 틀림을 구분하지 않는다 (.claude/rules/security.md)
|
||||
AUTH_004: {
|
||||
status: HttpStatus.UNAUTHORIZED,
|
||||
message: '이메일 또는 비밀번호가 올바르지 않습니다.',
|
||||
message: '메일 주소나 비밀번호가 맞지 않습니다. 다시 확인해 주세요.',
|
||||
},
|
||||
// 비밀번호 바꾸기(PUT /api/auth/password)의 지금 비밀번호가 틀림 — 세션은 그대로다.
|
||||
// 401 이 아니라 400 인 까닭: 웹 클라이언트는 401 이면 세션을 갱신하고 같은 요청을 다시 보낸다 (계약 1절)
|
||||
@@ -56,7 +58,7 @@ const COMMON_ERROR_CODES = {
|
||||
AUTH_006: {
|
||||
status: HttpStatus.BAD_REQUEST,
|
||||
message:
|
||||
'코드가 올바르지 않습니다. 휴대폰의 날짜와 시간이 자동으로 맞춰지도록 설정되어 있는지 확인해 주세요.',
|
||||
'코드가 맞지 않습니다. 휴대폰 설정에서 날짜와 시간을 자동으로 맞추게 해 두었는지 확인해 주세요.',
|
||||
},
|
||||
// 2단계 인증을 켠 직원의 요청에 코드가 없음 — 다른 곳에서 켠 뒤의 화면. 화면은 코드 칸을 보인다 (계약 5절)
|
||||
AUTH_007: {
|
||||
@@ -88,11 +90,11 @@ const COMMON_ERROR_CODES = {
|
||||
},
|
||||
RES_001: {
|
||||
status: HttpStatus.NOT_FOUND,
|
||||
message: '요청하신 정보나 페이지를 찾을 수 없습니다.',
|
||||
message: '찾을 수 없습니다. 이미 지워졌거나 옮겨졌을 수 있습니다.',
|
||||
},
|
||||
BIZ_001: {
|
||||
status: HttpStatus.BAD_REQUEST,
|
||||
message: '요청하신 작업을 완료하지 못했습니다. 다시 시도해 주세요.',
|
||||
message: '하려던 일을 마치지 못했습니다. 다시 시도해 주세요.',
|
||||
},
|
||||
} as const satisfies Record<string, ErrorCodeDefinition>;
|
||||
|
||||
@@ -109,24 +111,24 @@ const COMMON_ERROR_CODES = {
|
||||
const DOMAIN_ERROR_CODES = {
|
||||
FILE_001: {
|
||||
status: HttpStatus.BAD_REQUEST,
|
||||
message: '허용되지 않는 파일 형식입니다. 파일을 확인해 주세요.',
|
||||
message:
|
||||
'쓸 수 없는 형식의 파일입니다. 그 파일을 빼거나 다른 파일로 바꿔 주세요.',
|
||||
},
|
||||
FILE_002: {
|
||||
status: HttpStatus.PAYLOAD_TOO_LARGE,
|
||||
message: '파일 크기가 허용 범위를 초과했습니다.',
|
||||
message: '파일이 너무 커서 올릴 수 없습니다.',
|
||||
},
|
||||
// 대용량 첨부(11단계 — 계약 4절) — 올리기 · 파일의 지금 상태와 맞지 않는 요청: 끝낸 올리기에 조각 · 같은 조각을 동시에 · 받은 조각과 내용이 다른 조각 ·
|
||||
// 빠진 조각이 있는데 끝내기 · 끝내기가 진행 중 · 살아 있는 링크에 실린 파일 지우기. 아무것도 바꾸지 않았다 — 클라이언트는 GET 으로 상태를 보고 잇는다
|
||||
FILE_003: {
|
||||
status: HttpStatus.CONFLICT,
|
||||
message:
|
||||
'파일 상태가 그사이 바뀌어 처리하지 못했습니다. 다시 시도해 주세요.',
|
||||
'그사이 파일이 바뀌어 하던 일을 마치지 못했습니다. 다시 시도해 주세요.',
|
||||
},
|
||||
// 조각의 Content-Digest(sha-256)가 받은 바이트와 다르다 — 그 조각을 받지 않았다 (같은 조각을 다시 보낸다)
|
||||
FILE_004: {
|
||||
status: HttpStatus.BAD_REQUEST,
|
||||
message:
|
||||
'파일을 올리는 중에 일부가 제대로 전달되지 않았습니다. 다시 시도해 주세요.',
|
||||
message: '파일 일부가 제대로 올라가지 않았습니다. 다시 시도해 주세요.',
|
||||
},
|
||||
// 직원 보관 한도(보관량 · 보내지 않은 파일 수)를 넘는다 — 만들지 않았다. 문구에 숫자를 넣지 않는다(한도가 env 로 바뀐다)
|
||||
FILE_005: {
|
||||
@@ -138,7 +140,7 @@ const DOMAIN_ERROR_CODES = {
|
||||
FILE_006: {
|
||||
status: HttpStatus.INSUFFICIENT_STORAGE,
|
||||
message:
|
||||
'서버의 저장 공간이 모자라 지금은 파일을 올릴 수 없습니다. 잠시 뒤 다시 시도해 주세요.',
|
||||
'회사 저장 공간이 모자라 지금은 파일을 올릴 수 없습니다. 잠시 뒤 다시 시도해 주세요.',
|
||||
},
|
||||
// 더 내려받을 수 없는 파일 — 기간 지남 · 공유 멈춤 · 횟수 초과 · 위험 · 찾을 수 없음 (공개 받기 · 우리 웹메일 받기)
|
||||
FILE_007: {
|
||||
@@ -163,14 +165,14 @@ const DOMAIN_ERROR_CODES = {
|
||||
MAIL_003: {
|
||||
status: HttpStatus.BAD_REQUEST,
|
||||
message:
|
||||
'메일함 용량이 부족합니다. 불필요한 메일을 정리한 뒤 다시 시도해 주세요.',
|
||||
'메일함이 가득 찼습니다. 필요 없는 메일을 지우고 휴지통을 비운 뒤 다시 시도해 주세요.',
|
||||
},
|
||||
// 발송 때 엔진에서 첨부(blob)를 찾지 못함 — 올려 두고 오래 지나 만료된 업로드·그사이 지워진 원본 메일의 첨부(전달)·잘못된 첨부 id.
|
||||
// 문구는 원인을 단정하지 않는다 — 올린 파일은 다시 올리고, 전달하는 원본 첨부는 빼야 한다 (계약 2절)
|
||||
MAIL_004: {
|
||||
status: HttpStatus.BAD_REQUEST,
|
||||
message:
|
||||
'첨부 파일을 찾을 수 없습니다. 해당 첨부를 빼거나 다시 올린 뒤 보내 주세요.',
|
||||
'첨부 파일을 찾을 수 없습니다. 그 파일을 빼거나 다시 올린 뒤 보내 주세요.',
|
||||
},
|
||||
// 같은 Idempotency-Key 로 이미 보낸 메일과 내용(받는 사람·제목·본문·첨부)이 다르다 — 보내지 않는다.
|
||||
// 첫 메일이 실제로 나갔을 수 있으므로 클라이언트는 보낸편지함을 확인하게 하고 새 키로 다시 보내게 한다
|
||||
@@ -183,7 +185,7 @@ const DOMAIN_ERROR_CODES = {
|
||||
// 문구의 숫자는 attachment.policy.ts 의 MAX_ATTACHMENTS_PER_MESSAGE 와 같아야 한다 (attachment.policy.spec.ts 가 확인한다)
|
||||
MAIL_006: {
|
||||
status: HttpStatus.BAD_REQUEST,
|
||||
message: '첨부는 한 메일에 최대 20개까지 보낼 수 있습니다.',
|
||||
message: '첨부 파일은 메일 한 통에 20개까지 보낼 수 있습니다.',
|
||||
},
|
||||
// 본문이 너무 길다 — 텍스트 100,000자·서식 본문 500,000자 초과, 서식 본문이 정화 전 비용 한도나 정화 뒤 2,000,000바이트를 넘음.
|
||||
// 메일은 나가지 않는다. 클라이언트는 보내기 전에 같은 한도로 미리 막고 본문 아래에 이 문구를 보인다 (계약 2절)
|
||||
@@ -248,7 +250,7 @@ const DOMAIN_ERROR_CODES = {
|
||||
MAIL_016: {
|
||||
status: HttpStatus.BAD_REQUEST,
|
||||
message:
|
||||
'대용량 첨부 파일을 보낼 수 없습니다. 해당 파일을 빼거나 다시 올린 뒤 보내 주세요.',
|
||||
'보낼 수 없는 대용량 첨부 파일이 있습니다. 그 파일을 빼거나 다시 올린 뒤 보내 주세요.',
|
||||
},
|
||||
// 주소록(8단계) — 그룹 만들기 · 이름 바꾸기 때 이 주소록에 같은 이름의 그룹이 있다(앞뒤 공백을 빼고 ASCII 대소문자를 무시하고 견준다).
|
||||
// 화면은 이름 칸 아래에 알림 없이 보인다 (계약 3절)
|
||||
|
||||
@@ -150,7 +150,7 @@ describe('엔진 웹훅 본문 파서 (createMailEngineEventsBodyParser)', () =>
|
||||
success: false,
|
||||
error: {
|
||||
code: 'AUTH_001',
|
||||
message: '로그인이 필요한 서비스입니다. 로그인 후 이용해 주세요.',
|
||||
message: '로그인이 필요합니다. 로그인한 뒤 다시 시도해 주세요.',
|
||||
traceId: 'trace-e',
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user