IDE2015. 7. 24. 00:49
반응형

 Intellij를 사용하는 중에 Optimize imports(Ctrl + Alt + O) 기능을 이용하거나 Code Completion 기능으로 import문이 추가될 경우 Wildcard import문이 추가되는 경우가 생깁니다. 막연하게 성능문제가 생기니 피하라고 하는 사람도 있고 일부 정적 코드 분석 툴의 경우에도 사용하지 않는 것을 권장하는 결과가 나오는 경우가 있습니다.



Intellij의 코드 inspection 스크린샷

※Intellij의 코드 inspection에서 분석 결과화면으로 일부 코딩 규약의 경우 사용을 금지하고 있다는 경고내용



 성능문제가 생기니 피해야 한다고 하는 경우는 일반적으로 컴파일 시 Wildcard import의 경우는 실제 클래스 을 찾기위에 해당 패키지의 클래스를 전부 탐색하는데 시간이 걸리므로 사용하지 않아야 한다고 합니다. 하지만 컴파일 결과는 동일하므로 실제 어플리케이션 실행간에는 문제를 일으키지 않습니다. 또한 파일 몇개를 탐색한다고 인지할 정도의 속도차이가 발생할지도 의문입니다. 일반적인 경우라면 사전에 컴파일된 jar 혹은 war를 준비해 두고 deploy하는 경우가 대다수이므로 컴파일 타임의 시간 소모는 무시해도 될 정도의 시간일 것입니다. 물론 각각의 환경별로 다른내용을 추가하여 컴파일후 즉시 반영햐는 형태의 운용환경이라면 조금 얘기가 다를 수 있겠지만 말입니다. 아래의 코드는 java.util.Map으로 import한 경우와 java.util.*로 import한 것이외에는 동일한 소스코드를 컴파일해서 바이트 코드를 비교한 것인데 완벽하게 동일한 것을 알 수 있습니다.



java.util.Map Import한 경우

Compiled from "Test.java"
public class _test.Test {
  public _test.Test();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #16                 // class java/util/HashMap
       3: dup
       4: invokespecial #18                 // Method java/util/HashMap."<init>":()V
       7: astore_1
       8: return
}


java.util.* Import한 경우

Compiled from "Test.java"
public class _test.Test {
  public _test.Test();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #16                 // class java/util/HashMap
       3: dup
       4: invokespecial #18                 // Method java/util/HashMap."<init>":()V
       7: astore_1
       8: return
}




 다음으로 확인해 보아야 할 경우는 별개의 두 패키지를 Wildcard import한뒤 동일한 이름의 클래스를 추가했을 경우입니다. 이경우 참조할 클래스를 결정할 수 없으므로 컴파일 할 수 없는 상황이 발생합니다. 단순히 클래스를 추가했을 뿐인데 의도하지 않게 별도의 소스를 수정해야 하는 상태가 되므로 그다지 바람직하지 않다고 할 수 있습니다. 물론 이미 컴파일한 소스는 위의 바이트 코드와 같이 fully qualified name으로 변환되어 코드가 생성되므로 영향을 받지 않습니다. 그러므로 컴파일 전의 소스에만 영향을 미치므로 수정하고 다시 컴파일해도 무방하다고 판단하고 Wildcard import를 사용해도 됩니다. 하지만 일정규모를 넘는 프로젝트의 경우는 소스 수정권한이 없을 수 있으므로 Wildcard import를 사용하지 않는 것이 바람직 하겠습니다. 그러면 대응방법에 대해서 알아보도록 하겠습니다.



대응방법


1.  File > Settings 메뉴로 이동합니다.



2. Settings윈도우 내의 Editor > Code Style > Java 메뉴로 이동하여 import탭을 클릭하여 오픈합니다.



3. Imports탭 내부의 [Use single class import]를 체크합니다. 체크를 해지할 경우 기본적으로 WIldcard import가 적용됩니다.



4. [Class count to use import with '*'], [Names count to use static import with '*'] 항목은 각각 import와 static import의 경우 Wildcard import를 적용할 서브 클래스의 갯수를 의미합니다. '100'과 같이 높은 숫자로 지정하면 Wildcard import를 피할 수 있습니다.





이어서 Import탭 내부의 다른 항목들에 대해서 알아보도록 하겠습니다.


[Use fully qualified class names] 항목의 경우는 import문을 사용하지 않고 inline으로 필요한 class의 fully qualified name을 사용하는 방법입니다. 이 설정을 사용할 경우 사실상 [Use single class import] 설정 항목은 의미가 없어집니다. 이 설정의 경우 소스 가독성에 문제가 될 수 있으므로 사용하지 않는 것을 권장합니다.


[Insert imports for inner classes] 항목은 Inner class의 경우도 import문을 삽입할 것인지 설정하는 항목이다. 말로는 약간 어려운듯 하나 아래의 예제를 보면 간단하게 이해할 수 있을것입니다.

Insert imports for inner classes을 체크하지 않았을 경우

import java.util.HashMap;
import java.util.Map;

public class Test {
	private Map<String, String> map = new HashMap<String, String>();

	public void something() {
		for(final Map.Entry<String, String>l entry : map.entrySet()) {
			//do something
		}
	}

}

Insert imports for inner classes을 체크했을 경우

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class Test {
	private Map<String, String> map = new HashMap<String, String>();

	public void something() {
		for(final Entry<String, String>l entry : map.entrySet()) {
			//do something
		}
	}

}


[Packages to Use Import With '*'] 설정은 위 설정과 상관없이 항상 Wildcard import를 할 클래스를 지정하는 설정입니다. 해당 설정에는 Static과 With Subpackages 두가지 체크항목이 두개 있습니다. Static 항목은 Static import일 경우 적용하는 항목이고 With Subpackages 항목에 체크하였을 경우 하위 패키지를 포함하여 적용됩니다. 체크하지 않았을 경우 해당 레벨의 패키지에만 적용됩니다. 항목을 추가하고 싶은 경우 우측의 '+'를 클릭하면 되고 삭제할 경우는 삭제할 항목을 선택후 '-' 버튼을 클릭하면 삭제 됩니다.





 마지막으로 살펴볼 항목은 [Layout static imports separately] 입니다. 이 항목은 약간 애매한 곳에 위치하고 있습니다만 체크/해제 선택시 속해있는 Import Layout은 물론 상위의 [Packages to Use Import with '*'] 항목도 같이 영향을 받는 다는 점에 주의해야 겠습니다.


 우측에는 '+' 버튼이 2개 위치하고 있는데 위쪽은 클래스를 추가하는 버튼 두번째는 <blank line>으로 표시된 라인을 추가하는 버튼으로 import문 사이에 공백라인을 추가합니다. 클래스 선택후 '-'버튼을 이용하여 삽입된 클래스를 삭제, 화살표를 이용하여 상하로 이동하여 배치할 수 있습니다.



 위와 같이 Intellij의 Wildcard import방지하는 방법에 대해서 알아보았습니다. 사실 Wildcard Import된다고 해도 크게 문제가 되지 않는 경우가 대부분입니다. 하지만 막연히 사용하지 않는것이 좋다가 아닌 이유와 위험요인에 대해서 정확이 인지한 후 결정하면 어떨까 하는 생각입니다.


※본 아티클의 내용은 Intellij 14.1.4에서 확인 되었습니다.


Posted by Reiphiel