티스토리 뷰

반응형
  • 아아.. 블로그 포스팅을 할 건 많은거 같은데 회사 일이 바쁘다 보니 자꾸만 밀린다 ㅜㅜ..
  • 이건 API 서버 개발하다가 정말 유용하게 쓰고 있는 API 서버의 에러를 텔레그램 봇으로 받는 구현체 예제입니다.
  • API 서버의 환경은 다음과 같습니다
    • Node.js 7.x
    • Express.js
    • ECMA2016
  • 텔레그램 봇이 급하신 분들은 errorHandler.js 만 보세요.
  • 테스트로 사용한 전체 소스코드는 Gist 를 참고 바랍니다.

선 스크린샷, 후 코드

서버 로그를 계속 쳐다보고 있을 수가 없으니 에러 발생시 Notifiable 하게 하면 편하다.

구현체

Server.js

import express from 'express';
import occurError from './occurError';
import errorHandler from './errorHandler'
 
const app = express();
 
// 높은 Unit Testability 를 가져가기 위해 Express Route 내에서 특별한 로직을 처리하지 않고 실제 로직은 occurError() 와 같이 모듈로 빼서 리턴 값만 사용합니다.
app.get('/error/:number', (request, response) => {
  try {
    const result = occurError(request.params.number); // occurError.js
    response.json(result);
  } catch (error) {
    // try block 내에서 throw 가 발생했을 때 무조건 errorHandler() 에게 던집니다.
    // request 객체가 필요한 이유는 텔레그램 봇에서 Generating Log Message를 하기 위함입니다.
    // response 객체를 던지는 이유는 실제 response.send() 가 errorHandler 내부에서 일어나기 때문입니다.
    errorHandler(request, response, error); // errorHandler.js
  }
});
 
app.listen(3000, () => {
  console.log('Web Server Listen 3000 port..!');
});

occurError.js

import HttpError from './HttpError';
 
export default function occurError(numberParameter) {
  // numberParameter가 Number로 parseInt 되지 않을 때 에러를 발생시켰습니다.
  if (!parseInt(numberParameter, 10)) {
    throw new HttpError(403, 'PARAMETER_TYPE_EXCEPTION', 'numberParameter is require Number'); // HttpError.js
  }
  return 'This is Good Statement';
};

HttpError.js

// Error Class를 상속받는 HttpError Class를 정의합니다. HTTP 통신에 필요한 Status Code와 추가적인 데이터를 전달하기 위함입니다.
export default class HttpError extends Error {
  constructor(status, code, message) {
    super();
    // 저는 가끔 귀찮을 때 throw new HttpError(null, null, 'Hmm..') 과 같이 사용할 때가 있습니다. 이를 위한 OR 연산입니다.
    this.status = status || 500;
    this.code = code || 'UNEXPECTED_ERROR';
    this.message = message || 'What the Unexpected Error?!?!';
  }
}

errorHandler.js

import fetch from 'node-fetch';
 
const TOKEN = '11111:TelegramBotToken';
// 텔레그램 @BotFather 로 생성한 봇의 TOKEN이 필요합니다.
 
const TELEGRAM_BOT_URL = `https://api.telegram.org/bot${TOKEN}/sendMessage`;
// 텔레그램 봇으로 sendMessage 기능을 수행할 수 있는 URL 입니다.
// 텔레그램 봇 API에 대한 자세한 내용은 https://core.telegram.org/bots/api 을 참고하세요.
// npm에 node-telegram-bot-api 와 같이 추상화된 모듈도 있습니다.
// https://www.npmjs.com/package/node-telegram-bot-api
 
const CHAT_ID = 123456789;
// 메시지를 보낼 채팅창의 chat_id 입니다. 채팅창의 chat_id 를 얻는 방법은 여기서 언급하지 않겠습니다.
// 저는 몇 대의 봇과 다수의 chat_id 을 기능별로 DB로 관리하고 있습니다.
// TOKEN, CHAT_ID 와 같은 상수를 process.env.NODE_ENV 별로 관리하고 싶다면 getconfig 와 같은 것을 사용하면 좋습니다.
 
function errorHandler(request, response, error) {
  // HttpError Class 에서 정의한 status, code, message을 errorHandler에서 다시 정의하는 이유는 HttpError 객체로 Customize하게 잡히지 않는 Exception Error들 까지 포괄하여 처리할 수 있게하기 위함입니다. (ex. Syntax Error)
  const status = error.status || 500;
  const code = error.code || 'UNEXPECTED_ERROR';
  const message = error.message || error.toString();
 
  // 특정 Http Status Code 에서만 텔레그램 봇 활성화
  if ([500, 403, 401].indexOf(status) >= 0) {
    const text = `Occur ${code} Error..!\n\n- IP: ${request.ip}\n- URI: ${request.method} ${request.originalUrl}\n- HEADERS: ${JSON.stringify(request.headers)}\n- BODY: ${JSON.stringify(request.body)}\n\n- STATUS: ${status}\n- CODE: ${code}\n- STACK: ${error.stack}`;
 
    // TELEGRAM_BOT_URL 로 fetch 하는 부분은 동기로 돌아갈 필요가 없습니다. 성공이건 실패건 response.send() 는 실행되어야 하며, 연관되지 않습니다.
    fetch(TELEGRAM_BOT_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        chat_id: CHAT_ID,
        text
      }),
    }).then(result => result.json())
    .catch(telegramError => console.error(telegramError));
  }
 
  response.status(status).send({ code, message });
}


반응형
프로필사진

Yowu (Yu Yongwoo)

흔한 Node.js/Java 백엔드 개발자입니다
Ubuntu와 MacOS 데스크탑 개발 환경을 선호합니다
최근에는 vscode와 IntelliJ를 사용하고 있습니다
vscode에는 neovim, IntelliJ는 ideaVim
개발용 키보드는 역시 HHKB Pro 2 무각입니다
락 밴드에서 드럼을 쳤습니다

최근에 올라온 글
최근에 달린 댓글
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함
Total
Today
Yesterday