skarltjr / Memory_Write_Record

나의 모든 학습 기록
0 stars 0 forks source link

롬복은 어떻게 동작하는거지? #133

Open skarltjr opened 1 year ago

skarltjr commented 1 year ago
@Getter
public class Hello{
  private int number;
}
위와 같은 코드가 존재할때 롬복은 number에 해당하는 getter를 알아서 만들어주는데...

롬복은 어떻게 동작하는거지?

Lombok은 컴파일 시점에 애노테이션 프로세서를 사용하여 소스코드의 AST(abstract syntax tree)를 조작한다.
사진을 천천히 살펴보면 컴파일러가 만들어낸 AST를 롬복은 어노테이션 프로세싱으로부터 AST를 재가공하고
결국 두 번에 걸쳐 만들어진 AST로부터 바이트코드가 만들어진다.

AST와 컴파일러

추상 구문 트리

AST는 프로그래밍 언어로 작성된 소스 코드의 추상 구문 구조의 트리이며, 이 트리의 각 노드는 소스코드에서 발생되는 구조
AST는 컴파일 단계 중 구문 분석(syntax analyzing) 단계의 결과물이기 때문에 컴파일러와 관계가 있다.

컴파일 단계

1. 어휘 분석(lexical analyze) or 스캔(scan)
2. 구문 분석(syntax analyzung) - 결과물로 구문트리(syntax tree) 또는 추상 구문 트리(abstract syntax tree)가 생성!!!
3. 의미 분석(semantic analysis)
4. 중간 표현의 생성(intermediate representation)
5. 코드 생성(code generation)
6. 최적화(optimization)
7. 어셈블러

바이트 코드 생성

어노테이션 프로세스란?

컴파일 단계에서 어노테이션을 분석하고 정의에 따라 동작

그리고 어노테이션 프로세서!!!는 내가 만든 어노테이션에 구체적인 동작 행위를 하기위해서 자바에서 제공하는 api
즉 롬복은 어노테이션 프로세서를 통해 컴파일 시점에 AST를 조작하여 우리가 정의한 행동을 수행해온것

한 번 롬복 코드를 살펴보자

  1. 먼저 컴파일러가 만들어둔 AST 트리의 정보를 얻어야하고 이것이 init()에서 수행된다.
  2. AST를 수정하는 부분이 바로 process 매서드인데 다시 process 매서드를 살펴보면
    • 루트 어노테이션부터 순회
    • 각 어노테이션별로 동작을 정의하기위해 기존 AST트리에 새로운 노드를 추가하여 추후 동작 도모
    • https://github.com/skarltjr/LombokCopy
그래서 생각해볼 수 있는것은

컴파일시점에 이러한 행위를 하는 이유가 무엇일까?
- spring aop는 런타임 위빙 즉 런타임시점에 타겟 매서드를 대체할 프록시 객체를 만들어내는데 이로인해 실행 시간이 지연될 수 있다는 단점이 있다고 알고있는데
- AOP 개념을 떠나서 롬복의 경우 컴파일시점에 가로채어 바이트코드(좀 더 정확하겐 AST)를 조작함으로써 성능적 우위를 가져갈 수 있다고 생각
- 다만 컴파일시점에 바이트코드를 조작하는 다른것들과 충돌할 위험이 굉장히 크고 대표적인 예시가 aspectJ의 컴파일타임 위빙