1일차 미션(어노테이션)

맨 아래에 미션 내용이 있습니다.

(미션을 하면서 학습한 내용을 함께 작성하였습니다.)

 

 

Annotations

어노테이션은 메타데이터의 형태로 프로그램에 대한 데이터를 제공한다. 어노테이션은 코드의 작동에 직접적인 영향을 미치지 않는다.

어노테이션은 다음과 같은 사용을 한다.

  • 컴파일러에게 정보 제공 - 어노테이션은 컴파일러가 에러나 경고를 막기위해 사용된다.

  • 컴파일 시 및 배포 시 처리 - 소프트웨어 도구는 어노테이션 정보를 가지고 코드, XML 파일 등을 생성할 수 있다.

  • 런타임 처리 - 일부 어노테이션은 런타임 시(실행 시) 확인될 수 있고, 이를 기반으로 추가적인 동작이나 처리를 수행할 수 있다.

Annotation 기본사항

  • @Annotation 형태

  • @는 뒤에 오는 내용이 어노테이션임을 컴파일러에게 나타낸다.

  • element가 한개인 경우 name을 생략할 수 있다. element가 없는 경우 @Override처럼 괄호를 생략할 수 있다.

    @Author(
       name = "Benjamin Franklin",
       date = "3/27/2003"
    )
    class MyClass { ... }
    or
    
    @SuppressWarnings(value = "unchecked")
    void myMethod() { ... }
    
    @SuppressWarnings("unchecked")
    void myMethod() { ... }
    
  • 여러개의 어노테이션을 사용할 수 있다.

    @Author(name = "Jane Doe")
    @EBook
    class MyClass { ... }
    
  • 같은 타입을 가지는 어노테이션들을 repeating 어노테이션이라 한다. 자바 8버전부터 지원

    @Author(name = "Jane Doe")
    @Author(name = "John Smith")
    class MyClass { ... }
    

어디서 어노테이션이 사용되는가?

  • 어노테이션은 클래스, 필드, 메소드, 다른 프로그램의 요소 선언에 적용될 수 있다.

  • 클래스 객체 생성 표현식 (new @Interned MyObject(); ) , 형변환, implements 절, 발생한 예외 선언 절에서도 사용된다. 이러한 형태의 어노테이션은 “타입 어노테이션”이라 한다. 자바 8에서 생겨남

어노테이션 타입 선언

어노테이션으로 코드 내의 주석들을 대체할 수 있다.

예를들어서 ‘모든 클래스 시작에 아래와 같이 중요한 주석들을 단다’ 라는 규칙이 있다고 생각해보자.

public class Generation3List extends Generation2List {

   // Author: John Doe
   // Date: 3/17/2002
   // Current revision: 6
   // Last modified: 4/12/2004
   // By: Jane Doe
   // Reviewers: Alice, Bill, Cindy

   // class code goes here

}
To add t

어노테이션으로 동일한 내용의 메타데이터를 추가하기 위해서는, 사전에 아래와 같은 문법을 사용해서 어노테이션 타입을 정의해야한다.

@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   // Note use of array
   String[] reviewers();
}
  • 어노테이션 선언 시 interface 키워드 앞에 @를 붙여야한다.

  • 어노테이션 타입은 인터페이스 형태이다.

  • 메소드와 비슷하게 어노테이션 타입 요소 선언이 포함되어있다. 이 때 기본값을 정의할 수 있다.

  • 어노테이션을 정의하면 아래와 같이 사용가능하다.

@Documented : // 만약에 javadoc에 포함시키고싶으면 해당 어노테이션 추가
@ClassPreamble (
   author = "John Doe",
   date = "3/17/2002",
   currentRevision = 6,
   lastModified = "4/12/2004",
   lastModifiedBy = "Jane Doe",
   // Note array notation
   reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {

// class code goes here

}

미리 선언된 어노테이션 타입들

  • 자바 언어에서 사용되는 어노테이션

    • @Deprecated

    • @Override

    • @SuppressWarnings (컴파일러가 생성할 특정 경고 억제)

    • @SafeVarargs

    • @FunctionalInterface

  • 다른 어노테이션에 적용되는 어노테이션 : 메타 어노테이션

    • @Retention

    • @Documented

    • @Target

    • @Inherited

    • @Repeatable

Type Annotations and Pluggable Type Systems

  • 자바 8 이전에는 어노테이션을 선언에만 적용 가능

  • 이후에는 어떤 타입 사용에도 적용 가능

반복 어노테이션

  • 동일한 어노테이션을 한 선언 또는 타입에서 여러번 사용

  • ex) 타이머 서비스를 사용하는 코드에서 특정 메소드를 매월 마지막 날, 매주 금요일 오후 11시에 실행하도록 타이머를 설정하기 위해 @Schedule 어노테이션 두번 사용

    @Schedule(dayOfMonth="last")
    @Schedule(dayOfWeek="Fri", hour="23")
    public void doPeriodicCleanup() { ... }
    
  • 사용법

    1. 반복 가능한 어노테이션 타입 선언

    import java.lang.annotation.Repeatable;
    
    @Repeatable(Schedules.class)
    public @interface Schedule {
      String dayOfMonth() default "first";
      String dayOfWeek() default "Mon";
      int hour() default 12;
    }
    
    1. 컨테이닝 어노테이션 타입 선언 : @Schedules어노테이션은 Schedule 어노테이션을 array로 저장할 수 있는 value 요소를 가져야함

    public @interface Schedules {
        Schedule[] value();
    }
    

Lesson: Annotations (The Java Tutorials > Learning the Java Language)

  • 어노테이션을 직접 만들어 쓸 수 있다.

    @interface 어노테이션이름{
        타입 요소이름();    // 어노테이션의 요소를 선언한다.
          ...
    }
    
    @interface DateTime{
        String yymmdd();
        String hhmmss();
    }
    
  • 어노테이션의 메서드는 추상 메서드이며, 어노테이션을 적용할 때 지정(순서 X) 추상 메서드는 구현할 필요가 없음

    @interface TestInfo{
        int count();
        String testedBy();
        String[] testTools();
        TestType testType();  // enum TestType { FIRST, FINAL }
        DateTime testDate(); //자신이 아닌 다른 어노테이션 포함 가능
    
  • 적용시 값을 지정하지 않으면, 사용될 수 있는 기본값 지정 가능(null제외)

    @interface TestInfo{
        int count() default 1;
    }
    @TestInfo
    public class newClass{ ... }
    
  • 요소가 하나이고 이름이 value일 때는 요소의 이름 생략가능

    @interface TestInfo{
        String value();
    }
    @TestInfo("passed")    // @TestInfo(value="passed")와 동일
    class newClass{ ...    }
    
  • 요소의 타입이 배열인 경우, 괄호{}를 사용해야 한다

    @interface TestInfo{
        String[] testTools();
    }
    @Test(testTools={"JUnit", "AutoTester"})
    @Test(testTools="JUnit")
    @Test(testTools={}) // 값이 없을 때는 괄호{}가 반드시 필요
    
  • 모든 어노테이션의 조상

    • Annotation은 모든 어노테이션의 조상이지만 상속은 불가

    • 사실 Annotation은 인터페이스다.

  • 마커 어노테이션

    • 요소가 하나도 정의되지 않은 어노테이션

    • @Test, @Deprecated

  • 어노테이션 요소의 규칙

    • 요소의 타입은 기본형, String, enum, 어노테이션, Class만 허용

    • 추상메서드의 괄호 ()안에 매개변수를 선언할 수 없다

    • 예외를 선언할 수 없다

    • 요소를 타입 매개변수로 정의할 수 없다. <T>

[자바의 정석 - 기초편] ch12-23,24 애너테이션

실제로 직접 만들어서 사용할만한 어노테이션에는 뭐가 있을까?

  • 프로젝트를 하지 않아서 실제로 어떨 때 필요할 지 와닿지 않음

  • 지피티에게 물어본 결과

  1. @JsonField:

    • 해당 필드가 JSON 직렬화/역직렬화 대상임을 나타내는 어노테이션.

    javaCopy code
    public class MyObject {
        @JsonField
        private String name;
    
        @JsonField
        private int age;
    
        // ...
    }
    
  2. @NotNull:

    • 매개변수나 필드가 null이 아니어야 함을 나타내는 어노테이션.

    javaCopy code
    public void someMethod(@NotNull String parameter) {
        // 메서드 로직
    }
    
  3. @RetryOnFailure:

    • 메서드나 함수가 실패할 경우 지정된 횟수만큼 자동으로 재시도하도록 하는 어노테이션.

    javaCopy code
    @RetryOnFailure(maxAttempts = 3)
    public void someOperation() {
        // 작업 로직
    }
    
  4. @LogPerformance:

    • 메서드의 실행 시간을 로그에 기록하는 어노테이션.

    javaCopy code
    @LogPerformance
    public void performanceCriticalMethod() {
        // 성능 중요한 작업 로직
    }
    
  5. @SecureAccess(role = "ADMIN"):

    • 특정 역할이나 권한을 요구하는 보안 접근을 나타내는 어노테이션.

    javaCopy code
    @SecureAccess(role = "ADMIN")
    public void adminOnlyOperation() {
        // 관리자 권한이 필요한 작업 로직
    }
    

이러한 예시처럼 프로젝트의 특정 요구사항에 맞게 어노테이션을 설계하고 사용할 수 있습니다. 직접 만든 어노테이션을 사용하면 코드의 가독성을 높이고 개발자들 간의 일관성을 유지할 수 있습니다.

어노테이션을 사용하는 이유 (효과) 는 무엇일까?

개발자 관점에서 @Override와 같은 어노테이션을 사용하면 해당 메서드가 상위 클래스에서 오버라이드 된 것임을 확실하게 알 수 있다. 즉 코드를 읽을때 유용하고 의도를 명확하게 전달할 수 있다.

컴파일러 관점에서 컴파일러가 @Override어노테이션 정보를 통해 상위 클래스에 해당 메서드가 존재하는지 확인하고, 아니면 오류를 발생시킬 수 있다. 즉

즉 어노테이션은 개발자에게 코드 작성 시 명확한 정보를 제공하고, 컴파일러에게는 코드의 일관성과 정확성을 검증할 수 있는 수단으로 활용된다.

 

<gpt>

자바에서 어노테이션(Annotation)은 코드에 메타데이터를 추가하는 방법으로 사용됩니다. 어노테이션은 주석과는 다르게 컴파일러나 런타임 시에 코드에 대한 정보를 제공하며, 다양한 목적으로 활용됩니다. 몇 가지 주된 이유는 다음과 같습니다:

  1. 코드 문서화 및 가독성 향상: 어노테이션을 사용하면 코드에 추가적인 정보를 주석으로 달지 않고도 문서화할 수 있습니다. 예를 들어, @Deprecated 어노테이션은 해당 메서드나 클래스가 더 이상 권장되지 않음을 나타냅니다.

  2. 컴파일 타임 체크: 일부 어노테이션은 컴파일러에게 특정 경고나 오류를 생성하도록 알려줄 수 있습니다. 예를 들어, 널 포인터 예외를 방지하기 위해 사용되는 @NonNull 어노테이션 등이 있습니다.

  3. 런타임 처리와 리플렉션: 몇몇 어노테이션은 런타임에 정보를 검색하거나 특정 동작을 수행할 수 있도록 해줍니다. 예를 들어, 스프링 프레임워크에서는 @Autowired 어노테이션을 사용하여 의존성 주입을 수행합니다.

  4. 프레임워크와 라이브러리 통합: 어노테이션은 프레임워크나 라이브러리에서 특정 기능을 활성화하기 위한 힌트로 사용됩니다. 예를 들어, JUnit에서는 @Test 어노테이션을 사용하여 테스트 메서드를 식별하고 실행합니다.

  5. 커스텀 마커 어노테이션: 프로그래머가 자신만의 어노테이션을 정의하여 특정 상황에 대한 힌트를 추가하거나, 프레임워크에서 사용할 수 있는 커스텀 마커로 활용할 수 있습니다.

이러한 이유로 어노테이션은 자바의 다양한 분야에서 사용되며, 코드의 가독성과 유지보수성을 향상시키고 추가적인 기능을 제공합니다.

 

나만의 어노테이션은 어떻게 만들 수 있을까?

  1. @interface키워드를 사용하여 어노테이션을 정의한다

  2. 요소를 정의한다 : 필요한 속성이나 요소 정의하고 기본값 설정

  3. 적용한 어노테이션을 다른 코드에서 적용하여 사용하며, 필요한 경우 리플렉션을 활용하여 어노테이션의 정보를 읽을 수 있다.

MyAnnotation.interface

package com.group.libraryapp.annotationTest;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    String name();
    String value() default "value의 기본 값";
}

Class.java

package com.group.libraryapp.annotationTest;

public class Class {
    @MyAnnotation(name = "비둘기",value = "pigeon")
    public void doThis(){

    }

    @MyAnnotation(name = "pigeon")
    public void doThat(){

    }
}

MethodAnnotationExecutor.java

package com.group.libraryapp.annotationTest;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class MethodAnnotationExecutor {
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Class.class.getMethod("doThis");
        Annotation[] annotations = method.getDeclaredAnnotations();

        for(Annotation annotation : annotations){
            System.out.println(annotation);
            if(annotation instanceof MyAnnotation){
                MyAnnotation myAnnotation = (MyAnnotation) annotation;
                System.out.println("name : " + myAnnotation.name());
                System.out.println("value : " + myAnnotation.value());
            }
        }
    }
}

댓글을 작성해보세요.

채널톡 아이콘