로그 미들웨어 ( Log Middleware )는 클라이언트의 모든 요청 사항을 기록해 서버의 상태를 모니터링하기 위한 미들웨어다.

 

로그 미들웨어는 클라이언트의 요청을 기록해 어플리케이션을 모니터링하고 문제가 발생할 때 빠르게 진단할 수 있다.

또한, 로그 데이터는 사용자의 행동을 분석하는 등 데이터 분석 작업에도 활용할 수 있다.

규모가 큰 프로젝트를 진행하게 되면, 화면에 표시되는 모든 로그를 일일이 확인하는 것은 불가능에 가깝다.

이런 경우를 대비해 로그 기능을 지원하는 morgan, winston과 같은 라이브러리를 사용하거나 AWS CloudWatch, Datadog와 같은 외부 모니터링 솔루션 서비스를 이용해 로그를 수집하거나 관리할 수 있다.

 

Datadog와 같은 서비스를 이용해 로그 수집, 로그 분석과 같은 서비스를 빠르게 구현할 수 있다.

 

아래 예시를 통해 클라이언트의 요청을 터미널에 기록하는 간단한 로그 미들웨어를 구현해보자.

우선 winstion 라이브러리를 설치하는것으로 시작!

 

# yarn을 이용해 winston을 설치합니다.
yarn add winston

 

log.middleware

// src/middlewares/log.middleware.js

import winston from 'winston';

const logger = winston.createLogger({
  level: 'info', // 로그 레벨을 'info'로 설정합니다.
  format: winston.format.json(), // 로그 포맷을 JSON 형식으로 설정합니다.
  transports: [
    new winston.transports.Console(), // 로그를 콘솔에 출력합니다.
  ],
});

export default function (req, res, next) {
  // 클라이언트의 요청이 시작된 시간을 기록합니다.
  const start = new Date().getTime();

  // 응답이 완료되면 로그를 기록합니다.
  res.on('finish', () => {
    const duration = new Date().getTime() - start;
    logger.info(
      `Method: ${req.method}, URL: ${req.url}, Status: ${res.statusCode}, Duration: ${duration}ms`,
    );
  });

  next();
}

 

app.js

// src/app.js

import express from 'express';
import cookieParser from 'cookie-parser';
import LogMiddleware from './middlewares/log.middleware.js';
import UsersRouter from './routes/users.router.js';

const app = express();
const PORT = 3018;

app.use(LogMiddleware);
app.use(express.json());
app.use(cookieParser());
app.use('/api', [UsersRouter]);

app.listen(PORT, () => {
  console.log(PORT, '포트로 서버가 열렸어요!');
});

 

로그 레벨 ( level )은 로그의 중요도를 나타낸다. 

단순히 클라이언트의 요청 사항을 기록하기 위해 "Info" 레벨을 사용하지만, "error", "warn", "debug" 등 다양한 로그레벨이 있으며, 특정 상황에 따라 출력하는 레벨을 다르게 구현할 수 있다.

 

로그 미들웨어는 클라이언트의 요청이 발생했을 때, 가장 먼저 실행되어야 하는 미들웨어다.

따라서 app.use를 이용한 전역 미들웨어 중에서 가장 최상단에 위치한다.

 

에러 처리 미들웨어

에러 처리 미들웨어 ( Error Handling Middleware )는 Express.js에서 발생한 에러를 통합적으로 처리하기 위한 미들웨어다

 

error-handling.middleware

// src/middlewares/error-handling.middleware.js

export default function (err, req, res, next) {
  // 에러를 출력합니다.
  console.error(err);

  // 클라이언트에게 에러 메시지를 전달합니다.
  res.status(500).json({ errorMessage: '서버 내부 에러가 발생했습니다.' });
}

 

user.router.js

// src/routes/users.router.js

/** 사용자 회원가입 API 에러 처리 미들웨어 **/
router.post('/sign-up', async (req, res, next) => {
  try {
    const { email, password, name, age, gender, profileImage } = req.body;
    const isExistUser = await prisma.users.findFirst({
      where: {
        email,
      },
    });

    if (isExistUser) {
      return res.status(409).json({ message: '이미 존재하는 이메일입니다.' });
    }

    // 사용자 비밀번호를 암호화합니다.
    const hashedPassword = await bcrypt.hash(password, 10);

    // Users 테이블에 사용자를 추가합니다.
    const user = await prisma.users.create({
      data: {
        email,
        password: hashedPassword, // 암호화된 비밀번호를 저장합니다.
      },
    });

    // UserInfos 테이블에 사용자 정보를 추가합니다.
    const userInfo = await prisma.userInfos.create({
      data: {
        userId: user.userId, // 생성한 유저의 userId를 바탕으로 사용자 정보를 생성합니다.
        name,
        age,
        gender: gender.toUpperCase(), // 성별을 대문자로 변환합니다.
        profileImage,
      },
    });

    return res.status(201).json({ message: '회원가입이 완료되었습니다.' });
  } catch (err) {
    next(err);
  }
});

 

try catch 구문으로 묶고 error가 나면 next로 error-handling.middleware로 에러 전달

 

 

app.js

// src/app.js

import express from 'express';
import cookieParser from 'cookie-parser';
import LogMiddleware from './middlewares/log.middleware.js';
import ErrorHandlingMiddleware from './middlewares/error-handling.middleware.js';
import UsersRouter from './routes/users.router.js';

const app = express();
const PORT = 3018;

app.use(LogMiddleware);
app.use(express.json());
app.use(cookieParser());
app.use('/api', [UsersRouter]);
app.use(ErrorHandlingMiddleware);

app.listen(PORT, () => {
  console.log(PORT, '포트로 서버가 열렸어요!');
});

 

에러 처리 미들웨어는 클라이언트의 요청이 실패했을 때, 가장 마지막에 실행되어야 하는 미들웨어다.

따라서 app.use를 이용한 전역 미들웨어 중 가장 최하단에 위치한다.

 

에러 처리 미들웨어는 모든 에러를 관리하는 미들웨어, 서버 내부에서 발생한 에러를 상세하게 클라이언트에게 제공한다면 악의적인 사용자에게 공격의 표적이 될 수 있다. 

그러므로, 에러 처리 미들웨어에서는 "서버에서 에러가 발생했습니다."와 같은 추상적인 내용을 클라이언트에게 전달하도록 구현해야한다.

 

에러처리 공식 문서 

https://expressjs.com/ko/guide/error-handling.html

 

Express - Node.js web application framework

 

expressjs.com

 

 

 

+ Recent posts