inblog logo
|
[HootJem] 개발 기록 블로그
    java

    리플렉션(Reflection)으로 동적 메서드 호출하기

    리플렉션(Reflection)은 프로그램 실행 중에 클래스의 메타데이터를 동적으로 분석하고 활용할 수 있게 해주는 강력한 도구이다.
    HootJem's avatar
    HootJem
    Aug 16, 2024
    리플렉션(Reflection)으로 동적 메서드 호출하기
    Contents
    리플렉션이란?1. 리플렉션 예제2. 리플렉션 활용결론
     

    리플렉션이란?

    • 리플렉션
      • → 속을 비추다 (코드의 내부를 들여다보는 것)
    보통 런타임에 리플렉션이 일어난다. (모든걸 탐색하게 함)
    코드 실행전 컴파일시 분석하게 하기 위해서는 어노테이션을 활용하게 할 수 있음.
    어노테이션을 활용하기 위해서는 행위를 정의해야한다. 다만, 사람이 나무를 수리한다고 했을 때 나무의 높이에 따라 수리한다 를 제외한 행위는 다르게 정의될 수 있다.
    사람에게 깃발이 있는 나무만 수리하라고 명령할 것. (깃발= 어노테이션)
    사람에게 깃발이 있는 나무만 수리하라고 명령할 것. (깃발= 어노테이션)
    💡
    어노테이션이란? JVM 이 보는 힌트. 주석같은 역할을 한다.

    1. 리플렉션 예제

    리플렉션을 사용하지 않는 코드
    notion image
     

    1.1 컨트롤러 생성

    먼저, UserController라는 클래스를 만들어 로그인과 회원가입 기능을 제공하는 메서드를 정의합니다.
    package ex01; public class UserController { public void login(){ System.out.println("login 호출됨"); } public void join(){ System.out.println("join 호출됨"); } }
     

    1.2 App 클래스 생성

    이제, App 클래스에서 사용자가 입력한 URL에 따라 해당 메서드를 호출하도록 코드를 작성해봅시다.
    package ex01; public class App { public static void main(String[] args) { String path = "/login"; UserController uc = new UserController(); if(path.equals("/login")) { uc.login(); }else if (path.equals("/join")) { uc.join(); } } }
     

    1.3 실행

    notion image
     
    String path = "/login"; 를 join 으로 바꾸면
    notion image
     
    🎈 이 코드는 단순히 path 변수를 통해 /login 또는 /join 경로에 맞춰 UserController의 메서드를 호출합니다. 그러나 이런 방식은 확장성이 떨어집니다. 새로운 메서드가 추가될 때마다 App 클래스도 수정해야 하기 때문입니다.

    2. 리플렉션 활용

    🎈 참고로 리플렉션은 순서 보장이 되지 않는다.
    아래 코드는 UserController 클래스의 메서드를 리플렉션을 사용해 탐색하고, 그 이름을 출력합니다.

    2.1 UserController 생성

    public class UserController { public void login(){ System.out.println("login 호출됨"); } public void join(){ System.out.println("join 호출됨"); } }

    2.2 App 클래스 생성

    import java.lang.reflect.Method; public class App { public static void main(String[] args) { UserController uc = new UserController(); Method[] methods = uc.getClass().getDeclaredMethods(); for (Method mt : methods) { System.out.println(mt.getName()); } } }
    Method[] methods = uc.getClass().getDeclaredMethods();
    를 통해 UserController 안에 있는 메서드의 이름을 조회할 수 있다. (실행도 가능하다!)
    • 실행하는 코드
    notion image
    mt.invoke(uc); 를 사용하기 위해서는 Exception 이 필요함.
    (매개변수로 넣은 uc 안에 메서드가 존재하지 않을 수 있기 때문에)
     

    2.3 어노테이션 정의

    어노테이션을 사용하면 메서드 이름 대신 어노테이션 값을 기준으로 동적으로 메서드를 호출할 수 있다.
    먼저 RequestMapping 이라는 어노테이션을 정의해 본다.
    import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) //메서드 위에만 붙일 수 있다 @Retention(RetentionPolicy.RUNTIME) // 해당 깃발은 런타임시 실행됨. public @interface RequestMapping { String uri(); // String 타입의 uri 를 넣을 수 있음. }
    notion image
    소스 : 컴파일시 , 런타임 : 런타임시
    notion image
    이 엘레멘트가 붙을 수 있는 위치를 의미한다.
     

    2.4 어노테이션 적용 및 최종 코드

    public class UserController { @RequestMapping(uri = "/login") public void login(){ System.out.println("login 호출됨"); } @RequestMapping(uri = "/join") public void join(){ System.out.println("join 호출됨"); } }
    import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class App { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { String path = "/login"; UserController uc = new UserController(); Method[] methods = uc.getClass().getDeclaredMethods(); for (Method mt : methods) { Annotation anno = mt.getDeclaredAnnotation(RequestMapping.class); RequestMapping rm = (RequestMapping) anno; // 이렇게 통합할 수 있음 // RequestMapping rm = mt.getAnnotation(RequestMapping.class); if (rm == null) break; if(rm.uri().equals(path)){ mt.invoke(uc); } } } }
    위 코드에서는 어노테이션을 사용해 각 메서드가 어떤 URL 경로와 매핑되는지를 정의한 후, 런타임에 이 매핑 정보를 바탕으로 메서드를 호출한다. path 변수만 바꾸면 어떤 메서드든 호출할 수 있게 되며, 새로운 메서드가 추가되더라도 App 클래스는 수정할 필요가 없다.

    결론

    이번 포스팅에서는 스프링 프로젝트에서 자주 사용되는 어노테이션이 어떻게 동작하는지 살펴보며, 리플렉션에 대해 알아보았다. 리플렉션을 통해 어노테이션의 실제 사용 방식과 그 동작 원리를 더 깊이 이해할 수 있었으며, 이를 바탕으로 기존에 활용하던 코드를 분석하고 개선할 수 있는 방법도 배울 수 있었다. 앞으로 어노테이션을 더 효과적으로 활용하기 위해 이번에 배운 내용을 프로젝트에 적용해 보면 좋을것이다.
    Share article
    Contents
    리플렉션이란?1. 리플렉션 예제2. 리플렉션 활용결론

    [HootJem] 개발 기록 블로그

    RSS·Powered by Inblog