플러터 앱 개발

Chapter 12. 예외 처리

yuna 2026. 1. 13. 22:14

안녕하새우

오늘은 예외처리를 정리해보려고 하는데요!

 

 

어딜 가나 항상 예외는 있죠!!

하지만 코딩은 예외의 상황에 굉장히 민감한 친구이기 때문에

미리 예외 처리를 진행해 주면 좀 더 단단한 코드 작성이 가능합니다 :)

그럼 레쓰고 - !


1. 예외

: 프로그램이 실행되는 동안 발생할 수 있는 예외적인 상황

 

특징

  • 실행 중에 예상치 못한 문제가 생겼을 때 앱이 종료되지 않고, 대신 정해둔 방식으로 처리하는 것
  • 모든 종류의 예외는 Exception 클래스를 상속 받아서 구성
  • 예외가 어떤 타입의 예외인지 명확하게 하기 위해서 Exception클래스를 상속 받은 클래스로 객체를 생성해 주는 것이 좋음

예외의 상황

  • 인터넷 요청이 실패함(네트워크 끊김)
  • 파일이 없음/권한이 없음
  • JSON 파싱 실패(형식이 이상함)
  • 등등...

종류

1. Dart가 미리 정의해 둔 예외

  • DeferredLoadException
    • 필요한 시점에 로드되도록 설정한 라이브러리가 로드되지 못했을 때 발생
    • 형태: DeferredLoadException(String message)
  • FormatException
    • 데이터가 처리 가능한 형태가 아니어서 데이터를 처리하기 어려울 때 발생
    • 형태: FormatException([String message = "", dynamic source, int? offset])
    • message: 예외에 대한 설명 / source: 예외가 발생한 원인이 되는 것
  • IOException
    • 입출력 관련 동작을 하는 중에 발생하는 오류
    • 형태: IOException( )
    • FileSystemException: 파일을 다룰 때 발생
    • HttpException
    • ProcessException
    • SignalException
    • SocketException
    • StdinException
    • StdoutException
    • TlsException
    • WebSocketException
  • OSError
    • 운영체제 레벨에서 발생하는 오류
    • 운영체제로부터 받은 오류에 대한 정보를 가지고 있음!
    • 형태: OSError([String message = "", int errorCode = noErrorCode])
  • TimeoutException
    • 비동기 결과를 기다리는 동안 특정 시간이 초과되었을 때 발생
    • 형태: TimeoutException(String? message, [Duration? duration])

2. 사용자가 직접 정의한 예외

  • Dart가 정의한 예외들 외에 내가 직접 커스텀하고 싶을 때 쓴다.
  • Exception 클래스를 상속 받아서 새로운 예외 클래스를 만든다.
  • 예외 클래스도 @override를 통해 재정의 가능
class AgeException implements Exception {
  final String? message;
  
  AgeException(this.message);
}

void printAge(int age) {
	if (age < 0) {
	 throw AgeException(null);
	}
  print(age);
}

void main() {
	try {
	 printAge(-8);
	} catch (e) {
     print(e);
  }
}

 

예외에 사용하는 키워드

1. 발생한 예외를 처리하기 위한 경우

  • try
    • 예외가 발생할 수 있는 코드를 넣는 부분
    • 예외 처리 구문을 쓸 때 꼭 넣어야 함
    • try의 코드 블록 실행 중에 예외가 발생하면 try의 코드 블록에 있는 뒷 코드들은 실행되지 않는다.
    • try{ }
  • catch
    • try의 코드 블록 실행 중에 예외가 발생했을 때 실행할 코드를 넣는 부분
    • try의 코드 블록에서 예외가 발생하지 않으면 실행되지 않는다.
    • 예외 처리 구문을 쓸 때 꼭 넣어야 하고, 개수에 제한이 없다.
    • catch (e) {
      print(e);
      }
  • on
    • try의 코드 블록에서 발생할 수 있는 예외 중 특정 타입의 예외를 다루는 부분
    • 예외 처리 구문을 쓸 때 넣지 않아도 된다.
    • 단독으로 사용할 수 없고, catch와 항상 같이 써야 한다.
    • 예외 타입이 특정되기 때문에 catch에 객체가 전달되었을 때 그 객체를 가지고 할 수 있는 동작이 더 많다.
    • on IOException catch (e) {
      // IOException 이 발생했을 때 실행할 코드
      }
  • finally
    • 예외 발생 여부와 상관 없이 실행할 코드를 넣는 부분
    • try, catch를 모두 거친 후에 실행
    • 예외 처리 구문을 쓸 때 넣지 않아도 된다.
    • final { }
try {
	String invalidNumber = "abc";
	int result = int.parse(invalidNumber);
	print(result);
} catch (e) {
	print(e);
}

 

  • throw
    • 특정 경우에 예외를 의도적으로 발생시키기 위해 Exception 클래스나 Error 클래스를 통해 생성한 객체를 던져요
    • Exception 클래스나 Error 클래스를 상속 받은 클래스도 가능

특징

  • throw를 통해 발생된 예외는 try, catch, on으로 처리할 수 있다.
void printAge(int age) {
  if (age < 0) {
    throw Exception('나이는 0 이상이어야 해요 !');
  }
  print(age);
}

void main() {
  try {
    printAge(-8);
  } catch (e) {
    print(e);
  }
}

 

2. 오류

: 주로 프로그램 외부의 환경이나 시스템 레벨에서 발생하는 심각한 문제

 

특징

  • 모든 종류의 오류는 Error 클래스를 상속 받아서 구성
  • 발생하면 프로그램이 정상적으로 실행되기 어렵기 때문에 발생되지 않도록 해야한다.
  • 발생을 예상하거나 처리할 수 없어서 프로그램을 종료하는 것이 가장 최선의 방법

종류

1. Dart가 미리 정의해 둔 오류

  • ArgumentError: 허용되지 않는 인자를 함수에 전달했을 때 발생
  • AssertionError: assert( ) 문의 매개변수에 전달하는 조건문이 거짓일 때 발생
    • assert( ): 매개변수에 넣은 조건문이 참이면 정상적으로 실행이 계속 되고, 조건문이 거짓이면 예외(AssertionError)를 발생
    • 주로 논리적인 오류를 잡아낼 때 사용
    • assert([조건문]);
      • assert(urlString.startsWith('https'));
    • assert([조건문], '[메시지]');
      • assert(number < 100, '100 이상이면 안 됨 !');
  • RangeError
  • IndexError
  • NoSuchMethodError
  • OutOfMemoryError
  • StackOverflowError
  • StateError
  • TypeError
  • UnimplementedError
  • UnsupportedError

-> 오늘은 종류만 익히고 그때 그때 필요할 때 검색해서 알아가면 됩니다~!

2. 사용자가 직접 정의한 오류

  • Error 클래스를 상속 받아서 새로운 오류 클래스를 만들면 된다!