Java에서 Annotation (@) 은 기본적으로 "메타데이터(metadata)" 라고 할 수 있다.
혹여나 메타데이터가 뭔지 모르는 코붕이(코드 뉴비라는 뜻 ㅋㅋ) 를 위해 설명을 한다면,
"데이터에 대한 데이터" 라고 보면 된다.
즉, 원래 데이터 자체가 아니라 그 데이터를 설명하는 정보인 샘
사람의 이름으로 한다면, "김덕배" 의 생일은 메타데이터라고 할 수 있다. 그러니까, 책이라고 한다면 책의 ISBN을 메타데이터라고 할 수 있고. 데이터를 설명하는 데이터라고 생각하면 이해하기 쉬운데. 더 헷갈리는 사람들을 위해 네이버 사전을 인용한다면

말 그대로 "코드에 붙이는 주석/메모" 같은 개념인데,
단순히 주석처럼 무시되는 건 아니고 컴파일러나 런타임 환경이 해석할 수 있는 데이터이다.
그러면 훌륭한 우리 뉴비 친구들은 ?
앵? 그러면 아무거나 적어서 @달면 되는거 아니냐? 주석이랑은 무슨 차이지?
이라고 답을 할 수가 있는데, "주석"의 목적은 "읽는 '사람'"을 위한 것이라면 @이라는 Annotation 는 당신이 코드를 쓰고 있는 컴파일러가 이해할 수 있도록 머리에 달아주는 것을 말한다. 이것도 만약에 헷갈리면, 컴파일러의 개념이 부족한 것인데, 관련 컴파일러에 대한 이야기는 정말 길어지니 포스팅은 또 다음에 따로 하겠다
🔹 Annotation의 기본 특징
- 아무 프레임워크도 없이 쓰면:
- @Override, @Deprecated, @SuppressWarnings 같은 표준 애노테이션은 컴파일러가 직접 해석한다.
- @Override → 메서드 오버라이드가 제대로 되었는지 컴파일러 체크
- @Deprecated → 사용 시 경고 표시
- @SuppressWarnings → 컴파일 경고 억제
- @Override, @Deprecated, @SuppressWarnings 같은 표준 애노테이션은 컴파일러가 직접 해석한다.
- 런타임까지 가져가려면:
- 애노테이션 정의 시 @Retention(RetentionPolicy.RUNTIME) 을 붙이면 Reflection으로 읽을 수 있다.
- 이 경우, 프레임워크 없이도 Class.getAnnotations() 같은 방식으로 직접 해석 가능은 하다.
public class Test {
@내맘대로적음 // ❌ 사람 : ㅇㅇ 이 사람은 내 맘대로 적었구나 컴파일러 : ??? 님 이게 머에요?
public void doSomething() {
System.out.println("Hello");
}
}
이렇게 하면 컴파일러가 : ㅇ? 이게 진짜 모에요? 라고 오류를 뱉어낼 것이다
error: cannot find symbol
@내맘대로적음
^
symbol: class 내맘대로적음
이것은 코드가 "내가 님 코드 읽어보고 실행할려고 했는데 이게 먼지 몰라서 일단 실행안할게요" 라고 답하는 것이다
🔹 이제 프레임워크가 있으면
Spring, Hibernate 같은 프레임워크는 이 애노테이션을 런타임에 해석해서 동작을 바꿈
예:
- @Autowired → 객체 주입
- @Entity → JPA 엔티티로 인식
- @Controller → 웹 컨트롤러로 등록
즉, 프레임워크가 Annotation을 읽고 “행동을 연결”해주기 때문에
애노테이션이 단순한 메모를 넘어서 실행 흐름까지 제어하게 된다
그럼에도 불구하고 내가 사용하고 정의 하는대로 쓰게 하고 싶다면??
- 애노테이션은 클래스처럼 “정의” 되어 있어야 한다
- @Override 같은 애들은 사실 자바 표준 라이브러리에 @interface Override { ... } 로 정의된 애노테이션이거든요.
- 정의되지 않은 이름의 애노테이션을 쓰면 “심볼을 찾을 수 없다” 라는 컴파일 에러가 발생
내가 그럼 직접 정의를 해보자
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface 내맘대로적음 {
String value() default "no message";
}
public class MyService {
@내맘대로적음("이 메서드는 중요한 작업을 한다")
public void doWork() {
System.out.println("열심히 일하는 중...");
}
@내맘대로적음
public void doNothing() {
System.out.println("아무것도 안 하는 중...");
}
}
그럼 이제 void main 에서 갖고 놀기 시작을 해보면
import java.lang.reflect.Method;
public class AnnotationTest {
public static void main(String[] args) throws Exception {
MyService service = new MyService();
// MyService 클래스의 메서드들 확인
for (Method method : MyService.class.getDeclaredMethods()) {
if (method.isAnnotationPresent(내맘대로적음.class)) {
// 애노테이션 가져오기
내맘대로적음 ann = method.getAnnotation(내맘대로적음.class);
// 로그 출력
System.out.println("[LOG] " + method.getName() + " → " + ann.value());
// 실제 메서드 실행
method.invoke(service);
}
}
}
}
이렇게 코드블록들이 작동하는 것들을 확인 할 수 있다.
이제 내맘대로 @를 규정할수 있다는 매우 쓸모없는 정보를 알았다
실무에서 활용을 언제 할 수 있는가?
몰?루?

진짜 왜 씀?
멋지자너...
✅ 정리:
- 정의되지 않은 애노테이션을 쓰면 컴파일 오류
- 하지만 내가 @interface 로 정의해두면, 이름이 뭐든 정상적으로 사용 가능
'컴퓨터 공학 > Java' 카테고리의 다른 글
| [Java] 으흐흐..... HashMap 쓸거야 ! HashSet 쓸거야? (0) | 2026.02.04 |
|---|---|
| [Java] 그래서 Iterator 는 왜 쓰는거임? 걍 for 쓰지;? (0) | 2026.02.04 |
| [Java] 왜 가운데에 boolean 을 자꾸 추가해요 (0) | 2026.02.02 |
| Java 로 만든 첫번째 Software Development (5) | 2025.05.22 |
| 자바 개념 // 나만의 노트 (1) | 2024.03.06 |