본문 바로가기

소프트웨어

Checked vs Unchecked Exception

반응형

checked 와 unchecked exception 에 대해서 간단하게 정리해보겠습니다.

 

 

우선, Exception은 Error와 구분되는데요.

Error는 시스템 레벨에서 발생하는 심각한 오류를 말하고, 예측할 수 없으며 App에서 오류에 대한 처리를 할 수도 없고 할 필요도 없습니다.

 

반면에 Exception은 프로그래머가 구현한 로직에서 발생하는 오류입니다. 당연히 미리 예측도 가능하고 처리를 하는 것이 좋죠.

 

Error는 개발자가 처리할 수 없으니, Exception에 집중하겠습니다.

Exception은 checked와 unchecked 두 가지로 크게 나눕니다.

 

 

두 Exception을 비교해보면,,,

 

Unchecked Exception

RuntimeException을 상속

예외처리를 하지 않아도 문법적인 문제가 없음

실행단계에서 Exception 발생 여부를 확인

ex) NullPointerException, IllegalArgumentException, IndexOutOfBoundException, ...

 

Checked Exception

Exception 상속하면서 RuntimeException 상속하지 않음

예외처리를 하지 않으면 문법적인 문제가 발생, try ... catch 혹은 throws 처리 필요

컴파일단계에서 Exception 발생 여부를 확인

ex) IOException, SQLException


궁금증..

 

Spring Boot 프로젝트에서 Custom Exception을 만들때 습관적으로 RuntimeException을 상속하도록 했는데... 여기서 RuntimeException, Unchecked Exception이 아닌 Exception을 발생시키면 어떤 차이가 있을까요..?

 

Test를 해봤습니다.

 

@Service
public class CokeService {
    @Autowired
    private CokeRepository cokeRepository;

    @Transactional
    public void saveAndRuntimeException(Coke coke) {
        cokeRepository.save(coke);
        throw new RuntimeException("RuntimeException for debugging");
    }

    @Transactional
    public void saveAndException(Coke coke) throws Exception {
        cokeRepository.save(coke);
        throw new Exception("Exception for debugging");
    }
}

 

@SpringBootTest
class CokeServiceTest {
    @Autowired
    private CokeService cokeService;

    @Autowired
    private CokeRepository cokeRepository;

    @Test
    public void uncheckedExceptionTransactionTest() throws Exception {
        // clear
        cokeRepository.deleteAll();
        
        // RuntimeException
        try {
            cokeService.saveAndRuntimeException(Coke.builder()
                    .volume(500)
                    .name("cocacola")
                    .build()
            );
        } catch (RuntimeException ex) {
            ex.printStackTrace();
        }
        assertEquals(0, cokeRepository.findAll().size());
        
        // Exception 
        try {
            cokeService.saveAndException(Coke.builder()
                    .volume(1000)
                    .name("pepsi")
                    .sparkling(0.5)
                    .build()
            );
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        assertEquals("pepsi", cokeRepository.findAll().get(0).getName());
    }
}

 

RuntimeException, Exception을 각각 발생시켜서 rollback이 되는지 테스트해봤는데요,, 테스트는 통과합니다.

 

결론적으로, Spring은 Transaction 도중 RuntimeException이 발생하면 자동으로 rollback 하고 Exception의 경우는 그렇지 않습니다. 습관적으로 RuntimeException을 상속했었는데, 이제 근거를 알게 되었네요.

 

물론 @Transactional annotation의 rollbackFor 속성을 설정해주면 다른 Exception도 충분히 가능합니다.

 

 

 

 

반응형