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

C++ 예외 처리 심화

C++ 예외 처리 심화 — 중급

예외 처리 심화

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

예외 처리는 프로그램이 예상치 못한 상황에 직면했을 때 안정적으로 동작할 수 있도록 돕는 중요한 기술입니다. 실무에서는 다양한 예외 상황이 발생할 수 있으며, 이를 적절히 처리하지 않으면 프로그램이 비정상 종료되거나 데이터 손실이 발생할 수 있습니다. 예를 들어, 사용자가 입력한 데이터가 유효하지 않거나, 파일을 찾을 수 없거나, 네트워크 연결에 문제가 생길 수 있습니다. 이러한 상황에서 예외 처리를 통해 사용자에게 명확한 피드백을 제공하고, 시스템의 안정성을 높일 수 있습니다.

예외 처리를 모른다면, 프로그램이 중단되는 상황이 발생할 수 있으며, 이는 사용자 경험을 저해하고, 신뢰를 잃게 만들 수 있습니다. 따라서 예외 처리는 개발자에게 필수적인 스킬입니다.

2. 핵심 개념 설명

예외(Exception)

예외는 프로그램 실행 중 발생할 수 있는 예기치 않은 상황을 의미합니다. 이는 오류가 발생했음을 나타내며, 프로그램의 흐름을 변경할 수 있습니다.

try-catch 블록

try 블록 안에 코드를 작성하고, catch 블록을 통해 예외를 처리합니다. 마치 우리가 안전 장치를 갖춘 기계처럼, 예외 상황을 미리 대비하는 것입니다.

throw 키워드

throw 키워드는 예외를 발생시킬 때 사용합니다. 이는 마치 "불꽃이 튀는 것을 보았을 때 경고음을 울리는 것"과 같습니다.
용어설명
Exception예기치 않은 상황을 나타내는 객체
try예외 처리를 위한 코드 블록
catch예외를 처리하는 코드 블록
throw예외를 발생시키는 키워드

3. 기본 코드 예제

다음은 기본적인 예외 처리의 예제입니다.

#include <iostream>
#include <stdexcept> // std::runtime_error를 사용하기 위해 필요

int divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("0으로 나눌 수 없습니다."); // 예외 발생
    }
    return a / b;
}

int main() {
    try {
        std::cout << divide(10, 2) << std::endl; // 정상적인 나눗셈
        std::cout << divide(10, 0) << std::endl; // 0으로 나누기 시도
    } catch (const std::runtime_error& e) {
        std::cout << "예외 발생: " << e.what() << std::endl; // 예외 처리
    }
    return 0;
}

실행 결과:

5
예외 발생: 0으로 나눌 수 없습니다.

코드 한 줄씩 동작 설명:

  1. divide 함수가 두 개의 정수를 인자로 받아 나눗셈을 수행합니다.
  2. 만약 두 번째 인자가 0이라면, throw를 통해 예외를 발생시킵니다.
  3. main 함수에서 try 블록 안에서 divide 함수를 호출합니다.
  4. 첫 번째 나눗셈은 정상적으로 실행되어 5가 출력됩니다.
  5. 두 번째 나눗셈에서 예외가 발생하면, catch 블록으로 넘어가 예외 메시지를 출력합니다.
  6. 4. 실전 활용 예제

    1. 파일 읽기 예외 처리

    쇼핑몰에서 사용자 업로드 파일을 처리할 때, 파일이 존재하지 않거나 형식이 잘못된 경우를 처리합니다.

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

    2. 사용자 입력 예외 처리

    사용자가 나이 입력을 받을 때, 음수의 값을 입력했을 때 적절히 예외를 처리합니다.

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

    5. 흔한 실수와 주의사항

    1. catch 블록 생략

    try {
        // 코드
    } // catch 블록을 작성하지 않으면 예외가 처리되지 않음

    올바른 코드:

    try {
        // 코드
    } catch (const std::exception& e) {
        std::cout << e.what() << std::endl; // 예외 처리
    }

    2. throw 없이 예외 발생

    예외를 발생시키지 않고 단순히 오류 메시지를 출력하는 경우, 프로그램의 흐름이 계속 진행됩니다.

    if (b == 0) {
        std::cout << "0으로 나눌 수 없습니다." << std::endl; // 예외 발생 안 함
    }

    올바른 코드:

    if (b == 0) {
        throw std::runtime_error("0으로 나눌 수 없습니다."); // 예외 발생
    }

    6. 정리

    • 예외 처리는 프로그램의 안정성을 높이는 중요한 기술입니다.
    • try, catch, throw를 이용해 예외를 처리하는 방법을 배웠습니다.
    • 파일 처리와 사용자 입력에서 예외 처리의 필요성을 이해했습니다.
    • 흔한 실수로는 catch 블록 생략과 예외 발생 없이 오류 메시지만 출력하는 것입니다.
    • 다음에 학습하면 좋은 주제:

    • 사용자 정의 예외 클래스 만들기
    • 여러 개의 catch 블록 사용하기
    • 예외 안전성(예: RAII) 다루기