티스토리 뷰

스프링은 어노테이션을 기반으로 구성되어 있습니다. 어노테이션이란 무엇이고 스프링에서는 왜 어노테이션을 기반으로 구성하게 되었는지 정리해 보고자 글을 작성하게 되었습니다.

어노테이션

어노테이션은 사전적 의미로 주석이라는 뜻을 가지고 있다. 자바에서 어노테이션은 소스 코드에 추가해서 사용할 수 있는 메타 데이터의 일종이다. 메타 데이터란 애플리케이션이 처리해야 할 데이터가 아니라 컴파일 및 런타임 과정에서 코드를 어떻게 처리해야 할지 알려주기 위한 추가 정보이다. 자바 어노테이션은 JDK 1.5 버전 이상에서부터 사용가능하며, 자바 어노테이션은 클래스 파일에 임베드되어 컴파일러에 의해 생성된 이후 JVM에 포함되어 동작한다. 어노테이션이 나오기 이전에는 XML 및 마커 인터페이스를 통해 추가적인 정보를 제공할 수 있었다.

 

[ 어노테이션 장점 ]

  1. 코드 가독성 : 어노테이션은 코드와 설정을 같은 위치에 배치하므로 읽고 이해하기 쉽다. 클래스, 메서드, 필드, 파라미터 등 연관된 코드와 가까이 있기 때문에 흐름을 따라가기 쉽다.
  2. 설정의 간소화 : 별도의 설정 파일 작성 없이 어노테이션 적용을 통해 설정을 간소화할 수 있다.
  3. 중복 코드 제거 : 공통적인 코드 패턴이나 설정을 재사용할 수 있기 때문에 코드의 중복을 줄이고 효율적으로 코드를 작성할 수 있다.
  4. 커스텀 어노테이션 : 직접 커스텀 어노테이션을 정의함으로 필요한 기능이나 제약 사항을 정의하여 사용할 수 있다.
  5. 프로세서를 통한 검증 및 코드 생성 : 어노테이션 프로세서를 이용해 컴파일 시점에 어노테이션을 처리하고 검증할 수 있다. 또한 코드를 자동으로 생성하거나 수정할 수 있기에 효과적으로 기능을 구현할 수 있다.

 

[ 어노테이션 단점 ]

  1. 런타임 오버헤드 : 런타임 시점에 리플렉션을 사용하여 처리하는 어노테이션의 경우 성능상의 오버헤드가 발생할 수 있다.
  2. 컴파일 시점 제한 : 어노테이션도 컴파일 시점에 오류를 확인할 수 있지만, 어노테이션 로직이 런타임에 에러를 발생시키거나 어노테이션에 잘못된 값이 할당된 경우 컴파일 시점에 오류를 확인할 수 없을 수도 있다.

마커 인터페이스

마커 인터페이스는 일반적인 인터페이스와 동일하지만 아무런 메서드도 선언하지 않은 인터페이스를 말한다. 특별한 역할을 하기보다는 어노테이션과 같이 클래스에 대한 메타 데이터를 제공하는 데 사용된다. 주로 런타임 시점에 객체의 속성을 확인하기 위한 목적을 가지고 있다.

public interface Serializable {

}

대표적인 마커 인터페이스로는 Serializable이 있다. Serializable 인터페이스를 구현을 통해 해당 클래스는 직렬화될 수 있음을 나타낸다. 바이트 스트림으로 변환되어 다른 시스템으로 전송되거나 저장소에 저장될 수 있다.

 

[ 마커 인터페이스 장점 ]

  1. 타입 체크 : 마커 인터페이스를 사용하면 컴파일 시점에 타입을 확인할 수 있다. 어노테이션을 사용했을 때는 컴파일 시점에 타입 확인이 어려울 수도 있다.
  2. 추상화와 다형성 : 마커 인터페이스를 사용하면 인터페이스의 구현이기에 추상화와 다형성을 활용할 수 있다. 어노테이션은 인터페이스의 추상화와 다형성은 지원하지 않는다.

 

[ 마커 인터페이스 단점 ]

  1. 클래스 계층 구조 : 인터페이스를 구현하기에 클래스 계층 구조를 형성하게 되므로 유연성이 떨어질 수 있다.
  2. 확장성 : 메서드를 만드는 순간 하위 호환성이 깨지기 때문에 어노테이션처럼 지속적인 확장이 불가능하다.

자바 빌트인 어노테이션

자바 빌트인 어노테이션은 자바에서 제공하는 어노테이션을 의미한다.

  • @Override : 하위 클래스 메서드가 상위 클래스 메서드를 재정의하는 것을 의미한다. 철자와 같은 실수를 할 수 있기에 메서드가 재정의되도록 보장하는 어노테이션을 표시하는 것이 좋다.
  • @SuppressWarnings : 컴파일러에서 발생하는 경고를 억제하는 데 사용된다.
  • @Deprecated : 컴파일러가 이 메서드가 사용되지 않도록 경고를 보여주는 데 사용된다. 해당 어노테이션이 붙은 메서드는 향후 버전에서 제거될 수 있기 때문에 사용하지 않는 것이 좋다.
  • @SafeVarargs : 제네릭 같은 가변인자 매개변수를 사용할 때 경고를 무시한다.
  • @FunctionalInterface : 람다식을 위한 인터페이스를 지정한다. 함수형 인터페이스에 사용하기 적합하지 않은 경우 컴파일 오류가 발생한다.

메타 어노테이션

어노테이션을 위한 어노테이션으로 어노테이션을 정의할 때 사용된다.

 

[ @Documented ]

해당 어노테이션을 사용하면 문서화될 수 있음을 나타낸다. 따라서 자바 문서에도 어노테이션 정보가 표시될 수 있다.

 

[ @Retention ]

  • RetentionPolicy.SOURCE : 컴파일 이후에는 삭제된다.
  • RetentionPolicy.CLASS : 컴파일러에 의해 클래스 파일에 기록되지만 실행 시 유지될 필요는 없다.
  • RetentionPolicy.RUNTIME : 컴파일러에 의해 클래스 파일에 기록되고 실행 시 유지된다.

 

[ @Target ]

어노테이션이 적용될 수 있는 위치를 정의한다.

  • ElementType.TYPE : 클래스, 인터페이스, 어노테이션, 열거형에 선언될 수 있다.
  • ElementType.FIELD : 열거형을 포함한 필드에 선언될 수 있다.
  • ElementType.METHOD : 메서드에 선언될 수 있다.
  • ElementType.PARAMETER : 파라미터에 선언될 수 있다.
  • ElementType.CONSTRUCTOR : 생성자에 선언될 수 있다.
  • ElementType.LOCAL_VARIABLE : 지역 변수에 선언될 수 있다.
  • ElementType.PACKAGE : 패키지에 선언될 수 있다.
  • ElementType.TYPE_PARAMETER : 제네릭 타입 파라미터에 선언될 수 있다.
  • ElementType.TYPE_USE : 클래스, 인터페이스, 제네릭 타입, 배열, 캐스팅, 람다 표현식 등 타입 사용 위치에 선언될 수 있다.
  • ElementType.MODULE : 모듈에 선언될 수 있다.

 

패키지 어노테이션은 아래와 같이 사용할 수 있다.

/*
com/example/package-info.java
*/
@PackageAnnotation
package com.example;
public static void main(String[] args) {
	Package pkg = com.example.package-info.class.getPackage();
    PackageAnnotation annotation = pkg.getAnnotation(PackageAnnotation.class);
    
    // ...
}

 

[ @Inherited ]

기본적으로 어노테이션은 하위 클래스에 상속되지 않는데 해당 어노테이션이 선언된 어노테이션은 상속된다.

 

[ @Repeatable ]

어노테이션을 반복적으로 선언할 수 있다.

커스텀 어노테이션

기존에 있는 어노테이션을 혼합하여 재활용하는 방법도 있지만, 사용하고자 하는 어노테이션을 직접 정의해서 사용할 수 있다. 앞서 설명한 메타 어노테이션을 바탕으로 문서화 가능, 실행 시 유지, 파라미터에 선언될 수 있는 커스텀 어노테이션을 정의하면 아래와 같다.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface CustomAnnotation {

}

필요에 따라 필드나 메서드를 선언해서 사용할 수 있다.

스프링을 어노테이션 기반으로 만든 이유

어노테이션의 장점을 바탕으로 스프링을 어노테이션 기반으로 만든 이유를 생각해 볼 수 있다. XML을 통한 복잡한 설정으로 인해 코드의 복잡성이 올라가게 되고 이는 가독성을 떨어뜨리고 유지보수를 어렵게 만드는 요인이 된다. 이러한 문제점으로 인해 스프링에서는 어노테이션 기반 구성을 지원하도록 한다. 어노테이션 기반 구성은 가독성, 유지 보수, 간결함, 표준화 등의 측면에서 장점이 존재한다. 따라서 개발자들은 더 효율적이고 명확한 코드를 작성할 수 있다. 그렇다고 XML 구성을 지원하지 않는 것은 아니다. 두 방식을 함께 사용할 수 있기 때문에 프로젝트 요구사항에 맞춰 선택할 수 있는 유연성도 제공하고 있다.

댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Total
Today
Yesterday