Java 예외 처리 - try-finally와 try-with-resources
Java 예외 처리
Java에서 예외를 처리하고 리소스를 안전하게 관리하는 방법을 살펴봅니다.
try-finally 패턴
사용 이유
메서드를 끝낼 때 처리해야 할 작업이 있는데, 여러 분기에서 return하는 경우를 생각해 봅시다.
문제 상황:
public void process() {
Resource resource = acquire();
if (condition1) {
cleanup(); // 정리 코드 중복
return;
}
if (condition2) {
cleanup(); // 정리 코드 중복
return;
}
// 처리 로직
cleanup(); // 정리 코드 중복
}
해결책 - finally 사용:
public void process() {
Resource resource = acquire();
try {
if (condition1) {
return;
}
if (condition2) {
return;
}
// 처리 로직
} finally {
cleanup(); // 한 번만 작성
}
}
finally 블록은 어떤 경로로 메서드를 빠져나가든 항상 실행됩니다.
리소스 관리
전통적인 방식 (try-finally)
private static void printFile() throws IOException {
InputStream input = null;
try {
input = new FileInputStream("file.txt");
int data = input.read();
while (data != -1) {
System.out.print((char) data);
data = input.read();
}
} finally {
if (input != null) {
input.close();
}
}
}
개선된 방식 (try-with-resources, Java 7+)
AutoCloseable 인터페이스를 구현한 리소스는 자동으로 닫힙니다.
private static void printFile() throws IOException {
try (InputStream input = new FileInputStream("file.txt")) {
int data = input.read();
while (data != -1) {
System.out.print((char) data);
data = input.read();
}
}
// input.close()가 자동 호출됨
}
여러 리소스 관리
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
String line;
while ((line = reader.readLine()) != null) {
fos.write(line.getBytes());
}
}
// 모든 리소스가 역순으로 자동 close됨
try-catch-finally 실행 순서
try {
// 1. 정상 실행 시도
riskyOperation();
} catch (Exception e) {
// 2. 예외 발생 시 실행
handleException(e);
} finally {
// 3. 항상 실행 (정상/예외 모두)
cleanup();
}
return과 finally
public int getValue() {
try {
return 1;
} finally {
System.out.println("finally 실행"); // return 전에 실행됨
}
}
주의: finally에서 return하면 try의 return을 덮어씁니다 (권장하지 않음).
예외 처리 모범 사례
1. 구체적인 예외 잡기
// 좋음
try {
readFile();
} catch (FileNotFoundException e) {
// 파일 없음 처리
} catch (IOException e) {
// 기타 IO 오류 처리
}
// 나쁨
try {
readFile();
} catch (Exception e) {
// 모든 예외를 동일하게 처리
}
2. 예외 정보 보존
try {
// ...
} catch (IOException e) {
throw new MyException("파일 처리 중 오류", e); // 원인 예외 포함
}
3. 리소스는 try-with-resources 사용
// 권장
try (Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
// ...
}
정리
| 패턴 | 사용 시점 |
|---|---|
| try-catch | 예외를 처리해야 할 때 |
| try-finally | 정리 작업이 필요할 때 |
| try-with-resources | AutoCloseable 리소스 관리 |
| try-catch-finally | 예외 처리와 정리 작업 모두 필요할 때 |
Java 7 이상에서는 리소스 관리에 반드시 try-with-resources를 사용하세요. 코드가 간결해지고 리소스 누수를 방지할 수 있습니다.
Comments