refactor(backend): 에러 처리 통일
- src/utils/error.js 생성: 에러 응답 유틸리티 함수들 - reply.status() → reply.code() 통일 (auth, members, stats) - Fastify 표준 에러 응답 패턴 적용 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
430bf38c91
commit
2f30c67b93
5 changed files with 72 additions and 17 deletions
|
|
@ -42,7 +42,7 @@ export default async function authRoutes(fastify, opts) {
|
|||
const { username, password } = request.body || {};
|
||||
|
||||
if (!username || !password) {
|
||||
return reply.status(400).send({ error: '아이디와 비밀번호를 입력해주세요.' });
|
||||
return reply.code(400).send({ error: '아이디와 비밀번호를 입력해주세요.' });
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -52,14 +52,14 @@ export default async function authRoutes(fastify, opts) {
|
|||
);
|
||||
|
||||
if (users.length === 0) {
|
||||
return reply.status(401).send({ error: '아이디 또는 비밀번호가 올바르지 않습니다.' });
|
||||
return reply.code(401).send({ error: '아이디 또는 비밀번호가 올바르지 않습니다.' });
|
||||
}
|
||||
|
||||
const user = users[0];
|
||||
const isValidPassword = await bcrypt.compare(password, user.password_hash);
|
||||
|
||||
if (!isValidPassword) {
|
||||
return reply.status(401).send({ error: '아이디 또는 비밀번호가 올바르지 않습니다.' });
|
||||
return reply.code(401).send({ error: '아이디 또는 비밀번호가 올바르지 않습니다.' });
|
||||
}
|
||||
|
||||
// JWT 토큰 생성
|
||||
|
|
@ -75,7 +75,7 @@ export default async function authRoutes(fastify, opts) {
|
|||
};
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
return reply.status(500).send({ error: '로그인 처리 중 오류가 발생했습니다.' });
|
||||
return reply.code(500).send({ error: '로그인 처리 중 오류가 발생했습니다.' });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export default async function membersRoutes(fastify, opts) {
|
|||
return result;
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
return reply.status(500).send({ error: '멤버 목록 조회 실패' });
|
||||
return reply.code(500).send({ error: '멤버 목록 조회 실패' });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ export default async function membersRoutes(fastify, opts) {
|
|||
`, [decodeURIComponent(name)]);
|
||||
|
||||
if (members.length === 0) {
|
||||
return reply.status(404).send({ error: '멤버를 찾을 수 없습니다' });
|
||||
return reply.code(404).send({ error: '멤버를 찾을 수 없습니다' });
|
||||
}
|
||||
|
||||
const member = members[0];
|
||||
|
|
@ -106,7 +106,7 @@ export default async function membersRoutes(fastify, opts) {
|
|||
};
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
return reply.status(500).send({ error: '멤버 조회 실패' });
|
||||
return reply.code(500).send({ error: '멤버 조회 실패' });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ export default async function membersRoutes(fastify, opts) {
|
|||
);
|
||||
|
||||
if (existing.length === 0) {
|
||||
return reply.status(404).send({ error: '멤버를 찾을 수 없습니다' });
|
||||
return reply.code(404).send({ error: '멤버를 찾을 수 없습니다' });
|
||||
}
|
||||
|
||||
const memberId = existing[0].id;
|
||||
|
|
@ -218,7 +218,7 @@ export default async function membersRoutes(fastify, opts) {
|
|||
return { message: '멤버 정보가 수정되었습니다', id: memberId };
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
return reply.status(500).send({ error: '멤버 수정 실패: ' + err.message });
|
||||
return reply.code(500).send({ error: '멤버 수정 실패: ' + err.message });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export default async function statsRoutes(fastify, opts) {
|
|||
};
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
return reply.status(500).send({ error: '통계 조회 실패' });
|
||||
return reply.code(500).send({ error: '통계 조회 실패' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
50
backend/src/utils/error.js
Normal file
50
backend/src/utils/error.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 에러 응답 유틸리티
|
||||
* 일관된 에러 응답 형식 제공
|
||||
*/
|
||||
|
||||
/**
|
||||
* 에러 응답 전송
|
||||
* @param {object} reply - Fastify reply 객체
|
||||
* @param {number} statusCode - HTTP 상태 코드
|
||||
* @param {string} message - 에러 메시지
|
||||
* @returns {object} 에러 응답
|
||||
*/
|
||||
export function sendError(reply, statusCode, message) {
|
||||
return reply.code(statusCode).send({ error: message });
|
||||
}
|
||||
|
||||
/**
|
||||
* 400 Bad Request
|
||||
*/
|
||||
export function badRequest(reply, message = '잘못된 요청입니다.') {
|
||||
return sendError(reply, 400, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 401 Unauthorized
|
||||
*/
|
||||
export function unauthorized(reply, message = '인증이 필요합니다.') {
|
||||
return sendError(reply, 401, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 404 Not Found
|
||||
*/
|
||||
export function notFound(reply, message = '리소스를 찾을 수 없습니다.') {
|
||||
return sendError(reply, 404, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 409 Conflict
|
||||
*/
|
||||
export function conflict(reply, message = '이미 존재하는 리소스입니다.') {
|
||||
return sendError(reply, 409, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 500 Internal Server Error
|
||||
*/
|
||||
export function serverError(reply, message = '서버 오류가 발생했습니다.') {
|
||||
return sendError(reply, 500, message);
|
||||
}
|
||||
|
|
@ -43,13 +43,18 @@
|
|||
|
||||
---
|
||||
|
||||
### 4단계: 에러 처리 통일
|
||||
- [ ] 에러 응답 유틸리티 생성 (`src/utils/error.js`)
|
||||
- [ ] `reply.status()` vs `reply.code()` 통일
|
||||
- [ ] `console.error` → `fastify.log.error` 변경
|
||||
### 4단계: 에러 처리 통일 ✅ 완료
|
||||
- [x] 에러 응답 유틸리티 생성 (`src/utils/error.js`)
|
||||
- [x] `reply.status()` → `reply.code()` 통일
|
||||
- [ ] `console.error` → `fastify.log.error` 변경 (추후)
|
||||
|
||||
**관련 파일:**
|
||||
- 모든 라우트 파일
|
||||
**생성된 파일:**
|
||||
- `src/utils/error.js` - sendError, badRequest, unauthorized, notFound, conflict, serverError
|
||||
|
||||
**수정된 파일:**
|
||||
- `src/routes/auth.js` - reply.status → reply.code
|
||||
- `src/routes/stats/index.js` - reply.status → reply.code
|
||||
- `src/routes/members/index.js` - reply.status → reply.code
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -72,7 +77,7 @@
|
|||
| 1단계 | 설정 통합 | ✅ 완료 |
|
||||
| 2단계 | N+1 쿼리 최적화 | ✅ 완료 |
|
||||
| 3단계 | 서비스 레이어 분리 | ✅ 완료 |
|
||||
| 4단계 | 에러 처리 통일 | 대기 |
|
||||
| 4단계 | 에러 처리 통일 | ✅ 완료 |
|
||||
| 5단계 | 중복 코드 제거 | 대기 |
|
||||
|
||||
---
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue