inblog logo
|
stupefyee
    기술정리

    [기술정리] 리플렉션과 어노테이션

    Stupefyee's avatar
    Stupefyee
    Nov 14, 2024
    [기술정리] 리플렉션과 어노테이션
    Contents
    1. 리플렉션 (Reflection)2. 어노테이션 (Annotation)3. 리플렉션과 어노테이션의 결합4. 코드예시

    1. 리플렉션 (Reflection)

    1. 개념

    • 동적 클래스 정보: 실행 중에 클래스, 메서드, 필드 등의 정보를 동적으로 조회.
    • 런타임 메타데이터: 클래스, 인터페이스, 메서드, 생성자 등의 정보를 런타임에 얻을 수 있음.
    • 코드 유연성: 코드의 유연성을 높여 다양한 동적 작업 가능.

    2. 주요 특징

    • 클래스 객체 조회: 클래스명으로 객체를 생성하거나 메서드를 호출.
    • 필드와 메서드 접근: 비공개(private) 멤버에도 접근 가능.
    • 컴파일 시 알 수 없는 정보 처리: 런타임에만 알 수 있는 정보 처리 가능.

    3. 사용 예시

    • 프레임워크: 스프링, 하이버네이트 등에서 빈(bean) 생성, 의존성 주입에 사용.
    • 테스트 도구: 테스트 자동화 도구에서 테스트 메서드나 필드에 대한 정보를 동적으로 처리.
    • 동적 프록시: 런타임에 동적으로 프록시 객체를 생성.

    4. 장점

    • 동적 처리: 실행 중에 객체를 다룰 수 있음.
    • 유연성: 코드 변경 없이 런타임에 동적으로 동작을 변경.

    5. 단점

    • 성능 저하: 리플렉션을 사용하면 성능이 저하될 수 있음.
    • 타입 안전성 부족: 컴파일 타임에 오류를 잡기 어려움.
     

    2. 어노테이션 (Annotation)

    1. 개념

    • 메타데이터: 코드에 추가적인 정보를 제공하는 메타데이터.
    • 클래스, 메서드, 필드에 부착: 코드에 정보를 제공하거나 처리 방식 지정.
    • 런타임, 컴파일 타임 처리: 주석처럼 코드를 설명하거나, 컴파일 타임 또는 런타임에서 처리됨.

    2. 주요 특징

    • 어노테이션 프로세서: 어노테이션을 분석하고 처리하는 도구.
    • 타입 안전성: 컴파일 시 검증을 통해 안정성을 높임.
    • 직관적: 코드의 의도를 명확하게 표현.

    3. 사용 예시

    • Spring Framework: @Autowired, @Service, @Controller 등.
    • JUnit: @Test, @Before, @After 등.
    • 직접 정의: 사용자가 원하는 방식으로 어노테이션을 정의하여 사용.

    4. 장점

    • 코드 가독성 향상: 코드의 의도를 명확하게 표현.
    • 플러그인 처리: 외부 라이브러리나 프레임워크에서 동적으로 어노테이션을 처리.
    • 유연성: 코드에 변화를 주지 않고 동작을 제어.

    5. 단점

    • 어노테이션 의존성: 코드가 어노테이션에 의존적일 수 있음.
    • 런타임 처리 오버헤드: 런타임에 어노테이션을 처리해야 하므로 성능에 영향을 줄 수 있음.

    3. 리플렉션과 어노테이션의 결합

    1. 개념

    • 어노테이션: 코드에 메타데이터를 추가, 클래스, 메서드, 필드에 정보를 제공.
    • 리플렉션: 런타임에 클래스, 메서드, 필드 등 정보를 동적으로 조회하고 처리.

    2. 함께 동작하는 방식

    1. 어노테이션으로 메타데이터 제공
        • 코드에서 어노테이션을 사용해 클래스, 메서드, 필드에 특별한 의미를 부여.
        • 예: @Service, @Autowired 등.
    1. 리플렉션으로 어노테이션 처리
        • 런타임에 리플렉션을 통해 어노테이션을 읽고, 이에 따라 동작 처리.
        • 예: @Autowired 필드에 의존성 자동 주입, @Service 클래스를 자동으로 등록.

    3. 사용 예시

    • 스프링 프레임워크:
      • @Autowired: 의존성 주입을 위한 어노테이션.
      • @Service: 서비스 클래스에 대한 메타데이터 제공.
      • 리플렉션: 어노테이션이 붙은 클래스나 메서드를 런타임에 찾아 처리.

    4. 코드예시

    1. 어노테이션이 없을 때

    /** * 1차 개발자가 작성하는 코드 */ public class Router { UserController uc; public Router(UserController uc) { this.uc = uc; } public void routing(String path) { if (path.equals("/login")) { uc.login(); } else if (path.equals("/join")) { uc.join(); } } }
    1차 개발자가 배포하는 Router.java
    /** * 2차 개발자가 작성하는 코드 */ public class UserController { public void login() { System.out.println("로그인"); } public void join() { System.out.println("회원가입"); } public void logout() { System.out.println("로그아웃"); } }
    Router.java를 사용해 2차 개발자가 만든 UserController.java
    💡
    기능을 확장하려면 1차 개발자에게 라이브러리 수정 요청을 해야하는 한계가 존재
    public class App { public static void main(String[] args) { Router router = new Router(new UserController()); Scanner scan = new Scanner(System.in); String path = scan.nextLine(); router.routing(path); } }
    실행을 위한 App.java
    💡
    “/logout”을 콘솔창에 입력하면 아무것도 출력 X

    2. 어노테이션이 있을때

    @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RequestMapping { String value(); // value만 존재할 경우 어노테이션 파라미터 작성시 생략가능 }
    1차 개발자가 생성한 어노테이션 RequestMapping .java
    public class Router { UserController uc; public Router(UserController uc) { this.uc = uc; } public void routing(String path) { // 어노테이션 구현 순서 // 1. 메소드 찾아내기 Method[] methods = uc.getClass().getMethods(); // uc의 클래스의 모든 메소드를 가져옴 // 2. 어노테이션 체크 for (Method m : methods) { RequestMapping rm = m.getAnnotation(RequestMapping.class); // 3. value와 path 일치 확인해서 일치하면 invoke 하기 if (rm == null) { break; } if (rm.value().equals(path)) { try { m.invoke(uc); } catch (Exception e) { throw new RuntimeException("메소드 실행 중 오류 발생"); } } } } }
    만들어진 어노테이션을 구현하는 Router.java
    public class UserController { @RequestMapping("/login") public void login() { System.out.println("로그인"); } @RequestMapping("/join") public void join() { System.out.println("회원가입"); } @RequestMapping("/logout") public void logout() { System.out.println("로그아웃"); } @RequestMapping("/userinfo") public void userinfo() { System.out.println("유저인포"); } }
    1차 개발자가 제작한 어노테이션을 사용해 2차 개발자가 제작한 UserController
    💡
    @RequestMapping(value) 만 잘 붙인다면 제한 없이 메소드 구현 가능
    App.java 동일.
    Share article
    Contents
    1. 리플렉션 (Reflection)2. 어노테이션 (Annotation)3. 리플렉션과 어노테이션의 결합4. 코드예시

    stupefyee

    RSS·Powered by Inblog