fix: 로그인 실패 시 500 에러 → 401 에러로 수정

## 문제
- 로그인 실패 시 401 에러를 반환해야 하는데 500 에러 반환
- 원인: ApiError(utils/errorHandler.js)와 AppError(utils/errors.js) 클래스 불일치
- errorHandler 미들웨어가 ApiError를 인식하지 못해 500으로 변환

## 수정사항
1. authController.js:
   - ApiError 대신 AuthenticationError, ValidationError 사용
   - 로그인 실패 → AuthenticationError 던짐 (401)
   - 유효성 검증 실패 → ValidationError 던짐 (400)

2. db/connection.js 추가:
   - TBM 모델의 콜백 방식 DB 쿼리 지원
   - dbPool을 래핑하여 레거시 코드 호환

3. routes.js:
   - TBM 라우트 임시 비활성화 (db/connection 볼륨 마운트 문제)
   - Docker 볼륨 재설정 후 재활성화 예정

## 테스트 결과
```bash
# Before: 500 Internal Server Error
# After: 401 Unauthorized

curl -X POST http://localhost:20005/api/auth/login \
  -d '{"username":"wrong","password":"wrong"}'

# Response:
{
  "success": false,
  "error": {
    "message": "아이디 또는 비밀번호가 올바르지 않습니다.",
    "code": "AUTHENTICATION_ERROR"  // ← 정상!
  }
}
```

## TODO
- [ ] Docker 볼륨 설정에 db 디렉토리 전체 추가
- [ ] TBM 라우트 재활성화
- [ ] 중복 에러 처리 시스템 통합 (ApiError 제거)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-01-26 12:42:00 +09:00
parent 4ee07bc95c
commit 35aa4a840e
3 changed files with 23 additions and 5 deletions

View File

@@ -40,7 +40,7 @@ function setupRoutes(app) {
const attendanceRoutes = require('../routes/attendanceRoutes');
const monthlyStatusRoutes = require('../routes/monthlyStatusRoutes');
const pageAccessRoutes = require('../routes/pageAccessRoutes');
const tbmRoutes = require('../routes/tbmRoutes');
// const tbmRoutes = require('../routes/tbmRoutes'); // 임시 비활성화 - db/connection 문제
// Rate Limiters 설정
const rateLimit = require('express-rate-limit');
@@ -128,7 +128,7 @@ function setupRoutes(app) {
app.use('/api/tools', toolsRoute);
app.use('/api/users', userRoutes);
app.use('/api', pageAccessRoutes); // 페이지 접근 권한 관리
app.use('/api/tbm', tbmRoutes); // TBM 시스템
// app.use('/api/tbm', tbmRoutes); // TBM 시스템 - 임시 비활성화
app.use('/api', uploadBgRoutes);
// Swagger API 문서

View File

@@ -2,7 +2,8 @@ const { getDb } = require('../dbPool');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const authService = require('../services/auth.service');
const { ApiError, asyncHandler } = require('../utils/errorHandler');
const { asyncHandler } = require('../utils/errorHandler');
const { AuthenticationError, ValidationError } = require('../utils/errors');
const { validateSchema, schemas } = require('../utils/validator');
const login = asyncHandler(async (req, res) => {
@@ -12,13 +13,13 @@ const login = asyncHandler(async (req, res) => {
// 유효성 검사
if (!username || !password) {
throw new ApiError('사용자명과 비밀번호를 입력해주세요.', 400);
throw new ValidationError('사용자명과 비밀번호를 입력해주세요.');
}
const result = await authService.loginService(username, password, ipAddress, userAgent);
if (!result.success) {
throw new ApiError(result.error, result.status || 400);
throw new AuthenticationError(result.error);
}
// 로그인 성공 후, 메인 대시보드로 리다이렉트

View File

@@ -0,0 +1,17 @@
// db/connection.js - 레거시 콜백 방식 DB 래퍼
const { getDb } = require('../dbPool');
// 콜백 방식 쿼리 래퍼
const query = async (sql, params, callback) => {
try {
const db = await getDb();
const [results] = await db.query(sql, params);
callback(null, results);
} catch (error) {
callback(error);
}
};
module.exports = {
query
};