본문 바로가기
서버/스프링

스프링을 배우기 전에(1) - 어노테이션(Annotation)

by 나이아카 2021. 3. 4.

 회사에서 슬 스프링 부트와 관련된 코딩을 위해 준비를 하고 있습니다. 그에 맞춰 스프링에 대해서 어느 정도 공부하고 꾸준히 글로 옮길 예정입니다.

 그래서 먼저 스프링을 배우기 전에 필요한 여러가지 단어들 및 기술들을 끄적거린 후, 나중에 잘못 이해한 부분이나 제대로 글로 옮기지 못했던 부분도 수정하고... 회사에서 코딩을 시키기 전까지는 꾸준히 스프링에 대해서 쓸 예정입니다.

 

 그래서 첫 번째 주제는 어노테이션입니다. 이 어노테이션의 사전적 의미는 주석이라고 되어있습니다만, 주석처럼 코드 내부에서 아무런 영향도 미치지 못하는 것은 아닙니다. 스프링과 관련된 코드를 다루다 보면 다양한 종류의 어노테이션이 등장합니다.

 

 어노테이션을 사용하는 이유는 여러가지가 있는데 @Override와 같은 어노테이션을 사용할 경우, 컴파일러가 어노테이션을 통해 오버라이딩된 코드임을 파악해 확인하게 해줍니다. 이처럼 컴파일러에게 코드의 힌트를 제공해 기본적으로 확인할 수 없는 문법 에러를 파악할 수 있도록 도와줍니다. 

 이러한 어노테이션을 메타데이터와 같은 특성을 지녔다고 설명을 하는데, 이는 특정 단어(Aspect, Override등)를 통해 @가 존재하는 메소드 및 클래스의 정보를 알려주기 때문입니다.

 

 

먼저 자바에서 제공하는 기본적인 어노테이션들을 소개하겠습니다.

 

 

1. @Override: 이 어노테이션은 아마 자바와 관련된 코드를 사용하면서 자주 접해봤을 가능성이 높습니다. 이름처럼 오버라이딩되었음을 알려주는 어노테이션입니다. 이 어노테이션이 없다고 해서 오버라이딩을 못하는 건 아니지만(코틀린에서는 명시적으로 open - override를 사용해주어야 합니다.) 이 어노테이션을 통해 제가 만든 메소드가 제대로 오버라이딩 된 메소드가 맞는지 컴파일러가 문법적으로 확인할 수 있게 도와주는 역할을 합니다.

 

2. @Deprecated: 이 어노테이션의 경우, 관련된 기능(class 및 method)이 사라질 것임을 경고해줄 수 있습니다. 이 어노테이션이 존재하는 기능에는 ClassName 이런식으로 표시되며 IDE에서 제거 대상이라는 경고를 띄워주게 됩니다.

 

3. @SuppressWarnings: 어떠한 코드를 작성했을 때, 그 코드에서 경고 문구가 발생된 경우 그 경고를 무시하기 위해 코드의 상위 부분에 이 어노테이션을 작성할 수 있습니다. 만약 어떠한 클래스 내부에서 경고가 발생한 경우 그 메소드나 메소드를 들고 있는 클래스 위에 이 어노테이션을 삽입할 수 있습니다. 또한 이 어노테이션은 옵션이 존재합니다.

 

@SuppressWarnings("all")

 

all : 모든 경고 무시

boxing : boxing/unboxing과 관련되어 나타날 수 있는 경고 문구 무시

cast : 캐스트 연산자(강제 형변환 등)와 관련된 경고 무시

dep-ann : 잘못 사용된 주석 관련 경고 무시

deprecation : 사용이 자제되어야 하는 기능(@Deprecation이 달린 class 및 method와 같은)에 관한 경고 무시

fallthrough : switch문에서의 break 누락 관련 경고 무시

finally : try-catch에서 사용되는 finally 관련 경고 문구 무시

hiding : 부모 클래스의 기능(변수 및 클래스 등)을 하이딩할 때 생기는 경고 무시

incomplete-switch : switch 문에서 누락된 항목과 관련된 경고 무시

javadox : javadoc에 관련된 경고 무시

nls : 외부 리소스로 제공되지 않는 문자열 관련 경고 무시

null : nullable해서 문제가 발생할 수 있는 부분에 대한 경고 무시

rawtypes : 제네릭 클래스의 타입 파라미터 기술 관련 경고 무시

resource : close 관련 코드가 존재하는 기능(Scanner 등)에 close를 사용하지 않을 때 뜨는 경고 무시

restriction : 잘못된 경로거나, 사용이 금지된 참조(jar, library 등)와 관련된 경고 무시

serial : 직렬화가 가능한 클래스에서 누락된 serialVersionUID와 관련된 경고 무시

static-access : 잘못된 static-access와 관련된 경고 무시

static-method : static으로 선언될 수 있는 메서드와 관련된 경고 무시

super : super를 사용하지 않는 override 메소드에 관한 경고 무시

synthetic-access : 이너 클래스 관련 여러가지 공개되지 않은 접근 관련 경고 무시

sync-override : synchronized method 오버라이딩시 동기화 누락 경고 무시

unchecked : 검증되지 않은 연산자 관련 경고 무시

unqualified-field-access : 규정되지 않은 필드 액세스와 관련된 경고 무시

unused : 사용하지 않는 코드 삭제 요청 경고 무시

 

 

 이처럼 자바에서 기본적으로 제공하는 어노테이션도 있고, 스프링을 위해 제공되는 어노테이션도 존재합니다. 이러한 스프링에는 엄청나게 많은 종류의 어노테이션이 존재하는데 이 글에서는 그 모든 어노테이션을 다루지는 않습니다. 스프링의 어노테이션은 실제로 어노테이션에 따라 기능들이 추가적으로 사용될 수 있습니다.

 

 

1. @Bean: 직접 빈을 주입하고자 할 때 사용하는 어노테이션으로 추후 스프링을 배우다보면 빈에 대해서 학습하게 될 텐데, 그 빈을 직접 주입할 수 있게 해주는 어노테이션입니다. 주로 빈이 주입되어 있지 않은 외부 라이브러리(ArrayList 등)에 bean을 주입하고 싶을 때 사용할 수 있습니다. name value를 통해 빈의 이름을 지정해줄 수도 있습니다.

 

@Bean(name="")
beanArrayOf(list : ArrayList<T>) :  ArrayList<T> {
    return ArrayList<T>().addAll(list)
}

 

2. @Autowired: 속성이나 setter, 메소드 및 생성자에 사용이 가능하며 Type에 맞는 빈을 자동으로 주입해주는 기능을 합니다. 어디에 빈을 주입하고자 할 지에 대해서는 코드에 따라 오류가 나지 않도록 사용할 수 있습니다. 또한 주입되는 클래스는 기본적으로 bean에 등록되어 있어야 합니다. required의 경우 빈을 주입하는 것이 꼭 필요한 것인지에 대한 value입니다.

 

class service {
    private lateinit var data : BeanClass 
    
    @AutoWired(required = false)
    fun getData(beanClass : BeanClass) {
        this.data = beanClass
    }
}

@Repository
class BeanClass { //생략 }

 

@Repository
abstract class AbstractDAO {

    @Autowired
    protected lateinit var db: BeanClass
}

 

3. @RestController: view가 없는 서비스에 사용되는 controller로 데이터를 return 하는 것이 주 목적이 됩니다. @RequestMapping을 같이 사용합니다. @Controller를 이용하게 되면 데이터가 아니라 view를 return 할 수 있습니다.

 

4. @RequestMapping: URL을 컨트롤러의 메소드와 매칭하기 위해 사용되는 어노테이션입니다. 아래와 같은 형태로 사용될 수 있으며 이 어노테이션의 value 내부의 경로는 전부 이 어노테이션이 있는 클래스로 들어오게 됩니다.

 

@RequestMapping("/index")

 

5. @GetMapping: PostMapping, @PutMapping, @PatchMapping, @DeleteMapping와 같은 기능을 하지만 통신 메소드가 GET인 매핑 어노테이션입니다. 아래와 같이 /data1로 끝나는 url의 경우 어노테이션을 가진 메소드를 실행하게 됩니다.

 

@GetMapping("/data1")

 

 4와 5를 같이 사용하는 경우의 예 입니다. 경로/index/data1으로 들어오는 경우 getData1을 실행하게 됩니다.

 

@RequestMapping("/index")
@RestController
class IndexController {

    @Autowired
    private lateinit var indexService: IndexService

    @GetMapping("/data1")
    fun getData1(//생략) = {
        //생략
    }

}

 

 더 많은 어노테이션을 다루고 싶었으나 이 글의 목적은 어노테이션을 다루는 것이 아니라 어떤 어노테이션이 존재하고, 그러한 어노테이션들이 어떤 역할을 하는지에 대해 감을 익히는 부분에 시간을 할애했습니다. 아마도 추가적인 부분에 대해서는 또 공부가 필요할 것이라 생각합니다. 그렇게 추가적으로 스프링 개발에 들어갈 때 필요한 부분은 다시 채워넣을 생각입니다.

댓글