확장성을 위해 역할별이 아닌 독립형 / 모듈형으로 구성

structurebyroles.png

structurebycomponents.png

관리를 위해 index 또는 모듈파일에서 import해서 관리

structurebycomponents.png

여러 유형에서 사용할 수 있게 context 오브젝트를 매개변수로 동작하게끔 하기

keepexpressinweb.gif

config 오브젝트를 만들어서 관리 및 불러오기

{
  // Customer module configs 
  "Customer": {
    "dbConfig": {
      "host": "localhost",
      "port": 5984,
      "dbName": "customers"
    },
    "credit": {
      "initialLimit": 100,
      // Set low for development 
      "initialDays": 1
    }
  }
}

Node용 정의되지 않은 에러는 아래 객체사용

export class AppError extends Error {
  public readonly commonType: string;
  public readonly isOperational: boolean;

  constructor(commonType: string, description: string, isOperational: boolean) {
    super(description);

    Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain

    this.commonType = commonType;
    this.isOperational = isOperational;

    Error.captureStackTrace(this);
  }
}

//사용방법
throw new AppError(errorManagement.commonErrors.InvalidInput, 'Describe here what happened', true);

미들웨어 내에 펑션정의로 에러핸들링하지말고 핸들러를 만들어 관리

class ErrorHandler {
  public async handleError(error: Error, responseStream: Response): Promise<void> {
    await logger.logError(error);
    await fireMonitoringMetric(error);
    await crashIfUntrustedErrorOrSendResponse(error, responseStream);
  };
}

export const handler = new ErrorHandler();

//미들웨어
app.use(async (err: Error, req: Request, res: Response, next: NextFunction) => {
  await errorHandler.handleError(err, res);
});

process.on("uncaughtException", (error:Error) => {
  errorHandler.handleError(error);
});

process.on("unhandledRejection", (reason) => {
  errorHandler.handleError(reason);
});

//AppError 사용시

class ErrorHandler {
  public async handleError(err: Error): Promise<void> {
    await logger.logError(err);
    await sendMailToAdminIfCritical();
    await saveInOpsQueueIfCritical();
    await determineIfOperationalError();
  };

  public isTrustedError(error: Error) {
    if (error instanceof AppError) {
      return error.isOperational;
    }
    return false;
  }
}