> Hello World !!!

     

@syaku

nodejs - 효율적인 에러 처리: try-catch 사용 전략

반응형

JavaScript/nodejs 의 효율적인 에러 처리: try-catch 사용 전략

1. 들어가며

Java와 달리 JavaScript/Node.js에서는 모든 코드를 try 블록으로 감싸지 않아도 됩니다. 이는 JavaScript의 특성과 최신 개발 패러다임을 반영한 것으로, 더 효율적인 에러 처리를 가능하게 합니다.

2. JavaScript의 에러 처리 특징

2.1 빠른 실패(Fail Fast) 원칙

  • 문제를 조기에 발견하고 처리하는 것이 핵심
  • 입력값 검증은 함수 시작 부분에서 즉시 수행
  • 잘못된 입력을 빨리 감지하여 불필요한 프로세스 실행 방지
function processUser(user) {
  // 빠른 실패: 입력값 검증
  if (!user) throw new Error('User is required');
  if (!user.name) throw new Error('User name is required');

  // 메인 로직
  // ...
}

2.2 예외와 에러의 구분

  • 예상 가능한 상황

    • 입력값 검증
    • 파일 존재 여부 확인
    • 네트워크 연결 상태
    • try-catch 없이 if문으로 처리 가능
  • 예상치 못한 에러

    • 시스템 리소스 부족
    • 예기치 못한 외부 서비스 장애
    • try-catch로 처리 필요

3. 성능 최적화 관점

3.1 try-catch 블록의 영향

  • JavaScript 엔진의 최적화를 방해할 수 있음
  • try 블록 내부 코드는 최적화가 제한됨
  • 필요한 곳에만 선별적으로 사용 권장

3.2 최적화된 에러 처리 예시

async function saveDocument(data) {
  // 1. 입력값 검증 (try-catch 불필요)
  if (!data.content) {
    throw new Error('Content is required');
  }

  // 2. 비즈니스 로직 검증 (try-catch 불필요)
  if (data.content.length > MAX_CONTENT_LENGTH) {
    throw new Error('Content exceeds maximum length');
  }

  // 3. 외부 작업 (try-catch 필요)
  try {
    const result = await database.save(data);
    await notificationService.send(result.id);
    return result;
  } catch (error) {
    logger.error('Document save failed:', error);
    throw new Error('Failed to save document');
  }
}

4. 실제 적용 사례

4.1 파일 처리 서비스

export const fileProcessingService = async (fileData) => {
  // 1. 입력값 검증
  if (!fileData || !fileData.buffer) {
    throw new Error('Invalid file data');
  }

  // 2. 파일 형식 검증
  const fileType = await getFileType(fileData.buffer);
  if (!ALLOWED_TYPES.includes(fileType)) {
    throw new Error('Unsupported file type');
  }

  // 3. 파일 처리 (외부 작업)
  try {
    const processedFile = await processFile(fileData);
    const savedLocation = await saveToStorage(processedFile);

    return {
      location: savedLocation,
      size: processedFile.size,
      type: fileType,
      processedAt: new Date().toISOString()
    };
  } catch (error) {
    logger.error('File processing failed:', error);
    throw new Error(`File processing failed: ${error.message}`);
  }
};

5. 에러 처리 모범 사례

5.1 커스텀 에러 클래스 활용

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = 'ValidationError';
  }
}

class DatabaseError extends Error {
  constructor(message) {
    super(message);
    this.name = 'DatabaseError';
  }
}

5.2 에러 처리 미들웨어 (Express.js)

app.use((error, req, res, next) => {
  if (error instanceof ValidationError) {
    return res.status(400).json({
      error: error.message
    });
  }

  if (error instanceof DatabaseError) {
    return res.status(503).json({
      error: 'Service temporarily unavailable'
    });
  }

  // 기타 예상치 못한 에러
  logger.error('Unexpected error:', error);
  res.status(500).json({
    error: 'Internal server error'
  });
});

6. 결론

JavaScript에서의 효율적인 에러 처리는 예상 가능한 상황과 예상치 못한 에러를 구분하고, 적절한 위치에 try-catch를 사용하는 것이 핵심입니다. 이는 코드의 가독성을 높이고, 성능을 최적화하며, 더 견고한 애플리케이션을 만드는데 도움이 됩니다.

이러한 접근 방식은 현대적인 JavaScript 애플리케이션 개발에서 매우 중요하며, 특히 Node.js 기반의 서버 애플리케이션에서 더욱 그러합니다.

반응형