IMCAT.DEV
로그인 가입
C++ 입문 문법

C++ 기본적인 예외 처리

C++ 기본적인 예외 처리 — 초급

C++ 기본적인 예외 처리

1. 도입 (왜 배워야 하는가)

C++에서 예외 처리는 프로그램의 안정성과 신뢰성을 높이는 중요한 기술입니다. 실무에서 복잡한 시스템을 개발할 때, 예외 처리 없이 코드를 작성한다면 예상치 못한 오류로 인해 프로그램이 비정상적으로 종료될 수 있습니다. 예를 들어, 파일을 열 때 해당 파일이 존재하지 않거나, 사용자 입력 값이 잘못된 경우가 있을 수 있습니다. 이러한 상황에서 적절한 예외 처리를 하지 않으면 프로그램의 사용자는 불편을 겪고, 개발자는 수많은 디버깅 작업을 해야 합니다. 따라서 예외 처리를 통해 오류 발생 시 적절한 대처를 할 수 있도록 만드는 것이 필수적입니다.

2. 핵심 개념 설명

예외 처리란 프로그램 실행 중 발생할 수 있는 오류를 관리하는 방법입니다. C++에서는 try, catch, throw 키워드를 사용하여 예외를 처리합니다.

  • try: 예외가 발생할 가능성이 있는 코드 블록을 정의합니다.
  • catch: 특정 예외가 발생했을 때 실행될 코드를 정의합니다.
  • throw: 예외를 발생시키는 데 사용됩니다.
  • 실생활 비유

    예를 들어, 당신이 음식을 주문하는 상황을 생각해봅시다. 만약 레스토랑에서 음식을 주문했는데 재료가 떨어졌다면, 직원이 "죄송하지만 이 메뉴는 더 이상 제공되지 않습니다"라고 말하는 것이 catch에 해당합니다. 이때 직원은 고객에게 다른 메뉴를 추천하거나, 다음에 주문할 수 있도록 안내할 수 있습니다. 이처럼 예외 처리는 시스템이 예외적인 상황을 만났을 때 어떻게 반응해야 할지를 정의합니다.

    관련 용어 정리

    용어설명
    예외프로그램 실행 중 발생할 수 있는 오류 상황
    예외 처리예외 발생 시 어떻게 대처할 것인지 정의하는 것
    예외 객체발생한 예외에 대한 정보를 담고 있는 객체

    3. 기본 코드 예제

    아래는 기본적인 예외 처리 방법을 보여주는 코드입니다.

    #include <iostream>
    #include <stdexcept> // 예외 처리 관련 헤더
    
    int divide(int a, int b) {
        if (b == 0) {
            throw std::invalid_argument("0으로 나눌 수 없습니다."); // 예외 발생
        }
        return a / b; // 나누기 연산
    }
    
    int main() {
        try {
            std::cout << divide(10, 2) << std::endl; // 정상적인 나누기
            std::cout << divide(10, 0) << std::endl; // 예외 발생
        } catch (const std::invalid_argument& e) {
            std::cerr << "오류: " << e.what() << std::endl; // 예외 처리
        }
        return 0;
    }

    실행 결과

    5
    오류: 0으로 나눌 수 없습니다.

    코드 한 줄씩 동작 설명

    1. #include <iostream>: 입출력 스트림을 사용하기 위한 헤더 파일을 포함합니다.
    2. #include <stdexcept>: 표준 예외 클래스를 사용하기 위한 헤더 파일을 포함합니다.
    3. int divide(int a, int b): 두 정수를 나누는 함수를 정의합니다.
    4. if (b == 0): 분모가 0인지 확인합니다.
    5. throw std::invalid_argument("0으로 나눌 수 없습니다.");: 분모가 0일 경우 예외를 발생시킵니다.
    6. return a / b;: 정상적인 경우 나눈 값을 반환합니다.
    7. int main(): 프로그램의 시작점인 메인 함수를 정의합니다.
    8. try { ... }: 예외가 발생할 수 있는 코드 블록을 감싸서 처리합니다.
    9. std::cout << divide(10, 2) << std::endl;: 정상적으로 나누기를 수행하고 결과를 출력합니다.
    10. std::cout << divide(10, 0) << std::endl;: 예외를 발생시키는 나누기를 수행하려고 합니다.
    11. catch (const std::invalid_argument& e): 발생한 예외를 처리하는 블록입니다.
    12. std::cerr << "오류: " << e.what() << std::endl;: 예외 메시지를 출력합니다.
    13. 4. 실전 활용 예제

      예제 1: 파일 열기

      쇼핑몰 시스템에서 사용자가 요청한 상품 정보를 파일에서 읽어올 때, 파일이 존재하지 않거나 읽기 권한이 없을 경우 예외 처리를 통해 안정성을 높일 수 있습니다.

      #include <iostream>
      #include <fstream>
      #include <stdexcept>
      
      void readFile(const std::string& filename) {
          std::ifstream file(filename);
          if (!file.is_open()) {
              throw std::runtime_error("파일을 열 수 없습니다."); // 예외 발생
          }
          // 파일 읽기 로직...
      }
      
      int main() {
          try {
              readFile("nonexistent.txt"); // 존재하지 않는 파일
          } catch (const std::runtime_error& e) {
              std::cerr << "오류: " << e.what() << std::endl; // 예외 처리
          }
          return 0;
      }

      예제 2: 사용자 입력 검증

      사용자로부터 나이 정보를 입력받을 때, 음수나 비정상적인 값이 입력되면 예외를 발생시켜 처리합니다.

      #include <iostream>
      #include <stdexcept>
      
      void setAge(int age) {
          if (age < 0) {
              throw std::invalid_argument("나이는 음수가 될 수 없습니다."); // 예외 발생
          }
          std::cout << "나이: " << age << std::endl;
      }
      
      int main() {
          try {
              setAge(-5); // 잘못된 나이 입력
          } catch (const std::invalid_argument& e) {
              std::cerr << "오류: " << e.what() << std::endl; // 예외 처리
          }
          return 0;
      }

      5. 흔한 실수와 주의사항

      실수 1: 예외를 무시하기

      예외를 발생시키고 catch 블록에서 아무런 처리도 하지 않는 경우.

      try {
          throw std::runtime_error("예외 발생");
      } catch (...) {
          // 아무 처리도 하지 않음
      }

      -> 올바른 코드: 예외를 무시하지 말고 적절한 메시지나 대체 행동을 정의해야 합니다.

      실수 2: 잘못된 예외 타입

      예외를 처리할 때 잘못된 타입을 사용하는 경우.

      try {
          throw std::invalid_argument("잘못된 인자");
      } catch (const std::runtime_error& e) { // 잘못된 타입
          std::cerr << e.what() << std::endl;
      }

      -> 올바른 코드: 예외 타입에 맞는 catch 블록을 사용해야 합니다.

      6. 정리

    14. 예외 처리는 프로그램의 안정성과 신뢰성을 높이는 중요한 기술입니다.
    15. try, catch, throw를 사용하여 예외를 처리합니다.
    16. 예외 발생 시 적절한 대처를 통해 사용자에게 친숙한 경험을 제공합니다.
    17. 다음에는 C++의 사용자 정의 예외 처리나, 예외 안전성을 높이기 위한 RAII 패턴을 학습하는 것을 추천합니다.