본문 바로가기

SPRING

(Java)assert

최근 아주 간단한 기본중에 기본만 구현하는 스프링 레거시 프로젝트를 개발일지에 남기면서, 유효성 검사를 하는 부분이 참 생각할게 많았다. 특히나 객체가 Null인지, 문자열이 공백인지 공백만 있는 문자열인지 등 간단한 기능이고 내가 완벽하게 구현하는게 아님에도 불구하고 시간이 걸리는 부분이 꽤 있었다.

자주 사용되는 (java)assert, (junit)Assert, (Spring)Assert, (junit)Assertions 는 assert의 주장하다 라는 뜻을 따라 유효성검사를 할때 자주 사용하는 것으로 알고 있는데, 내가 글을 작성 하는 이유는 저 네가지가 너무 헷갈리기 때문이다.

전부 비슷한 역할을 수행하는데 다 다른 애들이다...

대충의 사용법은 비슷하지만, 정확히 알고 제때 사용하기 위해 무엇이 다른지, 어떻게 사용하는게 좋을지 한번 정리해서 남겨본다.

1. Java의 키워드 assert

assert는 자바의 키워드(예약어)이다. 오라클의 문서 [oracle](https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html)를 참고 했다.

문서에서는 java의 assert는 두가지 형태로 사용 가능하다고 한다.

  1. assert Expression1 ;
    1. Expression1 에는 boolean 표현식이 위치해야 하고, false일 경우 AssertionError를 세부 메시지 없이 던진다.
  2. assert Expression1 : Expression2 ;
    1. Expression1에는 boolean 표현식이 위치
    2. Expression2는 값을 가지는 표현식이며 void로 선언된 메소드 호출은 불가능
    3. 이 형태에서는 AssertionError의 세부 메시지를 제공하는데, Expression2의 값을 AssertionError의 생성자로 전달하고, 생성자는 이 값을 문자열로 변환하여 세부 메시지로 사용한다

덧붙여 상세 메시지는 사용자 수준의 오류 메시지가 아니기 때문에 규격화 할 필요는 없고, (정확한 해석인지는 모르겠으나) 실패한 assertion을 포함한 소스코드와 전체 스택추적의 맥락에서 해석되어야 한다고 설명이 있다.

더 아래에, 프로그램이 시작될때 assertion을 활성화 하거나 비활성화 할수 있고, 기본값은 비활성화 라고 설명이 있는데 이 문장으로 보아 디버그시 assertion 에러가 있을때 해당 assertion이 위치한 곳과 프로그램 실행 경로를 같이 보면서 해석하라는 의미로 보인다. 디버그시 잘 참고해라~의 의미인것 같다.

다음으로 중요한 부분에 대한 설명이 있다.

  1. Assertions를 사용하는게 좋은 상황
    1. 내부 불변식
    2. 제어 흐름 불변식
    3. 전제조건, 사후조건(이 명칭이 정확한지는 모르겠다), 클래스 불변식
  2. 사용하는게 안 좋은 상황
    1. public 메서드에서 매개변수의 유효성 검사를 위한 경우
    2. 프로그램의 작동을 위해 필요한 작업에 assertion을 넣는 경우

위 내용 중 assert를 사용하는게 안 좋은 경우가 중요해 보인다.

두 경우 다 assert의 기본값이 비활성 상태이기 때문에 프로그램 실행시 assert가 효과를 가지지 못하기 때문에 안 좋은 상황이라고 표현하는듯 하다. 그리고 assert 사용시 false인 경우 AssertionError를 던지며 사용자가 지정한 문자열을 상세 메시지로 전달하기 때문에 적절한 예외를 확인 할수 없는 문제가 있다.

예를 들어


public class AssertTest {  

    public void assertTest(int num) throws Exception {  
        int positive = num;  
        try {  

            assert positive > 0 : "0 또는 음수입니다"; // 매개변수가 양수이길 원함  
            System.out.println(positive);  

        } catch (AssertionError e) {  

            System.out.println(e.getMessage());  

        }  

    }  

    public static void main(String[] args) throws Exception{  

        AssertTest assertTest = new AssertTest();  

        assertTest.assertTest(0);  

    }  
}

위 코드의 main()에서 asserTest.assertTest()의 매개변수로 0을 넣었으니 0 또는 음수입니다 메시지가 출력되길 기대하지만 실제로 jvm 실행시 assert는 실행되지 않기때문에 그냥 0이 출력된다.
(인텔리제이의 경우 디버그시에도 기본값이 비활성화다. 대부분 비활성이 기본값임을 확인.)

다만 vm옵션에서 -ea 로 활성화 해주면 assert를 사용하여 작성한 부분이 실행되어 0 또는 음수입니다 가 출력된다.

인텔리제이의 경우 run -> Edit Configurations -> Modify options -> Add VM options -> (VM options 입력창에) -ea를 입력 -> Apply -> OK

대부분의 경우 vm옵션에서 활성화 되어 있지 않은게 기본값이기 때문에 프로그램을 실행하는 환경이 달라졌을때 일관적인 결과를 보장할수 없기에 매개변수의 유효성검사나 프로그램의 작동을 위한 경우에는 사용하지 말라고 하는것 같다. 또한 적절한 예외 메시지를 받을 수 없다. 내가 지정한 메시지가 출력되고 지정하지 않은 경우 출력이 안된다...

따라서 확실한 목적을 가지고 개발 또는 디버그시 사용하는것이 좋아보인다.

'SPRING' 카테고리의 다른 글

하루종일 화가났던 Querydsl gradle 설정 오류에 대하여..  (0) 2024.07.22
(spring)Assert Class  (0) 2024.07.14
(Junit5)Assertions Class  (1) 2024.07.08
(Junit4)Assert Class  (0) 2024.07.08
의존성 주입 1  (0) 2024.04.29