티스토리 뷰

오늘은 자바의 리플렉션 기능에 대해 정리해보려고 한다. 정리는 두차례로 진행이 될 예정이고, 오늘은 리플렉션에 대해서 간단히 알아보려고 한다.

리플렉션은 구체적인 클래스 타입을 알지 못해도 클래스의 메소드, 타입, 변수들에 대한 정보를 접근할 수 있게 해주는 API 이다. 리플렉션을 사용하면

객체를 동적으로 생성이 가능하다. 그렇다면 동적은 무엇이고? 정적은 무엇일까? 그렇다면 리플렉션이 가능한 이유를 알아보자. 

그리고 리플렉션이 가능한 이유를 알아보기 전에 간단히, 컴파일이 되는 과정을 간단히 알아보려고 한다. (참고 : https://lkhlkh23.tistory.com/2)




컴파일러에 의해 '.java' 소스 파일은 '.class' 바이트 코드로 변환이 되고, 클래스 로더에 의해 Runtime Data Area에 메모리를 할당해주고 있다.

간단히 보자면, 클래스 영역에는 클래스, 필드, 메소드, 상수 등의 정보가 저장되어 있다. (접근제한자, 리턴값, 데이터 타입, 변수명 등의 정보를 포함)

그리고 힙 영역에는 new 연산자를 통해 생성된 객체들을 저정할 뿐만 아니라, 힙 영역 내부 펌 영역에서는 GC 대상에서 제외되기 때문에 객체의 생명주기가 

영구적이라고 판단되는 객체들을 관리하고 있다. 


결국 클래스 영역에서는 클래스를 구성하는 각각의 인스턴스 멤버, 정적 멤버, 클래스, 상위 클래스에 대한 정보 등 클래스를 위한 모든 정보를 가지고 있다.

그렇기 때문에 런타임 시점에 클래스에 대한 정보를 활용해서 객체를 동적으로 생성할 수 있다. 동적이라는 의미는 런타임 시점을 의미하고, 정적이라는 의미는

컴파일 시점을 의미한다. 결국, 런타임 시점에 객체를 생성할 수 있다는 점이 리플렉션의 가장 큰 장점이지 않을까?

그리고 실제로 나는 리플렉션과 다형성을 활용해서 복잡한 IF-ELSE 문을 해결한 경험이 있다. (참고 : https://lkhlkh23.tistory.com/42)


리플렉션은 어디에서 활용할 수 있을까?


 1. Junit4에서 @Test 애노테이션이 설정되어 있는 메소드를 단위 테스트로 실행하고 싶은 경우 (다음 포스팅에서 구현 예정)


 2. 현재 실행하는 클래스의 클래스, 필드, 메소드 정보가 필요한 경우


 3. 데이터베이스에서 조회한 데이터의 칼럼 이름과 자바 클래스의 필드 이름이 같은 경우 자동으로 매핑하고 싶은 경우


편리한 리플렉션에도 대가는 따른다. 


 1. 리플렉션은 런타임 시점에서 객체를 생성하기 때문에 컴파일 시점에서 자료형을 검사할 수 있다는 자바의 기능을 활용할 수 없다.

    그렇기 때문에 런타임 시점에 접근할 수 없거나 존재하지 않는 메소드를 접근했을 때, 예외가 발생할 수 있다.


 2. 가독성이 떨어진다. 객체를 생성할 때, new() 연산자를 통해 간단하고도 명확하게 객체를 생성할 수 있다. 하지만 리플렉션을 사용하면 단순히 객체를
    생성할 때도 다소 복잡한 코드가 구현된다.


 3. OOME(Out of Memory Error) 발생 가능성이 있다. 앞서 컴파일 과정을 설명할 때, 간단하게 힙 영역 내부의 펌 영역에 대해 간단히 설명을 했다.

    펌 영역은 GC 대상에서 제외되기 때문에 정리되지 않고, 계속 누적이 된다는 것이다. 그리고 리플렉션을 사용하면 펌 영역에 적재되기 때문에

    리플렉션을 과다하게 사용할 경우, OOME(Out of Memory Error) 발생 가능성이 높아진다. 하지만 최근에는 하드웨어가 많이 발전되었기 때문에

    성능 저하가 다소 해결됬지만, 그래도 좋지만은 아닌것 같다.


 4. 접근제한자가 private인 멤버에도 접근할 수 있기 때문에 객체를 임의로 조작할 수 있어 문제가 될 수 있다.


참고로, 스프링 Handler Mapping 에서 리플렉션을 활용하고 있다. @GetMapping, @PostMapping 에 특정 URL 경로가 존재할 때 어떻게 해당 메소드를

정확하게 호출할 수 있을까? 그리고 클라이언트에게 전달받은 name, userId, email 파라미터가 어떻게 UserDto라는 객체로 변환될 수 있을까? 라는 의문을 

품은적이 있었다. 근데 지금 해결됬다! Handler Mapping은 Key, Value를 쌍으로 가지고 있는 Map을 가지고 있다. 이 Map에는 Method, Parameter, URL 등 

다양한 정보를 가지고 있고, 이 정보를 바탕으로 메소드를 정확히 호출하고, 리플렉션을 이용해서 각각의 파라미터를 객체들로 생성하고 있는 것이다.

리플렉션을 활용해서 기본 생성자로 객체를 생성한 다음, setter 메소드로 각각의 필드를 넣는 것이다. 

그렇기 때문에 스프링을 사용할 때 자바빈 규약을 반드시 지켜야 한다! 


리플렉션을 활용한 예제는 다음 포스팅으로! 사요나라!

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함