📖
Kyu9's Repo
  • Library of mameil
  • 이슈 경험
    • 20230220_트랜잭션
    • 20230306_캐싱이슈
    • 20230722_테스트코드에서 @Transactional
    • 20230807_deadlock
  • 인턴 스터디
    • Gradle
    • Stream, Optional, 람다식
    • JVM의 메모리 구조, Garbage Collector
    • RESTful API
    • Microservice Architecture
    • HTTP
    • 웹서버란 무엇인가
    • Git Branch
    • TDD
    • Redis을 이용한 캐시
    • Thymeleaf
    • 정리가 필요한 자료들
    • SpringBoot Management
    • 테스크 코드 분할
  • 동아리 스터디
    • 기본 SQL 공부
      • SQL의 기본 개념
      • SELECT 문장을 이용하여 원하는 데이터 출력하기
        • 집합 연산자 사용하기
        • where절에 비교 연산자를 사용해보기
        • SELECT_EX
        • 산술 연산자 사용해보기
      • 단일 행 함수 사용
        • lower/upper 함수 사용하기
        • length함수 사용하기
        • concat함수 사용
        • substr/mid/substring 함수 사용
        • instr함수 사용하기
        • lpad/rpad 함수 사용하기
        • trim/ltrim/rtrim 함수 사용하기
        • replace 함수 사용하기
        • round 함수 사용하기
        • truncate 함수 사용하기
        • mod함수 사용하기
        • ceil함수 사용하기
        • floor함수 사용하기
        • power 함수 사용하기
        • Date fn(날짜 함수)
        • 형 변환 함수
        • 일반함수란
    • a-ha 실습
    • 혼자서 만들어본 게시판
    • AWS 강의
  • 학교 나머지 공부 자료
    • 웹프레임워크(Spring)
      • Spring이란?
      • Webframework1-1
      • Webframework1-2
      • SpringBoot의 특징
      • SpringBoot 생성 방법
      • Spring Data JPA
      • SpringBoot Security
      • SpringBoot HATEOAS
  • 공부 자료들
  • WS 온라인 자바 스터디
    • Week1(JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.)
    • Week2(자바 데이터 타입, 변수 그리고 배열)
    • Week3(연산자)
    • Week4(제어문)
    • Week5(클래스)
    • Week6(상속)
    • Week7(패키지)
    • Week8(인터페이스)
    • Week9(예외처리)
    • Week10(멀티쓰레드 프로그래밍)
    • Week11(Enum)
    • Week12(Annotation)
    • Week13(I/O)
    • Week14(Generic)
    • Week15(람다식)
  • 백준문제
    • 입출력과 사칙연산
      • We love kriii(10718)
      • 고양이(10171)
      • 개(10172)
      • A+B(1000)
      • A-B(1001)
      • AxB(10998)
      • A/B(1008)
      • 사칙연산(10869)
      • 나머지(10430)
      • 곱셈(2588)
    • for문
      • 구구단(2739)
      • A+B - 3(10950)
      • 합(8393)
      • 빠른 A+B(15552)
      • N 찍기(2741)
      • 기찍 N(2742)
      • A+B - 7(11021)
      • A+B - 8(11022)
      • 별 찍기 - 1(2438)
      • 별 찍기 - 2(2439)
      • X보다 작은 수(10871)
    • if문
      • 두 수 비교하기(1330)
      • 시험 성적(9498)
      • 윤년(2753)
      • 사분면 고르기(14681)
      • 알람 시계(2884)
      • 오븐 시계(2525)
      • 주사위 세개(2480)
      • 영수증(25304)
    • While문
      • A+B - 5(10952)
      • A+B - 4(10951)
      • 더하기 사이클(1110)
    • 1차원 배열
      • 최소, 최대(10818)
      • 최댓값(2562)
      • 숫자의 개수(2577)
      • 나머지(3052)
      • 평균(1546)
      • OX퀴즈(8958)
      • 평균은 넘겠지(4344)
    • 함수
      • 정수N개의 합(15596)
      • 셀프 넘버(4673)
      • 한수(1065)
    • 문자열
      • 아스키코드(11654)
      • 숫자의 합(11720)
      • 알파벳 찾기(10809)
      • 문자열 반복(2675)
      • 단어 공부(1157)
      • 단어의 개수(1152)
      • 상수(2908)
      • 다이얼(5622)
      • 크로아티아 알파벳(2941)
      • 그룹 단어 체커(1316)
    • 기본수학-1
      • 손익분기점(1712)
      • 벌집(2292)
      • 분수찾기(1193)
      • 달팽이는 올라가고 싶다(2869)
      • ACM 호텔(10250)
      • 부녀회장이 될테야(2775)
      • 설탕 배달(2839)
      • 큰 수 A+B(10757)
      • Fly me to the Alpha Centauri(1011)
    • 기본수학-2
      • 소수 찾기(1978)
      • 소수(2581)
      • 소인수분해(11653)
      • 소수 구하기(1929)
      • 베르트와 공존(4948)
    • 재귀
      • 하노이 탑 이동 순서(11729)
      • 피보나치 수 5(10870)
      • 별 찍기(2447)
    • 브루트 포스
      • 블랙잭(2798)
      • 분해합(2231)
      • 덩치(7568)
      • 체스판 다시 칠하기(1018)
      • 영화감독 슘(1436)
    • 집합과 맵
      • 숫자 카드(10815)
      • 문자열 집합(14425)
      • 숫자 카드2(10816)
      • 듣보잡(1764)
      • 대칭 차집합(1269)
      • 서로 다른 부분 문자열 갯수(11478)
    • 정렬
      • 수 정렬하기(2750)
      • 수 정렬하기 2(2751)
      • 수 정렬하기 3(10989)
      • 통계학(2108)
      • 소트인사이드(1427)
      • 좌표 정렬하기(11650)
      • 좌표 정렬하기2(11651)
      • 단어 정렬(1181)
      • 나이순 정렬(10814)
      • 커트라인(25305)
      • 좌표압축(18870)
    • 백트래킹
      • N과 M - 1(15649)
      • N과 M - 2(15650)
      • N과 M - 3(15651)
      • N과 M - 4(15652)
      • N-Queen(9663)
      • 스도쿠(2580)
      • 연산자 끼워넣기(14888)
      • 스타트와 링크(14889)
    • 이분 탐색
      • 수 찾기(1920)
    • 동적계획법
      • 피보나치 함수(1003)
      • 신나는 함수 실행(9184)
      • 01타일(1904)
      • 파도반 수열(9461)
      • RGB거리(1149)
      • 정수 삼각형(1932)
      • 계단 오르기(2579)
      • 1로 만들기(1463)
      • 쉬운 계단 수(10844)
      • 포도주 시식(2156)
      • 가장 긴 증가하는 부분 수열(11053)
      • 가장 긴 바이토닉 부분 수열(11504)
      • 전깃줄(2565)
      • LCS(9251)
      • 연속합(1912)
      • 평범한 배낭(12865)
      • 더하기(9095)
    • DFS와 BFS
      • 미로탐색(2178)
      • 바이러스(2606)
      • DFS와 BFS(1260)
      • 단지번호붙이기(2667)
      • 전쟁 - 전투(1303)
      • 숨바꼭질(1697)
      • 데스 나이트(16948)
      • 나이트의 이동(7562)
      • 녹색 옷 입은 애가 젤다지?(4485)
      • 음식물 피하기(1743)
      • A->B (16953)
      • 숨바꼭질 3(13549)
      • 숨바꼭질 2(12851)
    • 구현
      • 치즈(2636)
  • 프로그래머스 문제
    • SQL
      • Animal Table - Oracle
      • Animal Table - MySQL
      • Animal Table2 - Oracle
      • Animal Table 3,4 - Oracle
    • Lv1
      • 두 개 뽑아서 더하기
      • 제일 작은 수 제거하기
      • 문자열 내 p와 y의 개수
      • 예산
      • 자릿수 더하기
      • 두 정수 사이의 합
      • 같은 숫자는 싫어
      • 가운데 글자 가져오기
      • 수박수박수박수박수박수?
      • 나누어 떨어지는 숫자 배열
      • 2016년
      • 폰캣몬
      • 서울에서 김서방 찾기
      • 문자열을 정수로 바꾸기
      • 소수 만들기
      • 문자열 다루기 기본
      • 소수 찾기(에라토스테네스의 체)
      • 숫자 문자열과 영단어
      • 이상한 문자 만들기
      • 없는 숫자 더하기
      • 문자열 내림차순으로 배치하기
      • 문자열 내 마음대로 정렬하기
      • 약수의 개수와 덧셈
      • 콜라츠 추측
      • 자연수 뒤집어 배열로 만들기
      • 신규 아이디 추천
      • 비밀지도
      • 크레인 인형뽑기 게임
      • 실패율
      • 로또의 최고 순위와 최저 순위
      • 키패드 누르기
      • 정수 내림차순으로 배치하기
    • Lv2
      • 행렬의 곱셈
      • 영어 끝말잇기
      • 영어 끝말잇기
      • N개의 최소 공배수
      • 피보나치 수
      • 124 나라의 숫자
      • 짝지어 제거하기
      • 프린터
      • 다음 큰 숫자
      • 최댓값과 최솟값
      • 최소값 만들기
      • 숫자의 표현
      • JadenCase 문자열 만들기
      • 오픈채팅방
      • 영어 끝말잇기
      • 멀쩡한 사각형
      • 올바른 괄호
      • 위장
      • 기능개발
      • 더 맵게
      • 스킬트리
    • 완전탐색
      • 모의고사(Lv1)
      • 카펫(Lv2)
      • 소수 찾기(Lv2)
    • 정렬(Sorting)
      • K번째 수(Lv1)
      • 가장 큰 수(Lv2)
      • H-Index(Lv2)
    • 해시(Hash)
      • 완주하지 못한 선수(Lv1)
      • 전화번호 목록(Lv2)
    • 탐욕법(Greedy)
      • 체육복(Lv1)
      • 큰 수 만들기(Lv2)
      • 구명보트(Lv2)
    • 동적계획법(DP)
      • 정수 삼각형(Lv3)
    • 깊이/너비 우선 탐색(DFS/BFS)
      • 타겟 넘버(Lv2)
      • 네트워크(Lv3)
      • 단어 변환(Lv3)
  • 스프링부트 책
    • Day 1
    • Day 2
    • Day 3
    • Day 4
    • Day 5
    • Day 6
    • Day 7
    • Day 8
    • Day 9
    • Day 10
    • Day 11
    • Day 12
    • Day 13
    • Day 14
    • Day 15
    • Day 16
    • Day 17
  • JPA 책
    • 프로젝트 세팅 및 기본설정
    • 영속성 관리 개념
    • 엔티티 매핑
      • 실습 예제
    • 연관관계 매핑 기초
      • 실습 예제
    • 다양한 연관관계 매핑
      • 다대일, 일대다 관계
      • 일대일, 다대다 관계
      • 실습 예제
    • 고급 매핑
      • 상속 관계 매핑
      • @MappedSuperclass
      • 복합 키와 식별 관계 매핑
      • 조인 테이블
    • 프록시와 연관관계 관리
      • 프록시
      • 즉시 로딩과 지연 로딩
      • 영속성 전이, 고아 객체
    • 값 타입
      • 임베디드 타입
      • 값 타입과 불변 객체
      • 값 타입의 비교, 컬렉션
    • 객체지향 쿼리 언어
      • JPQL part1
      • JPQL part2
      • JPQL part3
      • QueryDSL
      • NativeSQL
      • 객체지향 쿼리 심화
    • 응용 애플리케이션
      • 엔티티 설정
    • 스프링 데이터 JPA
      • 공통 인터페이스
  • Kotlin In Action
    • 코틀린의 특징
    • 코틀린의 기초
    • 함수 정의와 호출
    • 클래스, 객체, 인터페이스
    • 람다 방식
    • 코틀린 타입 시스템
    • 연산자 오버로딩과 기타 관례
    • 고차함수
    • 제네릭스
    • 애노테이션과 리플렉션
    • 코루틴
  • Oracle
    • Oracle 기본
    • Oracle 심화
  • SQL_연습
    • Revising the Select Query
    • Basic Select
    • Advanced Select
    • Basic Select 2
  • SQL 첫걸음(책)
    • Day 1
    • Day 2
    • Day 3
    • Day 4
    • Day 5
    • Day 6
    • Day 7
    • Day 8
    • Day 9
    • Day 10
    • Day 11
    • Day 12
    • Day 13
    • Day 14
    • Day 15
    • Day 16
    • Day 17
    • Day 18
    • Day 19
    • Day 20
    • Day 21
    • Day 22
    • Day 23
    • Day 24
    • Day 25
    • Day 26
    • Day 27
    • Day 28
    • Day 29
    • Day 30
  • 더 자바 코드를 조작하는 다양한 방법
    • JVM 이해하기
    • 바이트코드 조작
    • 리플렉션
    • 다이나믹 프록시
    • 애노테이션 프로세서
  • 더 자바, 애플리케이션을 테스트하는 다양한 방법
    • JUnit5
    • Mockito
    • 도커와 테스트
    • 성능, 운영이슈, 아키텍처 테스트
  • 이펙티브 자바
    • item1 - 생성자 대신 정적 팩토리 메소드를 고려하라
    • item2 - 생성자에 매개변수가 많다면 빌더를 고려하라
    • item3 - 생성자나 열거타입으로 싱글턴임을 보증하라
    • item4 - 인스턴스화를 막기 위해선 private 생성자를 사용하라
    • item5 - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
    • item6 - 불필요한 객체 생성을 피하라
    • item7 - 다 쓴 객체 참조를 해제하라
    • item8 - finalizer와 cleaner 사용을 피하라
    • item9 - try-finally 보다 try-with-resources을 사용하라
    • item10 - equals는 일반 규약을 지켜 재정의하라
    • item11 - equals을 재정의하려면 hashCode도 재정의하라
    • item12 - toString을 항상 재정의하라
    • item13 - clone 재정의는 주의해서 진행하라
    • item14 - Comparable을 구현할지 고민하라
  • Elastic Search
    • 강의 Summary
    • Elastic Summary 개념 정리
    • Elastic Summary 적용 정리
  • 토비의 스프링 강의
    • 스프링부트 살펴보기
    • 독립 실행형 서블릿 애플리케이션
  • k8s
    • minikube 설치
    • jenkins 추가
  • Article
    • Choosing the Right MessageBroker
Powered by GitBook
On this page
  • 애노테이션 프로세서를 만들어보자
  • 이러한 Annotation Processor를 어디서 사용하냐?

Was this helpful?

  1. 더 자바 코드를 조작하는 다양한 방법

애노테이션 프로세서

아주 좋은예시로는 롬복이 존재한다

롬복이 없다면 getter, setter, constructor, toString, equals, hashcode 등등 이러한 중복되는 코드들을 항상 손으로 작성해야 한다 롬복의 애노테이션인 @Getter, @Setter, @AllArgsConstructor, @ToString, @EqualsAndHashCode 등을 넣어주면 실제 코드에는 그러한 구현체가 없었지만 -> 실제로 코드에서 사용하려고 보면 정상적으로 사용되는 것들을 사용할 수 있다는 점!

이러한 신기한 기능이 동작하는 원리는 이러하다 우선 애노테이션 프로세서는 컴파일 시점에 작동하는 기능이고 애노테이션 프로세서는 컴파일 시점에 끼어들어서 특정한 애노테이션이 붙어 있는 놈들을 참조해서 또 다른 소스코드를 생성하는 방식이다 여기서의 소스코드람은 굳이 자바에 한정되지 않고 문서와 같은 다른 언어들도 가능하다

컴파일 시점에 애노테이션 프로세서를 통해서 소스코드의 Abstract Syntax Tree(AST)를 조작한다 Syntax Tree란 -> 소스 코드의 구성을 순서도와 같이 생긴거로 만드는 방식이다

일단 기존의 소스 코드를 조작하는 것이 정상적인 사용법이 아니다 실제로 코드를 보면 단순하게 애노테이션만 붙어 있지만, 바이트 코드에서 만들어진 것을 보면 해당 애노테이션에 맞는 코드가 들어가 있는 상황이다 그래서 갑을논박이 진행되기도 한다네요

애노테이션 프로세서를 만들어보자

애노테이션을 선언할때는 Retention을 설정해준다 이놈은 해당 애노테이션을 어디까지 유지할 것인가 애노테이션이란 놈은 컴파일시에 사용하고, 바이트 코드에서는 필요가 없다 그러면 RetentionPolicy.CLASS는 바이트 코드까지 간다는 의미이기 때문에 필요 없고 RetentionPolicy.SOURCE까지만 주면 된다

그렇게 먼저 애노테이션을 선언하고, 해당 애노테이션의 동작을 맡을 프로세서를 만들어야 한다 프로세서를 만들기 위해서는 자바에서 제공하는 AbstractProcessor 를 상속받으면서 사용할 수 있다 기본적인 함수들은 원하는대로 찾아보고 사용할 수 있고 대표적인 것들을 보자

getSupportedAnnotationTypes() 이 함수는 이걸 구현한 프로세서가 어떠한 애노테이션을 처리할 것인지 명시해주는 곳이다 단순하게

public Set<String> getSupportedAnnotationTypes(){
    return Set.of(만든애노테이션.class.getName());
}

이렇게 사용할 수 있다

다음으로는 process()이라는 함수인데 이놈이 해당 애노테이션을 붙혔을 때 어떠한 작업을 할 것인지 구현하는 곳이다

public boolean process(Set<? extends TypeElement> annotations, RoundEnvirnment roundEnv){
    return false;
}

해당 파라미터로는 annotations과 RoundEnvironment 이렇게 2가지가 들어가게 되는데 RoundEnvironment는 애초에 processor라는 개념은 다양한 라운드에 걸쳐서 진행이되는데 마치, 안드로이드에서의 생명주기와 같다고 볼 수 있고 이 라운드를 의미한다 리턴타입으로는 기본적으로 boolean으로 잡혀있는데 default값으로는 true가 잡혀있다 -> 이 의미는 해당 애노테이션을 다음 라운드(생명주기)에서도 처리를 할 예정이라는 의미이다 그래서 false로 잡는다면 해당 함수(process)에서만 사용하겠다는 의미이다

해당 구현내용은 이러하다 우선은 해당 애노테이션이 적절한 위치(메소드, 필드 등)에 사용되었는가를 확인한다

Set<? extneds Element> elements = roundEnv.getElementsAnnotatedWith(애노테이션.class);

만약 이렇게되면 애노테이션을 선언할때 사용하는 @Target에서 elements.getKind()을 통해서 ElementKind 타입을 비교해가면서 확실하게 사용하는 것이 가능하다

일단 사용하는데 있어서 적당한 위치에 사용했는지를 우선 체크했고, 그 다음으로는 소스코드를 생성하는 것을 확인해보자 자바 소스 코드를 생성하는데 아주 유용한 라이브러리는 Javapoet 이라는 라이브러리가 있다 우선 의존성을 주입해주고,

우선은 element를 TypeElement으로 형변환을 해두고 -> 클래스를 만들고 -> 메소드를 만든다

TypeElement type = (TypeElement)element;
//클래스 생성
ClassName className = ClassName.get(typeElement);

//메소드 생성
MethodSpec createdMethodName = MethodSpec.methodBuilder("createdMethodName")
                                .addModifiers(Modifier.PUBLIC)
                                .returns(String.class)
                                //$에 대한 변수를 뒤에 인자로 넣어준다
                                .addStatement("return $S", "returnString")
                                .build();
                                
TypeSpec createdClassName = TypeSpec.classBuilder("createdClassName")
                                .addModifiers(Modifier.PUBLIC)
                                .addMethod(createdMethodName)
                                .build();
                                

여기까지 구현한 것은 클래스의 형태를 가진 객체를 만든 것이고 메모리에 저장되어있는 상황이다 그러면 이 객체를 실제로 파일로 만들어서 쏴 애노테이션을 선언한 곳에서 컴파일시에 소스코드로 만들어서 저장해둘 것이다

그리고 filer 이라는 소스 코드, 클래스 코드 및 리소스를 생성할 수 있는 인터페이스를 통해서 생성해야한다 생성한 프로세서(AbstractProcessor를 상속받은)에는 processingEnv이라는 변수를 AbstractProcessor 에서 제공해주고 있다

Filer filer = processingEnv.getFilter();
//여기 JavaFile을 통해서 최종적으로 파일을 생성하게 되는데, 우선적으로는 패키지명을 적어줘야하고, 해당 패키지명은 기본적으로 element변수와 같은 위치에 있는 것이 자연스럽다
JavaFile.builder(className.getPackageName(), createdClassName).build().writeTo(filer);

이렇게까지 해줘야 소스코드가 생성될 수 있으며, 저렇게 파일을 생성하는 코드에는 Exception을 따로 try-catch으로 처리해두고 원하는 에러 메세지를 출력할 수 있다

뭐 대충 이렇게 만들 수 있고 해당 애노테이션을 직접 사용하기 위해서는 애노테이션을 등록해줘야한다 그 방법은, resource 패키지 밑에 META-INF을 생성하고 그 밑에 services라는 패키지를 만들고 그 밑에 javax.annotation.processing.Processor 파일을 만들고 우리가 만든 프로세서의 패키지명을 작성해주면된다 근데 위에서 만든 케이스같은 경우에는 해당 애노테이션을 만들려고하는 시점이 소스를 컴파일할 때가 아닌데, 컴파일(빌드)하는 시점에 해당 프로세서가 돌아갈려고 하기 때문에 빌드에 실패한다 -> 이 문제는 애노테이션을 주석처리해두고 빌드해두고, 클린하지 말고 빌드하면 잘 작동된다 이런 방식으로는 너무 귀찮기도하고 패키지도 수동으로 만들어줘야하기 때문에 매우 귀찮다 이러한 것을 해결해주는게 google에서 만든 @AutoService라는 애노테이션이다 -> 요놈은 단순하게 만든 프로세서 위에 @AutoService(Processor.class) 이렇게만 작성해둬도 알아서 만들어진다..! Java Service Provider?는 뭐지..?

자 이렇게 만들고 나면 어떻게 사용하냐 우선 빌드하고나면 해당 프로젝트 정보(groupId, artifactId, version)을 가지고 사용하려는 프로젝트의 gradle에 적용하고 gradle을 돌려보면 External Libraries에 들어갈 것이다 그럼 이제는 그냥 쓰면 잘 돌아갈 예정이다!!! 추가적으로 IDE에서 Annotation Processor 설정에서 Enable annotation processing을 체크해줘야하는 사항을 기억하자 그리고 target/generated-sources/annotations/패/키/지/ 에 위에서 작성한 값들이 만들어져서 들어가 있다

진짜 신기하다... 토이때 꼭만들어보자....

이러한 Annotation Processor를 어디서 사용하냐?

애노테이션 프로세서는 소스코드 레벨에서, 소스코드에 붙어있는 애노테이션의 정보를 읽어서 컴파일러가 컴파일중에 새로운 소스코드를 생성하거나 기존 코드까지도 수정할 수 있다 크게 롬복, AutoService, @Override 등에서 사용하고 있다 애노테이션 프로세서를 사용하게되면 컴파일시에 코드를 처리해두기 때문에 런타임시에 들어가는 비용이 없다는 것이 장점이다

Previous다이나믹 프록시Next더 자바, 애플리케이션을 테스트하는 다양한 방법

Last updated 2 years ago

Was this helpful?