Lombok


Lombok과 같은 Getter/Setter 자동 생성기는 실제로 호불호가 갈릴 수 있다. 캡슐화된 데이터의 필드만 작성함으로 `Value Object`의 표현력을 떨어뜨릴 수 있고, java agent를 통해 동작하는지라 사전 환경 구성이 되어 있지 않는 상황에는 올바른 컴파일을 보장할 수 없다. 컴파일 시점에 Getter/Setter 코드가 생성되다보니 api를 사용하는 client 코드도 상당히 불명확해 진다. 하지만 구식 엔터프라이즈 환경에서 찍어내듯 만들어내는 `Data Wrapper`들을 작성해야 한다면, 확실히 손가락의 고통(;;)은 줄여준다.

다음은 Lombok에 대한 튜토리얼 내용이다.


Lombok은 Java 코드에서 불필요한 코드를 제거하기 위해 사용할 수 있는 JAR(Java Archive) 파일이다.

예를 들어, 표준 Java Bean을 생각해 보자. 일반적으로 Java Bean에는 여러 가지 특성이 있다. 각 특성에는 액세서와 mutator(Getter 및 Setter)가 있다. 또한, 일반적으로 이 특성에는 toString() 메소드, equals() 메소드 및 hashCode() 메소드가 있다.

이점을 생각해 보면, 중복된 기능이 매우 많다는 것을 알 수 있다. 각 특성에 Getter와 Setter가 있고 이것이 일반적으로 필요하다면 그렇게 강조할 필요도 없을 것이다.

Lombok을 입력한다. Lombok에서는 코드의 수를 줄이기 위해 어노테이션을 사용하여 Java 코드의 클래스와 블록을 식별한다. 앞서 설명한 Java Bean 예제에서는 모든 Getter, Setter 및 3가지 다른 메소드가 컴파일 시간에 포함된다.

이렇게 하는 편이 훨씬 더 효과적이다. Eclipse나 IBM® WebSphere® Studio Application Developer(Eclipse를 사용하지 않는 경우에는 이 제품을 사용하고 있을 것이다. )를 사용 중인 경우에는 Java 프로젝트에 Lombok을 통합하여 개발 시간 결과를 즉시 얻을 수 있다. 다시 말해서 포함된 Getter와 Setter는 Eclipse 컴파일러를 통해 즉시 인식된다. 그러면 다른 Java 코드에서 이 메소드를 참조할 수 있다.

직접적인 이점은 물론 코드 수가 줄어든다는 점이며 이는 언제나 유익하다. 또한, 특정 Getter나 Setter에 특별히 관심을 두어야 하는 경우에도 확인할 코드를 찾으려고 수 많은 코드를 자세히 조사할 필요가 없다. 코드가 더욱 명확하게 표시되고 중복되는 부분이 줄어든다. 결국, 모든 개발자에게 도움이 된다.

또한, Lombok을 사용하면 Java Bean뿐만 아니라 코드의 다른 부분을 단순화할 수 있다. 예를 들면, try/catch/finally 블록과 동기화 메소드에 있는 중복 코드를 제거할 수 있다.



Lombok 설치

Lombok을 설치하기 위해, 이 기사에서는 당신이 Eclipse나 WebSphere Studio Application Developer를 사용하고 있다고 가정한다. 이러한 도구를 사용하지 않는 경우에도 Lombok을 여전히 사용할 수 있지만 개발 시간에 대한 이점을 얻을 수는 없다. 그러나 컴파일 시간에 대한 이점은 얻을 수 있다.

먼저, 자주 사용하는 브라우저를 열어서 http://projectlombok.org/로 이동한다.

이 기사를 쓰는 현재, 이 URL 페이지의 오른쪽 상단에는 큰 글자가 표시되어 있다. 이 글자는 "Download!"이다. 이 글자를 클릭하여 lombok.jar을 다운로드한다. 다른 사이트에서 다운로드하는 99%의 파일과 다르게, 이 파일은 압축을 해제할 필요가 없다.

파일을 다운로드한 다음 JAR 파일을 실행한다. 해당 운영 체제에서 프롬프트를 열어서 lombok.jar을 설치한 디렉토리로 이동한 다음 java -jar lombok.jar을 입력한다.

JRE(Java Runtime Environment)이 해당 경로에 있다고 가정한다. 그렇지 않으면 JRE를 추가해야 한다. 이렇게 하는 방법을 학습하려면 특정 운영 체제의 관련 문서를 참조한다.

Microsoft® Windows®를 사용하고 있는 경우에는 lombok.jar 아이콘을 두 번 클릭할 수도 있다. 또한, 해당 GUI(Graphical User Interface)에서 JAR을 실행할 수 있어야 한다.

그러나 이러한 과정을 모두 종료하면 결국에는 Lombok 설치 화면이 표시된다. 이 화면에는 Eclipse나 WebSphere Studio Application Developer 실행 파일의 위치를 묻는 메시지가 표시된다. 아마도 이 실행 파일은 올바른 기본 위치에 있을 것이다. 그러나 어떤 경우에는 기본 위치를 변경해야 할 수도 있다.

Install/Update를 클릭하면 Lombok이 Eclipe 개발 환경과 신속하게 통합된다. Eclipse를 이미 실행 중인 경우에는 Eclipe를 종료한 다음 다시 시작한다.



Lombok 사용

이제 Eclipse나 WebSphere Studio Application Developer 내에서 실제로 Lombok을 사용할 준비가 되었다. Listing 1에 있는 코드를 살펴보자.


Listing 1. Java Bean을 시작하기 위한 좋은 출발점

public class Lure {
  private String name;
  private int size;
  private String color;
  private String style;
}

이 코드는 간단한 Java Bean으로 시작한다. 여기에서 Java Bean의 각 특성에 해당 Getter와 Setter를 추가한다. 그런 다음, equals() 메소드, toString() 메소드 및 hashCode() 메소드를 추가한다.

Lombok을 사용하면 이러한 과정을 수행할 필요가 없다. 그 대신 하나의 어노테이션(@Data)을 추가하면 된다.

그렇다. 이렇게만 하면 된다. Listing 2에는 @Data가 포함되었다.


Listing 2. Java Bean을 시작하기 위한 더 나은 출발점

import lombok.Data;
public @Data class Lure {
  private String name;
  private int size;
  private String color;
  private String style;
}

기억해야 할 점은 이 코드는 lombok.jar이 빌드 경로에 있고 Java 클래스에서 lombok.Data를 가져오는 경우에만 작동된다는 점이다.

Eclipse나 WebSphere Studio Application Developer에 있는 클래스 아웃라인(일반적으로 해당 화면의 클래스 오른쪽)를 보면, 이러한 메소드가 Lure 클래스에 자동으로 추가된다는 점을 확인할 수 있다.

이 아웃라인을 즉시 볼 수 없는 경우에는 Eclipse에서 Window 메뉴를 클릭한 다음 Show View를 선택한다. 화면 오른쪽에 표시되는 플라이아웃 메뉴에서 Outline을 선택한다. 아웃라인을 강제로 표시하려면 단축키 조합 Alt+Shift+Q를 누른 다음 O를 누른다.

Lure를 인스턴스화하는 다른 클래스를 쓰는 경우에는 Lure에 포함된 getName() 또는 setSize()와 같은 메소드에 즉시 액세스할 수 있다. 또한, equals(), hashCode() 및 toString()에도 액세스할 수 있다. 간단하지 않은가?

Eclipse나 WebSphere Studio Application Developer를 사용하지 않는 경우에는 이와 같은 내포된 추가 메소드는 실제로 코드를 컴파일하는 경우에만 인식된다. 따라서 Eclipse나 WebSphere Studio Application Developer를 이용하지 않고도 Lombok을 사용할 수 있지만 Lombok은 Eclipse나 WebSphere Studio Application Developer와 통합되도록 설계되었다.

Getter와 Setter 메소드를 생성할 경우, Lombok은 기존 표준을 따른다. 모든 메소드 이름은 get 또는 set으로 시작하고 특성 이름은 대문자로 시작한다. 물론 특성이 부울인 경우는 예외이다. 이러한 경우, Getter는 get이 아니라 is로 시작한다. 이렇게 하는 것이 Java Bean에서는 일반적인 관례이다.

이제, Getter 중 하나에 특정 요구사항을 적용해야 하는 Java Bean이 있다고 가정하자. Listing 2에 있는 예제에서는 getStyle() 메소드를 통해 색상과 크기가 결합된 값을 리턴할 수 있다. 이 경우에는 getStyle() 메소드의 코드를 마음껏 분석할 수 있다. Lombok에서는 코드를 검사하지만 해당 특성을 기반으로 하는 자체 getStyle 버전을 작성하지는 않는다.

아마, Getter 메소드가 있어도 공개하고 싶지 않을 것이다. Lombok에서는 이러한 목적으로 삽입 매개변수를 입력할 수 있다. Listing 3에는 사용자 정의 수정자가 있다.


Listing 3. 사용자 정의 수정자

private String name;
@Getter(AccessLevel.PROTECTED)
private int size;
private String color;
private String style;

이 경우에는 getSize() 메소드가 공개되지 않는다. 이 코드에는 하나의 보호된 수정자가 있어서 파생된 서브클래스와 Lure 클래스에서만 이 코드를 사용할 수 있다.

다른 기본값을 언제나 승인하고 싶은 것은 아니므로 Lombok에서는 두 가지를 모두 제공한다. 예를 들면, toString() 메소드는 쉼표로 구분된 목록에 있는 값과 특성 이름 및 클래스 이름을 단순히 표시한다. 이 목록은 클래스 이름 옆에 삽입구 형태로 표시된다.

예를 들어, Lure 클래스를 로그할 때 색상은 무시한다고 하자. toString()의 기본값을 변경하려면 ToString 어노테이션을 사용해야 한다.


Listing 4. toString() 수정

@ToString(exclude="color")
public @Data class Lure {
  private String name;
  private int size;
  private String color;
  private String style;
}

인스턴스화된 Lure 클래스에 대한 예제를 인쇄하면 다음과 같은 것이 표시된다.


Lure(name=Wishy-Washy, size=1, style=trolling)


색상이 어떻게 제거되었을까? Lombok에서 어노테이션을 사용하여 색상을 제거한다.

또한, equals()와 hashCode() 메소드를 처리하는 방법을 수정할 수 있다. Listing 5에 있는 코드는 설명할 필요도 없이 명확하다.


Listing 5. hashCode() 수정

@EqualsAndHashCode(exclude="style")
public @Data class Lure {
  private String name;
  private int size;
  private String color;
  private String style;
}

이 경우에는 equals() 및 hashCode() 메소드가 생성되면 style 특성이 제외된다.



기타 기능

try/catch/finally 블록을 쓰는 것을 개발자들이 꺼려하곤 한다. 필자 역시 그렇다. 다행히도, Lombok에서는 사용하지 않아도 된다. 이 방법은 단지 Lombok을 사용하여 Java 코드에서 불필요한 코드를 제거하는 또 다른 방식일 뿐이다. try/catch/finally 블록의 중복을 제거하려면 간단히 @Cleanup 어노테이션을 사용하자. Listing 6을 참조한다.


Listing 6. @Cleanup 어노테이션 사용

public static void main(String[] args) throws IOException {
  @Cleanup InputStream in = new FileInputStream(args[0]);
  @Cleanup OutputStream out = new FileOutputStream(args[1]);

  //write file code goes here
}

표준 Java 코드에서 일반적으로 사용하는 것보다 많은 클리너가 사용되었다. 호출된 코드(이 경우 IOException)에서 발견한 예외가 어떤 것이든지 여전히 처리해야 한다는 점에 주목하자.

중요한 점은 Listint 6에 있는 코드 블록에서 try/catch/finally 블록이 제거될 뿐만 아니라 열린 스트림이 닫힌다는 점이다. close()가 아닌 다른 메소드를 이용하는 오브젝트를 사용하여 자원을 포기하는 경우에는 어노테이션 옆에 삽입구를 추가하여 메소드를 호출한다. 예를 들면, @Cleanup("relinquish")와 같은 형태이다.

또한, Lombok에는 메소드를 동기화하는 수단이 있으며 이 수단은 그다지 다변적이지 않다. 예상대로 이러한 동기화는 @Synchronized 메소드를 사용하여 수행된다.


Listing 7. @Synchronized 어노테이션 사용

@Synchronized private int foo() {
  //some magic done here
  return 1;
}

이 예제에서는 Lombok을 이용하여 $lock, 인스턴스 오브젝트를 자동으로 작성한 다음 이 오브젝트와 대조하여 foo() 메소드를 동기화한다.

@Synchronized를 사용하여 어노테이트된 메소드가 정적이면 Lombok을 통해 $LOCK, 클래스 오브젝트가 자동으로 작성되어 @Synchronized 메소드와 동기화된다.

또한, 오브젝트를 지정한 다음 삽입구 형태의 매개변수를 사용하여 명시적으로 잠글 수 있다. 예를 들면, @Synchronized("myObject")는 myObject 오브젝트와 대조하여 @Synchronized 메소드를 동기화한다. 이 경우에는 클래스 오브젝트를 명시적으로 정의해야 한다.



결론

Lombok을 사용하면 모든 애플리케이션 개발자들이 가능한 제거하려고 하는 중복성 문제를 해결할 수 있다.

또한, 코드의 가독성을 개선할 수 있다. 이렇게 되면 매우 많은 특성이 있는 Java Bean에서 일반적인 표준을 따르지 않는 "특정" Getter와 Setter를 훨씬 더 쉽게 찾을 수 있다. 이는 특정 Getter와 Setter 메소드는 단지 하나만 코드되기 때문이다.

Lombok을 이용하면 코드를 쉽게 정리하여 생산성을 개선하거나 Java 코드에서 불필요한 코드를 제거할 수 있다.


출처 : 한국 DeveloperWorks


'TODO: blah blah~' 카테고리의 다른 글

Spring DM for OSGi Tutorial  (0) 2010.12.27
Maven을 통한 SpringDM Target Platform 생성  (0) 2010.12.27
Lombok  (1) 2010.12.27
JDK Binary Tools  (0) 2010.12.27
Java Application 중복실행 방지  (0) 2010.12.27
Eclipse Rich Ajax Platform (RAP) Tutorial  (0) 2010.12.27