본문으로 건너뛰기
개발 머꼬
개발 노트Java
hohyeon.dev19

try에서 return했는데 finally의 return 값이 나온 이유

  • #Common Pitfall
  • #Engineering Note
  • #Java

문제 발생

다음 메서드가 항상 false만 반환해서 원인을 찾다가, finally 블록의 return이 범인이라는 것을 발견했습니다.

public boolean process() {
    try {
        return true;
    } finally {
        return false; // 항상 이 값이 최종 반환됨
    }
}

원인 분석

finally 블록은 try(그리고 catch)가 어떤 방식으로 끝나든(정상 return, 예외 발생 등) 항상 실행되도록 설계되어 있습니다. 문제는 finally 안에 return문이 있으면, 그 returntry/catch에서 이미 결정된 반환값이나 발생한 예외를 완전히 덮어써버린다는 점입니다.

심지어 try 블록에서 예외가 발생했더라도, finallyreturn이 있으면 그 예외는 전파되지 않고 조용히 삼켜집니다 — 이건 더 위험한 함정입니다. 예외가 발생했다는 사실 자체가 사라지므로 디버깅이 극도로 어려워집니다.

public int risky() {
    try {
        throw new RuntimeException("문제 발생");
    } finally {
        return 0; // 예외가 무시되고 0이 반환됨 — 예외가 삼켜짐
    }
}

해결 방안

  1. finally 블록 안에 return/break/continue를 쓰지 않는 것을 원칙으로 합니다. 대부분의 정적 분석 도구(SonarQube, IntelliJ 검사 등)가 이 패턴을 경고로 잡아줍니다.
  2. finally는 리소스 정리(파일 닫기, 락 해제 등) 용도로만 씁니다 — 반환값 결정 로직은 try/catch 안에서 끝내야 합니다.
  3. try-with-resources를 쓸 수 있는 상황(Closeable 리소스)이라면 finally로 직접 close()를 호출하는 대신 그쪽을 우선 씁니다 — 이 함정 자체를 피할 수 있습니다.
  4. 이미 있는 코드에서 이 패턴을 발견했다면, 왜 finallyreturn을 넣었는지(의도적인지 실수인지) 먼저 확인하고, 실수라면 조기에 고쳐야 합니다 — 이런 코드는 겉보기엔 멀쩡히 컴파일되고 실행되어 리뷰에서 놓치기 쉽습니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.