“자바 코드에 붙이는 주석 같은 메타데이터”
— 컴파일러나 런타임 환경에게 ‘이 코드 이렇게 처리해줘’라고 알려주는 정보 표시용 태그.
@Override
public String toString() {
return "Hello";
}
@Override 는 “이 메서드는 부모 클래스의 메서드를 재정의한 거야!” 라고 컴파일러에게 알림“어노테이션도 여러 종류가 있다”는 말이 바로
👉 역할(용도) 에 따라 분류된다는 뜻이다.

| 구분 | 설명 |
|---|---|
| 1️⃣ 메타 어노테이션 (Meta-Annotation) | 어노테이션을 설명하는 어노테이션 |
| 2️⃣ 일반 목적 어노테이션 (General-Purpose Annotation) | 자주 쓰는 기본 제공 어노테이션 |
| 3️⃣ 마커 어노테이션 (Marker Annotation) | 값 없이 “존재 자체로 의미”를 가지는 어노테이션 |
| 4️⃣ 사용자 정의 어노테이션 (Custom Annotation) | 개발자가 직접 만드는 어노테이션 |
| 구분 | 의미 | 예시 |
|---|---|---|
| 🧩 메타 어노테이션 | 어노테이션을 정의할 때 쓰는 어노테이션 | @Target, @Retention |
| 🧱 일반 목적 어노테이션 | 자바가 기본 제공하는 범용 어노테이션 | @Override, @Deprecated |
| 🏷 마커 어노테이션 | 속성 없이 존재만으로 의미를 가짐 | @Test, @FunctionalInterface |
| ✏️ 사용자 정의 어노테이션 | 개발자가 직접 만든 어노테이션 | @MyAnnotation, @Info |
| 구분 | 설명 | 예시 |
|---|---|---|
| ✅ 컴파일러에게 정보 제공 | 코드가 잘못된 부분을 알려주거나 무시하도록 지시함 | @Override, @Deprecated, @SuppressWarnings |
| 🧩 컴파일 시 자동 코드 생성 | Lombok이나 Dagger 같은 라이브러리들이 컴파일 시 코드를 자동으로 생성 | @Getter, @Setter, @Builder |
| ⚙️ 런타임 시 동작 제어 | 프레임워크(Spring, JUnit 등)에서 실행 중에 특정 행동을 하도록 지정 | @Autowired, @Test, @Controller |
| 🧾 문서화 지원 | Javadoc에서 문서 자동 생성 시 사용 | @param, @return |
| 🔍 리플렉션(Reflection) 활용 | 실행 중에 클래스/메서드/필드 정보를 읽어서 특정 처리 | 커스텀 어노테이션(@MyAnnotation) 등 |
public class Example {
@Deprecated // ⚠️ 이 메서드는 앞으로 사용하지 말라는 뜻!
public void oldMethod() {
System.out.println("옛날 방식");
}
@Override // ✅ 부모 메서드를 재정의했다는 표시
public String toString() {
return "새로운 방식";
}
}
@Deprecated → IDE에서 “이거 곧 없어질 예정이야” 경고 표시@Override → 부모 클래스의 메서드를 재정의했는지 검사👉 소스 코드에 주석(설명)을 달아서 자동으로 문서(HTML 파일 등)를 만드는 기능
/** ... */ 형태로 설명을 써두면,javadoc 명령어로 API 문서처럼 보기 좋은 문서를 자동으로 생성할 수 있다! 📚Java 프로그래밍 언어의 공식 문서화 도구
| 태그 | 설명 | 사용 위치 |
|---|---|---|
@author | 작성자 이름 | 클래스 |
@version | 버전 정보 | 클래스 |
@param | 메서드 매개변수 설명 | 메서드 |
@return | 메서드 반환값 설명 | 메서드 |
@throws | 발생 가능한 예외 설명 | 메서드 |
@see | 관련 참조 정보 | 클래스/메서드 |
@deprecated | 더 이상 사용하지 않음 | 클래스/메서드 |
jeini@JEINIui-MacBookAir HelloWorld % javadoc -d ./docs -sourcepath src project
👉 “프로그램이 자기 자신(또는 다른 코드)을 다루는 프로그래밍 기법”
— 즉, 코드를 ‘데이터’처럼 다루는 코드 를 짜는 것.
보통 이런 코드는 일반 코드 👇
int a = 10;
int b = 20;
System.out.println(a + b);
근데 메타 프로그래밍은 이런 느낌 👇
// Java 리플렉션(Reflection) 예시
Class<?> clazz = Class.forName("java.lang.String");
System.out.println("클래스 이름: " + clazz.getName());
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
System.out.println("메서드 이름: " + m.getName());
}
👉 여기서 프로그램이 “String 클래스 내부 구조”를 직접 읽고,
그 안에 있는 메서드 이름들을 알아내고 출력하고 있다.
이게 바로 코드를 다루는 코드, 즉 메타 프로그래밍이다. ✨
| 도구 | 설명 |
|---|---|
| 리플렉션 (Reflection) | 클래스, 필드, 메서드 정보를 런타임에 읽고 수정 |
| 어노테이션 (Annotation) | 코드에 메타데이터를 붙이고, 이를 해석해서 동작 변경 |
| 프록시 (Proxy) | 런타임에 클래스나 인터페이스를 감싸서 동작을 바꿀 수 있음 |
| 리플렉션 + 어노테이션 조합 | 프레임워크(Spring 등)가 내부 동작을 자동화할 때 주로 사용 |

public @interface 어노테이션이름 {
타입 요소이름() default 기본값;
}
@interface 로 선언default 값은 선택사항 (기본값이 필요 없으면 생략 가능)어디에 붙일 수 있는지도 정할 수 있다!
👉 클래스, 메서드, 필드, 파라미터 등등.
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Info {
String author();
String date() default "N/A";
}
🧩 여기서
ElementType.TYPE → 클래스, 인터페이스, enum에 적용 가능ElementType.METHOD → 메서드에 적용 가능
어노테이션이 언제까지 유지될지를 정한다.
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Info {
String author();
String date() default "N/A";
}
| 종류 | 설명 |
|---|---|
SOURCE | 컴파일할 때만 존재 (컴파일 후 사라짐) |
CLASS | 클래스 파일에는 남지만, 런타임에는 사라짐 |
| RUNTIME | 실행 중에도 유지돼서 리플렉션으로 읽을 수 있음 ✅ |
👉 보통 RUNTIME 을 제일 많이 쓴다! (Spring, Hibernate 등 다 이것)