[질문]
- 어노테이션을 사용하는 이유 (효과) 는 무엇일까?
어노테이션의 의미는 주석 -> 인터페이스를 기반으로 한 문접(어노테이션을 생성하는 방싱에서 @interface를 사용한다.)
메타 데이터로 이용되고 클래스, 메서드, 변수, 매개변수 및 패키지 등에 주석처럼 달아서 사용함.
기존 자바 웹 애플리케이션들은 설정값을 XML 파일에 명시하여 관리 -> 변경될 수 있는 데이터들은 코드가 아닌 외부 설정 파일에 분리하기 때무넹, 재컴파일 없어도 쉽게 변경사항이 저장 가능하다.
기존의 자바 웹 애플리케이션들은 대부분 설정값을 XML파일에 명시하영 관리 / 변경될 수 있는 데이터들은 코드가 아닌 외부 설정 파일 XML에 분리하기 때문에 재컴파일 없이도 쉽게 변경사항 저장 가능
이러한 문제점을 해결하기 위해 고안된 문법이 Annotation
어노테이션을 사용하면 데이터에 대한 유효성 검사조건을 보다 쉽게 파악할 수 있게 되며 코드가 깔끔해진다.
단순히 부가적인 표현뿐만 아니라 리플렉션을 이용하면 어노테이션 지정만으로 원하는 클래스를 주입할 수 있다.
- Annotation 용도
- 1. @Override 어노테이션 처럼 컴파일러를 위한 정보를 제공하기 위한 용도
- 3. 컴파일 과정에 어노테이션 정보로부터 코드를 생성하기 위한 용도
- 2. 스프링 프레임워크의 @Controller 어노테이션 처럼 런타임에 리플렉션을 이용해서 특수 기능을 추가하
출처 : https://sassun.tistory.com/57
- 나만의 어노테이션은 어떻게 만들 수 있을까?
커스텀 어노테이션을 만들 때 몇가지 규칙이 있다.
어노테이션 타입은 @interface로 정의 해야한다. 모든 어노테이션은 자동적으로 java.lang.Annotation 인터페이스를 상속하기 때문에 다른 클래스나 인터페이스를 상속 받으면 안된다.
파라미터 멤버들의 접근자는 public이거나 default여야만 한다.
파라미터 멤버들은 byte,short,char,int,float,double,boolean,의 기본타입과 String, Enum, Class, 어노테이션만 사용할 수 있다.
클래스 메소드와 필드에 관한 어노테이션 정보를 얻고 싶으면, 리플렉션만 이용해서 얻을 수 있다. 다른 방법으로는 어노테이션 객체를 얻을 수 없다.
Custom Annotation 의 예시
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {
enum Color{BLUE,RED,GREEN}
Color fruitColor() default Color.GREEN;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
String value() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
int id() default -1;
String name() default "";
String address() default "";
}
위에서 만든 Custom Annotation을 사용해보면 아래와 같이 사용할 수 있다.
public class Apple {
@FruitName("Apple")
private String appleName;
@FruitColor(fruitColor = FruitColor.Color.RED)
private String appleColor;
@FruitProvider(id = 1,name = "HomePlus",address = "Seoul")
private String appleProvider;
...getter setter
}
간단하게 spring에서 늘 사용하던 어노테이션 형식을 이런식으로 만들어서 사용하면 된다.
출처 : https://sh970901.tistory.com/114
예시를 한개 더 들어보자.
RestMemberController를 개발하여 Swagger로 문서화한다고 한다고 하고 여기서 @Api와 @RestController 어노테이션은 다른 RestController들에도 공통적으로 적용되는데 커스텀 어노테이션으로 만들어서 반복작업을 줄이는 작업을 해보자.
@Api
@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class RestMemberController {
private final MemberService memberService;
@ApiOperation("멤버 목록 반환")
@GetMapping("/list")
public ResponseEntity<String> upload() {
return ResponseEntity.ok(memberService.getList());
}
}
1. 어노테이션 생성
위에서 언급했던 것 처럼 인터페이스 앞에 @를 붙여서 생성할 수 있다.
public @interface RestControllerWithSwagger {
}
2. 메타 어노테이션 추가
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Target(ElementType.TYPE)
public @interface RestControllerWithSwagger {
}
출처 : https://mangkyu.tistory.com/130
애노테이션의 메타 정보가 언제 버려질지에 대한 타이밍을 설정한다.
SOURCE, CLASS, RUNTIME 중 하나를 선택할 수 있다.
RetentionPolicy.SOURCE
소스코드인 구간에만 유지되고 클래스 파일이 되는 컴파일 과정에서 애노테이션 정보는 사라진다.
RetentionPolicy.CLASS
.class 파일에 기록되고, 런타임에 버려진다.
클래스 파일까지만 유지된다.
자바에서의 기본 retention 이다.
The @Inherited 어노테이션은 이 어노테이션을 사용한 슈퍼클래스를 상속한 서브클래스에서도
해당 어노테이션을 갖도록 한다. 아래 예시를 보면,
java.lang.annotation.Inherited
@Inherited
public @interface MyAnnotation {
}
@MyAnnotation
public class MySuperClass { ... }
public class MySubClass extends MySuperClass { ... }
MySubClass 클래스는 @MyAnnotation 을 상속한다.
@Documented 어노테이션이 지정된 대상의 JavaDoc 에 이 어노테이션의 존재를 표기하도록 지정.
java.lang.annotation.Documented
@Documented
public @interface MyAnnotation {
}
@MyAnnotation
public class MySuperClass { ... }
출처: https://hamait.tistory.com/314 [HAMA 블로그:티스토리]
@Target
@Taget에는 어떤 값(클래스, 필드, 메서드…)에 어노테이션을 적용할 것인지 넣을 수 있다.
3. 적용할 어노테이션 추가
추가적으로 적용할 어노테이션이 있으면 추가해준다. 우리는 @Api와 @RestController라는 어노테이션을 공통으로 묶을 것이므로 이를 추가해준다.
@Api
@RestController
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Target(ElementType.TYPE)
public @interface RestControllerWithSwagger {
String name() default "RestController";
String value();
}
5. 추가한 어노테이션 클래스에 적용하기.
다음과 같이 적용할 수 있다.
@RestControllerWithSwagger(value = "RestMemberController", name = "RestMemberController")
@RequiredArgsConstructor
@Test1
@RequestMapping("/member")
public class RestMemberController {
private final MemberService memberService;
@ApiOperation("멤버 목록 반환")
@GetMapping("/list")
public ResponseEntity<String> upload() {
return ResponseEntity.ok(memberService.getList());
}
}
출처: https://mangkyu.tistory.com/130 [MangKyu's Diary:티스토리]
후기 :
인프런 강의를 통해서 어노테이션 사용법을 배웠는데 각각의 어노테이션의 뜻과 기능들을 잘 알지 못한채 사용한 거 같다. 스프링에는 여러 어노테이션이 있으며 그 범위가 매우 광범위하고 어려운 내용들이 많이 있기에 급한마음을 갖지 않고 천천히 학습을 하면서 프로젝트에 적용할 계획이다.
'Inflearn' 카테고리의 다른 글
인프런 워밍업 클럽 0기 - BE 5일차 과제 (0) | 2024.02.23 |
---|---|
인프런 워밍업 클럽 0기 - BE 4일차 과제 (0) | 2024.02.22 |
인프런 워밍업 클럽 0기 - BE 3일차 과제 (0) | 2024.02.21 |
인프런 워밍업 클럽 0기 - BE 2일차 과제 (1) | 2024.02.21 |