article thumbnail image
Published 2022. 8. 15. 00:09

 

 

Reflection

 

런타임에 메서드, 클래스 및 인터페이스의 동작을 검사하거나 수정하는 데 사용되는 API

구체적인 클래스 타입을 알지 못해도 클래스의 이름만으로 메소드, 필드에 접근할 수 있다.

 

 

API 라고 해서 사용 방법을 알아야할까? 라는 생각이 들어서 검색해보았는데

성능 및 디버깅 이슈로 개발자가 직접 Reflection 을 구현하는 경우는 드물다고 한다.

(참고) https://kmongcom.wordpress.com/2014/03/15/자바-리플렉션에-대한-오해와-진실/

 

 

 

Why?

 

그렇다면 왜 Reflection 에 대해서 알아야할까?

답은 스프링 프레임워크에서 이미 우리가 Reflection 을 사용하고 있기 때문이다.

 

 

Java 는 컴파일 시점에 타입을 결정하는 정적 타입 언어다.

개발자가 변수에 들어갈 값에 따라 자료형을 지정해야한다.

 

동적 타입 언어인 JavaScript 에서는 아래와 같이 코드를 작성해도 문제가 없다.

var foo = 123;
foo = "15243";

런타임 시에 동적으로 타입을 결정하기 때문이다.

 

 

자바는 컴파일 시점에 미리 타입을 결정하기 때문에 실행 속도가 빠르고

타입 에러에 대한 문제점을 실행 이전에 발견할 수 있어 안정성이 높지만,

 

자바로 만들어진 프레임워크(스프링)의 입장에서는 어플리케이션 실행 이전에는 얘가 어떤 타입의 클래스를 만들어놨을지 알 수 없다.

하지만 우리의 스프링은 런타임에 모든 컨트롤러(어노테이션이 붙은) 클래스들을 알아서 빈으로 등록해야만 한다.

 

이게 어떻게 가능한지 알아보자.

 

 

 

 

Reflection 동작 원리

 

우선 자바 컴파일에 대해서 가물가물하신 분들을 위해..

예전에 적어뒀던 노트를 첨부하도록 하겠다.

 

 

컴파일 시점에 자바 코드는 바이트 코드(.class)가 되어 JVM에 저장된다.

 

이 때 클래스 정보는 컴파일되어 Heap 영역, Metaspace (java 8+) 에 Type.class 형식으로 저장되기 때문에

런타임 시에 접근하여 클래스의 정보, 접근제어자 등을 알 수 있게 된다.

 

@Controller 어노테이션이 붙은 클래스를 알고싶다면, Reflection 을 사용해 Metaspace 에서 모든 클래스 정보를 불러오고

그 중 어노테이션에 @Controller 가 포함되어 있는 클래스를 가져오면 된다.

 

Reflection 을 사용해 알 수 있는 정보는 아래와 같다.

 

  • ClassName
  • Class Modifiers
  • Package Info
  • Superclass
  • Implemented Interfaces
  • Constructors
  • MethodsFields
  • Annotations

 

 

 

예제

 

간단한 사용 방법을 알아보도록 하자.

메서드는 없고 이름, 나이 필드를 가진 Person class 가 있다.

 

public class Person {
    private String name;
    private int age;
}

 

Object 타입으로 생성 된 Person 객체(구체적인 클래스 타입을 모르는 상태)의 필드에 아래와 같이 접근할 수 있다.

 

@Test
public void givenObject_whenGetsFieldNamesAtRuntime_thenCorrect() {
    Object person = new Person();
    Field[] fields = person.getClass().getDeclaredFields();

    List<String> actualFieldNames = getFieldNames(fields);

    assertTrue(Arrays.asList("name", "age")
      .containsAll(actualFieldNames));
}

 

 

 

결론

 

Reflection 이란, 컴파일 된 클래스 정보를 통해 동적으로 접근이 가능하도록 지원하는 API

Spring annotation, Spring DI 등에서 활용되고 있다.

Bean Factory 와 같이 엄청나게 재사용되는 곳에만 적용하도록 하자. 

 

 

 

 

 

참고

https://dev-nomad.com/89

https://dublin-java.tistory.com/53

복사했습니다!