java 코드는 어떻게 자동으로 만들어질까(1/2)

안녕하세요. 야놀자클라우드 플랫폼 개발팀 한재형 입니다.
java 개발자들은 많이 아시겠지만,
주니어들 에게는 다소 생소할 수 있는 기능을 하나 소개하려 합니다.

실제 주니어때 있었던 대화 입니다.

사수 : 너 annotation processor 가 뭔지 알아?

나 : 음.. annotation 이랑 processor 는 아는데요..ㅎㅎ

사수 : 그럼 annotation processor 는?

나 : 잘 모르겠는데.. 아! lombok 설정 할 때 intellij 에서 annotation processor 설정을 체크 한 적이 있어요.

사수 : 그래. 그럼 그걸 왜 했을까?

나 : 잘 모르겠는데요…

사수 : lombok 은 어떻게 동작 하는거 같아?

나 : 음.. 혹시 리플렉션이나 프록시 같은걸로..?

사수 : lombok 동작 원리를 공부해 봐.

Photo by 도훈 이 on Unsplash

그렇게 annotation processor 공부가 시작 되었습니다.

lombok 이란 반복성 코드를 자동으로 생성해주는, 매우 빈번하게 사용되는 라이브러리 입니다.

처음 lombok 을 쓰는 프로젝트의 환경 세팅을 했을 때 Enable annotation processing 라는 문구를 한번 쯤은 봤을 것이고, ide 의 annotation processing checkbox 을 활성화 해야 lombok 을 사용할 수 있었을 것 입니다..

그리고 그냥 그런가 보다 하고 넘어 갔었습니다.

하지만 해당 옵션이 뭔지, lombok 의 동작 원리를 알게 되면 개발하는데 있어 시야가 좀 더 넓어질 수 있습니다.

그러면 annotation processor 란 뭘까요.

annotation 이란 @Override 형태와 같이 사용하는 메타성 데이터의 일종 입니다.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

그럼 annotation 으로 뭔가 processing을 하는게 아닌가 추측을 할 수 있을 겁니다.

그리고 그게 맞습니다.

annotation processor 는 java 컴파일러에서 제공하는 기능으로,
특정한 annotation 을 기반으로, java 컴파일 단계에서
코드를 검사, 조작 하거나 생성
할 수 있게 해줍니다.

그리고 이미 알게 모르게 사용하고 있습니다.

lombok 뿐 아니라 자동으로 코드를 생성해주는 라이브러리(query-dsl 같은) 들은 대부분 annotation processor 단계에서 생성한다고 보면 됩니다.

그냥 그런가보다 하고 넘어갔던 build.gradle 의 설정들이 알고 보면 보인다.

그러면 코드를 자동으로 생성 할 수 있게 되면 어떤 장점이 있을까요?

단순 중복 코드, 일명 노가다 작업을 줄어들게 할 수 있습니다.
이를 boilerplate code 라고 하는데,
lombok 을 사용했을 때의 장점을 생각하면 쉽게 와 닿을 것 입니다.
getter, setter 등 단순 지루하고 반복되는 코드들을 자동으로 생성할 수 있게 할 수 있을 것 입니다.

간단한 예제를 하나 만들어볼까요.

예를 들어 이런 기능은 어떨까요.

jpa 를 사용하는 경우 entity 클래스와 dto 클래스가 각각 존재할 수 있습니다.그리고 많은 경우 두개의 클래스가 비슷한 구조를 가집니다.
(물론 다를 수도 있습니다.)

그렇다면 entity 클래스를 기반으로, 자동으로 생성자와, getter 를 가진 dto 클래스를 생성해 주는 기능을 한번 만들어 볼까요.

@Entity
public class User {
private long id;
private int age;
private String name;
private String address;
private String job;

@Override
public String toString() {
...
}
}

위는 너무 흔하게 볼 수 있는 평범한 entity 클래스 입니다.

그리고 custom annotation 인@Dto annotation 을 붙이고 컴파일 하면
생성자와, getter 가 존재하는 UserDto.java 가 생성이 됩니다.

User 에 Dto 를 붙이고 컴파일 하면 generated 경로에 UserDto 가 생긴다.

clean시 삭제 되고, 컴파일시에 Dto 클래스가 생성 되는걸 확인 할 수 있습니다.

예제는 github 에 있습니다.

코드를 생성할 땐 JavaPoet 이라는 매우 강력한 라이브러리가 있기 때문에 쉽게 작성할 수 있습니다.

클래스 이름, 패키지, 생성자, 메소드, 필드, 어노테이션, 각종 구문 등.. 생각 할 수 있는 모든 코드를 자동으로 만들 수 있습니다.

AbstractProcessor 의 구현체가 필요하다. Dto annotation이 붙은 클래스를 찾고, 찾은 클래스를 바탕으로 새 코드를 만든다.
실제 코드를 만들어지는 코드. JavaPoet 이라는 강력한 라이브러리로 쉽게 만들 수 있다.

그래서 어디다 써요?

사실 실무에서 annotation processor 를 직접 만들어 사용할 경우는 많이 없을 겁니다.

대부분은 이미 잘 만들어진 라이브러리가 존재하고,
직접 만들려고 하는 경우에는 설정이나 수정 등, 배보다 배꼽이 더 커질 경우가 생길 수도 있습니다.

(공통 프레임워크나 라이브러리 팀이 아닌 이상..)

귀찮다 라는 얘기..

하지만 알고도 사용하지 않는 것과, 몰라서 못 쓰는 것과는 다른 얘기 입니다.

최소한 이런 기능을 사용하는 라이브러리가 있지 않을까 찾아볼 수 도 있을 겁니다.

annotation processor 는 매우 강력한 기능이기 때문에,
분명히 개발 하는데 있어 시야가 더욱 넓어지는데 도움이 많이 될 것 입니다.

그런데 lombok 은 새 클래스가 생기진 않는데요..?

lombok 은 새 클래스가 생성되지 않고, 바이트코드 레벨 에서 코드 조작이 일어납니다.

그건 다음 콘텐츠에서 다뤄보도록 하겠습니다.

다음편(2/2)을 기대해주세요!

--

--

야놀자클라우드 Tech Blog
야놀자클라우드 Tech Blog

Published in 야놀자클라우드 Tech Blog

야놀자 클라우드는 효율적인 호텔 운영을 돕고 편리한 호텔 고객 경험을 제공하는 클라우드 기반의 종합 호스피탈리티 솔루션을 만들어가고 있어요.