IBM Korea Skip to main content
       IBM 홈    |  제품 & 서비스  |  고객지원 & 다운로드  |  회원가입  

Magic with Merlin: 표명 기능 이용하기
목 차:
assert 키워드
표명 활성화하기
표명을 사용하기 위한 다른 방법들
프로그램적으로 활성화시키기
결론
참고 자료
필자 소개
기사에 대한 평가
관련 dW 링크:
Ant와 JUnit를 사용한 점진적 개발I
Magic with Merlin 컬럼
자바 멤버 기능 문서화하기
alphaWorks의 JATE
US 원문 읽기
자바 코드에서 표명을 활성화/비활성화시키는 방법

John Zukowski
사장, JZ Ventures, Inc.
2002년 2월

Merlin은 테스팅 향상을 위해 메소드에 사전 조건 및 사후 조건에 따른 검증 기능을 선택 사항으로 제공한다. 표명 (assertion) 기능은 실행시에 기본적으로 비활성화되어 있지만, 에러 조건을 체크하기 위해 활성화될 있다. John Zukowski는 여러분 코드에 표명에 의한 검사 기능을 추가하기 위한 기본적인 사항과, 명령행으로 그리고 프로그램적으로 표명을 활성화하고 비활성화시키는 방법에 관해 설명하겠다.

표명 기능은 Java 1.4판에서 열렬하게 기다려지던 새 기능이다. 여러분은 표명을 향상된 예외 처리 기능이라고 생각하면 된다. 표명이란 불리언 표현식으로서, 프로그래머가 프로그램의 특정 지점에서 참이 되어야 한다고 믿는 바를 표현한다. 예를 들어, 프로그래머는 switch 문에서 default 조건에 도달하지 않아야 한다는 표명을 포함시킬 수 있다.

표명 검증은 어떤 시점에서도 활성화/비활성화될 수 있기 때문에, 표명이 활성화된 상태에서 테스트를 하고 표명이 비활성화된 채로 배치할 수 있다. 마찬가지로 사용자는 실행 중인 프로그램에서 문제를 만났을 때 표명을 재활성화할 수 있다.

이번 컬럼에서 나는 여러분 코드에 표명을 추가하기 위한 기본적인 사항들을 소개하고, 최적의 코드 테스팅과 성능을 위해 표명을 활성화하고 비활성화시키는 두 개의 다른 방법을 보여 주겠다.

assert 키워드

표명 검사는 예외 처리와 비슷하지만, 표명이 실패했을 때 어떤 예외 상황도 발생하지 않는다. 대신 AssertionError가 주어진다. 모든 에러와 마찬가지로 표명 장애에서의 복구는 불가능하지는 않다 하더라도 어렵다. 그러한 장애는 프로그램 상태가 정상적인 작업 매개변수를 벗어났다는 뜻이기 때문이다.

표명을 사용하기 위한 두 가지 기본 생성자는 다음과 같다.:


assert booleanExpression;
assert booleanExpression : message;

발생되는 에러의 결과로 선택적으로 메시지가 나타난다는데 주의한다.

여러분은 표명 구문을 메소드의 사전 조건이나 사후 조건으로 추가할 수 있다. 또한 메소드를 호출하기 위해 불리언 표현식을 설정할 수 있다. 또한 조건이 가정된 if 블록 내의 else 조건이나 결코 도달하지 않을 switch 구문의 default 절에 표명을 추가할 수도 있다. assert 키워드에 대한 유일한 제한 사항은 실행될 수 있는 블록에 있어야 한다는 것이다. 표명은 인스턴스에 대한 클래스 변수 선언에 사용될 수 없지만, 어떤 메소드에도 둘 수 있다.

표명 활성화하기

여러분이 표명을 사용하고 싶다면 프로그램을 컴파일하고 실행시키기 위해 몇 가지 특수한 명령행 옵션을 써야 할 것이다. 컴파일러가 1.3 호환 모드에서 작동하기 때문에 여러분은 명확하게 1.4 모드를 요청해야 한다. 표명이 포함된 프로그램을 컴파일하려면 간단히 자바 컴파일러에게 -source 1.4 설정을 보내면 된다. 표명 검사는 기본적으로 비활성화되어 있다. 따라서 여러분은 또한 실행시에 이 기능을 분명하게 활성화시켜야 할 것이다. 표명 검사를 활성화시키려면 -enableassertions 옵션이나 좀 더 짧은 -ea 옵션을 사용한다.

다음의 간단한 예제는 여러분 프로그램에 표명 검사를 추가하기 위해 필요한 단계들을 보여 주는데, 명령행 인자의 수를 체크하고 인자가 0이 아닌 경우 문제를 보고한다.:


public class AssertTest {
  public static void main(String args[]) {
    assert args.length == 0 : args.length + " != 0";
    System.out.println(args.length);
  }
}

프로그램을 컴파일하려면 다음과 같이 -source 옵션을 사용해야 한다.:


javac -source 1.4 AssertTest.java

프로그램을 테스트하려면 단지 프로그램을 실행시키고 명령행 인자를 보내면 된다.:


java AssertTest 1 2 3 4

프로그램은 인자의 갯수를 표시하기 때문에 이 테스트는 4를 보고할 것이다. 표명 검사는 기본적으로 비활성화되어 있기 때문에 어떤 표명 에러도 추적되지 않는다.

이제 표명 검사가 활성화된 프로그램을 실행시켜 보자.:


java -ea AssertTest 1 2 3 4

표명 검사가 활성화된 프로그램을 실행시키면 다음과 같은 에러 리포트가 나온다.:


Exception in thread "main" java.lang.AssertionError: 1 != 0
        at AssertTest.main(AssertTest.java:3)

본질적으로 이것이 표명 기능의 전부이다. 가장 어려운 부분은 assert 키워드를 어디에 두어야 하는지와 조건이 무엇인지를 아는 것이다.

표명을 사용하기 위한 다른 방법들

-ea 옵션이 프로그램 전체에 표명을 활성화시키는 쉬운 방법이긴 하지만, 다른 옵션들도 있다. 또한 -ea는 시스템 클래스에는 작동하지 않는다.; 따라서 여러분은 -enablesystemassertions 혹은 보다 쉽게 -esa를 사용해야 한다.

전체 패키지 트리 (즉 패키지와 모든 하위 패키지)에 표명을 활성화시키려면 -ea 옵션 뒤에 콜론을 붙이고 패키지 이름과 생략 표시 (...)를 쓰면 된다. 예를 들어, 다음 구문은 net.zukowski.ibm 패키지와 이 패키지의 모든 하위 패키지에 대해 표명 검사를 활성화시킬 것이다.:


java -ea:net.zukowski.ibm... EclipseTest

특정 클래스에 대해서는 생략 표시로 패키지 이름을 끝내는 대신 전체 클래스 명을 지정한다.

만일 여러분이 전체 패키지에 대해 표명 검사를 활성화시키고 싶은데 어느 특정 클래스나 패키지를 제외하고 싶다면, -da 태그를 사용하면 된다. ("-da"는 -disableassertions의 줄임꼴이다.) 활성화와 비활성화 옵션을 나열하기만 하면 준비가 다 된 것이다. 예를 들어, 다음 구문은 net.zukowski.ibm 패키지 전체에 대해 표명 검사를 활성화시키지만 net.zukowski.ibm.BeanUtils 클래스는 제외시킨다.:


java -ea:net.zukowski.ibm... -da:net.zukowski.ibm.BeanUtils EclipseTest

프로그램적으로 표명 활성화하기

명령행에서 표명 검사를 활성화하는데 더하여 프로그램적으로 검사를 활성화 (혹은 비활성화) 시킬 수 있다. 이것은 앞으로 로딩될 클래스에만 영향을 미치기 때문에, 의지에 따라 켜거나 끌 수 없다.

클래스의 ClassLoader는 다음 네 메소드로 표명의 활성화와 비활성화를 제어한다.:

  • public void setDefaultAssertionStatus(boolean enabled): 이 메소드는 클래스 로더가 로딩하는 패키지와 클래스의 기본 상태를 설정한다. 이 설정은 특정 패키지와 클래스 옵션을 설정함으로서 겹쳐 쓰기될 수 있다.

  • public void setPackageAssertionStatus(String packageName, boolean enabled): 패키지와 그 패키지의 전체 하위 패키지의 상태를 오버라이드하기 위해 패키지명과 활성화 상태를 전달한다.

  • public void setClassAssertionStatus(String className, boolean enabled): 특정 클래스의 상태를 오버라이드하기 위해 완전한 조건을 갖춘 클래스명과 활성화 상태를 전달한다.

  • public void clearAssertionStatus(): 이 메소드는 모든 패키지와 클래스 설정을 거짓(false)으로 리셋시킨 후 클래스 로더도 거짓으로 리셋시킨다.

한 클래스의 클래스 로더를 가져오려면 Class 객체의 getClassLoader() 메소드를 호출한다. 비 정적인 메소드에 대해서는 다음 명령문을 사용한다.:


ClassLoader loader = getClass().getClassLoader();

정적인 메소드에 대해서는 getClass()를 호출할 수 없다. 여러분이 인스턴스를 가지고 있지 않기 때문이다. 따라서 다음과 같이 현재의 클래스명 끝에 .class를 추가하기만 하면 된다. :


ClassLoader loader = EclipseTest.class.getClassLoader();

이것은 변경 후에 로딩되는 클래스에만 영향을 미친다는 점을 기억하기 바란다. 대부분의 경우 여러분은 명령행에서 표명을 활성화시킬 것이다.

결론

이제 여러분은 이 기능을 알게 되었다. 바로 Java 1.4 표명 기능이다. 어디에 표명을 사용해야 하는지에 대한 정보는 참고 자료에 나와 있는 공식 문서의 Usage Notes 부분을 참조한다. 표명을 사용할 때 기억해야 할 핵심 사항은 이들이 선택적으로 활성화될 수 있다는 것이다.; 따라서 시점의 차이에 의하여 부작용이 나타날 수 있다.

참고 자료

필자 소개
Photo of John ZukowskiJohn Zukowski는 JZ Ventures, Inc.에서 전략적 자바 컨설팅을 수행하고 있으며, jGuru 그룹이 이끄는 수많은 Java FAQs의 체재 전문가로 활동하고 있다. 최근 Apress에서 Java CollectionsDefinitive Guide to Swing for Java 2 (제 2판)를 발간하였다.



이 기사에 대하여 어떻게 생각하십니까?

정말 좋다 (5) 좋다 (4) 그저그렇다 (3) 수정보완이 필요하다(2) 형편없다 (1)

  회사소개  |  개인정보 보호정책  |  법률  |  문의