[Java] 리플렉션

2024. 11. 7. 15:32·백엔드/Java

리플렉션

 

자바에서 리플렉션이란 런타임 시점에 동적으로 특정 클래스의 필드, 메서드, 생성자에 접근해 사용하는 자바 API이다.

 

 

가져오는 클래스의 정보는 모두 접근 제어자에 관계 없이 가져온다.

 

 

그리고 자바는 정적 언어이기 때문에 컴파일 시점에 객체 타입을 결정하지만, 자바 리플렉션 API를 사용한다면 런타임 시점에 타입을 동적으로 결정할 수 있다.

 

 

리플렉션 예제 코드

public class Member {

    // 필드의 접근 제어자가 모두 다름
    private String name;
    private int age;
    private String address;
    public String phone;

    // 기본 생성자는 필수
    public Member() {}

    // 메서드의 접근 제어자가 모두 다름
    private String getName() {
        return name;
    }

    private int getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }

    public String getPhone() {
        return phone;
    }
}

 

 

이러한 Member 클래스가 있고, 이 클래스의 정보를 리플렉션을 통해 가져오기 위해선 아래의 코드가 필요하다.

 

public class Main {
    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("Member");

        // 생성자
        Constructor declaredConstructor = clazz.getDeclaredConstructor();
        System.out.println("기본생성자 : " + declaredConstructor.getName());
        System.out.println();

        // 필드
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println("필드값 : " + field.getName());
        }
        System.out.println();

        // 메서드
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("메서드 : " + method.getName());
        }
    }
}

-------- 결과 --------

기본생성자 : Member

필드값 : name
필드값 : age
필드값 : address
필드값 : phone

메서드 : getName
메서드 : getAddress
메서드 : getAge
메서드 : getPhone

 

결과를 보다시피 메서드와 필드의 접근 제어자에 관계 없이 모든 정보를 가져온다.

 

 

 

기본생성자가 필수인 이유

 

기본 생성자가 필수인 이유는 다음과 같다.

리플렉션 API는 생성자에 필요한 파라미터 정보를 가져올 수 없기 때문이다.

 

 

많은 사람들이 위의 이유 때문에 기본 생성자를 강제한다고 알고있다.

 

 

물론 자바7 이전이라면 맞는 말이다.

 

 

하지만 자바8 이후부턴 리플렉션 API를 사용해 생성자의 파라미터를 가져올 수 있다.

 

 

그렇다면 왜 아직까지 기본 생성자를 필요로 하는 것일까?

 

 

 

1. 객체 생성과 초기화 분리

기본 생성자는 객체의 생성과 초기화를 분리하는데 유용하다. 객체를 먼저 생성한 후에 필드를 설정할 수 있기 때문에, 다양한 방식으로 필드 값을 설정할 수 있다. 더군다나 JPA의 경우에도 아무런 설정이 되지 않은 엔티티를 생성하고, 이후에 각 필드에 값을 매핑한다.

→ 물론 불변성을 해치는 행위이긴 하다..

 

 

2. “기본” 생성자

기본 생성자는 말 그대로 기본 생성자이다. Spring 같은 프레임워크에서 기본 생성자를 사용하지 않는다면 어떻게 될까? 결국 적절한 파라미터를 가진 생성자를 찾는 과정이 추가된다. 이는 설정과 코드 관리가 복잡해지고, 프레임워크 내부 동작에도 부담이 될 수 있다.

 

 

내 생각엔 이 두 가지가 가장 합당한 이유같다.

 

 

 

리플렉션 장점 및 예시

 

보통 컴파일 시점에는 어떤 클래스를 사용할지 모르지만 런타임 시점엔 클래스 정보를 가져와 실행할 때 사용된다.

 

 

리플렉션의 대표적인 예시가 Spring 빈 객체 생성 및 의존성 주입이다.

 

 

Spring에선 리플렉션을 사용해 객체간의 유연성과 확장성을 부여할 수 있다.

 

 

컴파일 시점이 아니라 런타임 시점에 클래스 정보를 획득하는 것이 유연성을 높일 수 있는 이유는 인터페이스에 의존하고, 구현체는 런타임에 결정함으로써 코드 수정 없이 다양한 구현체를 주입할 수 있게 해 준다.

 

 

이런 유연성 덕분에 Spring에서는 특정 환경에 따라 다양한 구현체를 사용하거나, 테스트 환경에서 Mock 객체를 주입하는 등의 작업을 손쉽게 수행할 수 있다.

 

 

또한 새로운 기능을 추가할 때 기존 클래스를 변경하지 않고 새로운 클래스를 만들어 주입하기만 하면 되므로 OCP(개방 폐쇄 원칙)를 준수할 수 있게 된다.

 

 

 

리플렉션 단점

 

1. 성능 문제

리플렉션은 런타임에 메타데이터를 동적으로 조회하는 방식으로 동작하기 때문에, 정적 바인딩보다 성능이 떨어질 수 있다. 대표적인 경우가 메서드 호출이다. 리플렉션을 사용해 메서드를 호출하는 경우, JVM의 정적 메서드 호출과 비교했을 때 성능이 상대적으로 낮다. 그 이유는 정적 메서드 호출은 컴파일 시점에 이미 어떤 메서드를 호출할 지 정해지기 때문이다.

 

 

2. 객체 불변성

위에서 언급한 것 처럼 리플렉션은 기본 생성자가 반드시 필요하다. 그럼 필드에 값 할당은 어쩔 수 없이 직접 필드에 매핑하거나, setter() 같은 메서드를 따로 사용해야 한다. 그럼 처음에 생성된 객체의 값이 변경되고, 객체 불변성을 해칠 수 밖에 없다.

 

 

3. 코드 가독성

리플렉션은 코드의 동적 특성을 많이 활용하므로, 코드가 복잡해지고 가독성이 떨어질 수 있다. 리플렉션을 사용한 코드가 많아지면 그 만큼 클래스의 이름을 String 형태로 작성되어 있는 것이 많다는 의미기도 하기 때문에 다른 개발자가 코드를 이해하고 수정하기 어려워진다.

 

 

 

하지만 이러한 단점에도 불구하고 많은 프레임워크에선 리플렉션 API를 사용한다. 그 만큼 어떤 경우에 잘 사용해야 할 지에 대한 판단이 중요하다. 리플렉션은 주로 프레임워크나 라이브러리에서 동적이고 유연한 객체 관리가 필요한 상황에서 유용하게 사용된다. 하지만 일반적인 애플리케이션 코드에서는 성능이나 코드 유지보수 측면을 고려해 리플렉션 사용을 최소화하는 것이 바람직하다.

'백엔드 > Java' 카테고리의 다른 글

[Java] SOLID (1) (Feat : 클린 아키텍처)  (0) 2025.02.05
[Java] 멀티스레딩 - 가상 스레드  (0) 2024.11.04
[Java] 멀티스레딩 - 스레드 간 통신  (2) 2024.11.04
[Java] 멀티스레딩 - 락 심화  (0) 2024.11.04
[Java] 멀티스레딩 - 스레드간 데이터 공유  (0) 2024.10.31
'백엔드/Java' 카테고리의 다른 글
  • [Java] SOLID (1) (Feat : 클린 아키텍처)
  • [Java] 멀티스레딩 - 가상 스레드
  • [Java] 멀티스레딩 - 스레드 간 통신
  • [Java] 멀티스레딩 - 락 심화
오도형석
오도형석
  • 오도형석
    형석이의 성장일기
    오도형석
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • MSA 모니터링 서비스
        • DB
      • 스파르타 코딩클럽
        • SQL
        • Spring
      • 백엔드
        • Internet
        • Java
        • DB
      • 캡스톤
        • Django
        • 자연어처리
      • Spring
        • JPA
        • MSA
      • ETC
        • ERROR
      • 개발 일기 N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 인기 글

  • 태그

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
오도형석
[Java] 리플렉션
상단으로

티스토리툴바