Spring) Reflection 개념 및 사용 방법

오성민·2023년 2월 26일
0

spring

목록 보기
16/17
post-thumbnail

목차

  • 개념
  • 사용 방법
  • 장단점
  • 사용했던 이유

Reflection 개념

Reflection이란? 힙 영역에 로드된 Class 타입의 객체를 통해, 원하는 클래스의 인스턴스를 생성할 수 있도록 지원하고, 인스턴스의 필드와 메소드를 접근 제어자와 상관 없이 사용할 수 있도록 지원하는 API이다.

Reflection 사용 방법

Spring에서 사용할 때를 기준으로 사용법 먼저 바로 적겠다.

for(Field field : user.getClass().getDeclaredFields()){
            field.setAccessible(true);
            System.out.println(field.getName() + " = " + field.get(user));
        }

위와 같이 사용을 하면 된다.
그렇다면 결과로

위와 같은 결과를 얻을 수 있다.

현재 사용법으로 적어놓은 코드에서 User class에 모든 필드는 private으로 설정돼있다.
원래 같으면 해당 class에 필드 값에 접근하려고 할 때에는 public한 메소드인 getter를 사용해서 접근을 해야한다.
getter를 사용하지 않는다면, private 접근제어자 때문에 필드에 직접 접근이 불가능하다.

User class에서 사용한다면 user.getClass().getDeclaredFields() 해당 메소드를 통해서 User class에서 사용하는 모든 필드 정보를 얻을 수 있다.
이렇게 나온 Field array이를 for문을 통해서 모든 필드에 접근을 하였고, field.getName() 메소드를 통해서 필드의 이름을
field.get(user)를 통해서 변수로 넘어온 인스턴스에 해당 필드에 값을 출력할 수 있다.

하지만 User class가 아닌 다른 곳에서 사용을 한다 field.setAccessible() 메소드를 통해서 해당 필드에 접근할 것인지를 선택해주면 된다.
기본값은 false이니 외부에서 접근을 할 것이면 true로 설정을 해주면 된다.

생각해보면 왜 setAccessible()를 통해서 접근을 막는지를 알아야 된다.

장단점

장점

  • 접근제어자와 관계 없이 필드와 메소드에 접근할 수 있어서 유연성이 매우 뛰어나다.

단점

  • 캡슐화를 저해한다. 이게 가장 큰 단점이라고 생각되며, setAccessible() 메소드를 통해서 허용을 해야지 private 접근제어자로 막은 필드나 메소드에 접근할 수 있는 이유이다. 객체지향적인 특성이 깨지니 정말 필요할 때에만 사용을 해야한다.
  • 런타임 시점에서 인스턴스를 생성하므로 컴파일 시점에는 타입을 체크할 수 없다.
  • 런타임 시점에 인스턴스를 생성하므로 동작 흐름을 파악하는데 어려움이 있어서 가독성이 떨어진다.
  • 모두 다 그런 것은 아니지만 리플렉션을 사용할 때에 성능이 떨어진다.

사용했던 이유

리플렉션을 활용하는 방법이나 이유는 여러 가지가 있을 것이다. 당장 인터넷을 찾아봐도 spring에서 어노테이션 기반으로 동작하는데 크게 기여한 기술이라고 한다.
우리가 @Component를 사용하지 않고 가독성을 올리기 위해서 @Controller, @Service 등등..을 사용해도 spring이 알아서 클래스를 생성하고 관리해주는 기술에서 사용된다고 한다.

하지만 내가 사용했었던 이유는 가장 크게 2가지였다.

  1. null 체크

넘어온 데이터가 null인지 판단할 때에 깔끔하게 코드를 짤 수 있는 방법을 찾다가 reflection이라는 것을 알게 되었다.
원래는 모든 필드를 if문을 써서 체크를 하려고 했지만 그렇게 된다면 필드가 변경되었을 때는 매우 끔찍할 것이다.

public boolean hasNull() throws IllegalAccessException {
        for(Field field : this.getClass().getDeclaredFields()){
            if(field.get(this) == null){
                return true;
            }
        }
        return false;
    }

null체크는 위와 같이 했었다.

  1. 수정 로직

예를 들어서 게시물을 수정할 때에나 데이터를 변수로 넘어온 값을 통해 수정을 하는 로직에서 사용을 할 때에 사용하려고 하였다.
만약 게시물을 수정할 때에 기존에는
제목, 내용
만 수정할 수 있었는데 요구사항으로
제목, 내용, 카테고리
를 수정할 수 있다고 할 때에 수정하는 로직을 메소드로 만들어도 다시 찾아서 일일이 수정을 해야한다.
그렇게 되면 실수를 할 가능성도 있고, 너무 귀찮다. 물론 성능을 생각해야겠지만 이러한 방법도 있다는 것을 반드시 기억하고 사용해야 할 때에는 시기적절하게 사용을 해봐야겠다.

profile
풀스택을 지향하는 개발자

0개의 댓글