본문 바로가기
language/java

Java try-with-resources 원리 완벽 이해하기

by 죄니안죄니 2026. 5. 29.
반응형

Java try-with-resources 원리 완벽 이해하기

Java 7부터 도입된:

try-with-resources

는 현대 Java에서 파일, 네트워크, DB 연결 등을 다룰 때 거의 필수로 사용됩니다.

실무에서는:

  • JDBC Connection
  • PreparedStatement
  • ResultSet
  • FileInputStream
  • BufferedReader

등을 처리할 때 대부분 사용합니다.

예:

 
try (
    BufferedReader br =
        new BufferedReader(
            new FileReader("test.txt")
        )
) {

    System.out.println(br.readLine());
}
 

이 문법은 단순한 문법 설탕(Syntactic Sugar)이 아닙니다.

실제로는:

  • AutoCloseable
  • 컴파일러 코드 변환
  • finally 자동 생성
  • Suppressed Exception

까지 연결되는 중요한 JVM 동작 원리입니다.


1. 왜 등장했을까?

Java 6 이전에는:

 
BufferedReader br = null;

try {

    br = new BufferedReader(
        new FileReader("test.txt")
    );

} finally {

    if (br != null) {
        br.close();
    }
}
 

처럼 작성했습니다.


2. 문제점

매우 많았습니다.

코드가 길다

 
if (br != null)
 

반복.


close 누락 가능

 
connection.close();
 

실수로 빠뜨릴 수 있음.


예외 덮어쓰기 문제

매우 중요.


3. 예외 덮어쓰기 문제

예:

 
try {

    throw new RuntimeException("원래 예외");

} finally {

    throw new RuntimeException("close 예외");
}
 

4. 결과

close 예외만 보임
 

5. 문제

원래 예외가 사라짐.

즉:

진짜 원인 분실
 

발생.


6. 그래서 등장

Java 7:

 
try-with-resources
 

추가.


7. 기본 문법

 
try (
    Resource resource = ...
) {

}
 

8. 특징

try 블록 종료 시
자동 close()
 

수행.


9. 어떤 객체가 가능할까?

매우 중요.


10. AutoCloseable

AutoCloseable 인터페이스 구현 필요.


11. 정의

 
public interface AutoCloseable {

    void close() throws Exception;
}
 

12. 즉

 
implements AutoCloseable
 

만 하면 사용 가능.


13. 예시

 
class MyResource
    implements AutoCloseable {

    @Override
    public void close() {

        System.out.println("close");
    }
}
 

14. 사용

 
try (
    MyResource r = new MyResource()
) {

    System.out.println("work");
}
 

15. 결과

work
close
 

16. 컴파일러 내부 변환

매우 중요합니다.

실제로 JVM에선:

 
try (
    Resource r = ...
) {

}
 

를 직접 실행하지 않음.


17. 컴파일 후

대략 아래 코드로 변환.

 
Resource r = ...;

try {

} finally {

    if (r != null) {
        r.close();
    }
}
 

18. 즉

컴파일러가 finally 생성
 

해주는 것.


19. close 실행 시점

순서:

try 실행
↓
정상 종료
↓
close()
 

20. 예외 발생 시

try 예외
↓
close()
↓
예외 전파
 

21. 여러 리소스 사용 가능

예:

 
try (

    Connection conn = ...;
    PreparedStatement ps = ...;
    ResultSet rs = ...

) {

}
 

22. close 순서

매우 중요.


23. 생성 순서

 
conn
↓
ps
↓
rs
 

24. close 순서

반대.

rs
↓
ps
↓
conn
 

25. 왜 반대일까?

스택 구조 때문.


26. 비유

접시 쌓기
 

와 같음.

마지막에 올린 것부터 제거.


27. JDBC에서 중요한 이유

예:

 
ResultSet
 

 
PreparedStatement
 

에 의존.


28. 먼저 닫으면?

의존성 문제
 

발생 가능.


29. 그래서 역순 close

안전.


30. Suppressed Exception

매우 중요합니다.


31. 예시

 
try (
    MyResource r = ...
) {

    throw new RuntimeException("원래 예외");
}
 

32. close도 실패

 
public void close() {

    throw new RuntimeException(
        "close 실패"
    );
}
 

33. 예전 finally 방식

close 실패만 보임
 

34. try-with-resources

원래 예외 유지
+
close 예외 보관
 

35. 이것이 Suppressed Exception

Suppressed exception


36. 구조

Main Exception
 └─ Suppressed Exception
 

37. 확인 방법

 
Throwable[] suppressed =
    e.getSuppressed();
 

38. 예시 출력

 
for (Throwable t :
     e.getSuppressed()) {

    System.out.println(
        t.getMessage()
    );
}
 

39. 왜 중요할까?

실제 장애 분석 시:

원래 예외
+
close 예외
 

둘 다 확인 가능.


40. JDBC 실무 예시

가장 흔한 패턴.

 
try (

    Connection conn =
        dataSource.getConnection();

    PreparedStatement ps =
        conn.prepareStatement(sql);

    ResultSet rs =
        ps.executeQuery()

) {

    while (rs.next()) {

    }
}
 

41. 장점

자동 close
 

42. 누수 방지

Connection Leak 감소
 

43. 코드 간결

finally 제거
 

44. 파일 처리도 동일

 
try (
    BufferedReader br =
        Files.newBufferedReader(path)
) {

}
 

45. 실무에서 자주 하는 실수

1) close 직접 호출

 
try-with-resources
 

안에서:

 
resource.close();
 

직접 호출.

불필요.


2) AutoCloseable 미구현

컴파일 오류.


3) close 예외 무시

Suppressed Exception 확인 안 함.


4) try 밖에서 리소스 생성

안 좋은 예:

 
Connection conn =
    getConnection();

try(conn) {

}
 

가능은 하지만 보통 생성도 try 안에서.


46. Closeable vs AutoCloseable

많이 물어봄.


AutoCloseable

 
void close() throws Exception
 

Closeable

 
void close() throws IOException
 

47. 관계

AutoCloseable
    ↑
 Closeable
 

48. Stream도 AutoCloseable

예:

 
Files.lines(path)
 

49. 그래서 가능

 
try (
    Stream<String> stream =
        Files.lines(path)
) {

}
 

50. 실무 핵심 규칙

매우 중요.

AutoCloseable 객체는
무조건 try-with-resources 우선
 

51. 핵심 흐름 요약

리소스 생성
↓
try 실행
↓
예외 여부 관계없이
↓
자동 close()
↓
예외 전파
 

52. 가장 중요한 핵심 한 줄

try-with-resources는
컴파일러가 finally + close 로직을 자동 생성하고,
Suppressed Exception까지 안전하게 처리하는 기능이다
 

53. 면접 단골 질문

Q. try-with-resources를 쓰려면 무엇을 구현해야 하나?

 
AutoCloseable
 

Q. 여러 리소스가 있으면 close 순서는?

생성 역순
 

Q. 왜 finally보다 좋은가?

Suppressed Exception 지원
+
누수 방지
+
코드 간결
 

다음 글에서는 "커스텀 예외(Custom Exception) 설계" 를 진행하면 지금까지 배운 Exception 구조, Checked/Unchecked, Spring RuntimeException 전략이 전부 연결되기 시작합니다. 실무에서 가장 많이 사용하는 예외 설계 패턴까지 함께 다룰 수 있습니다.

반응형

댓글