본문 바로가기
Spring

[Spring] POJO, Java Bean, Spring Bean

by ghan2 2024. 6. 1.

헷갈리는 개념인 POJO, Java Bean, Spring Bean에 대해 알아보았다!

 

POJO: Plain Old Java Object

오래된 방식의 간단한 자바 오브젝트라는 말로서 Java EE 등의 중량 프레임워크들을 사용하게 되면서 해당 프레임워크에 종속된 "무거운" 객체를 만들게 된 것에 반발해서 사용되게 된 용어이다

: 회원에게 제한을 두지 않고 사용자에게 엔터티에 대한 완전한 액세스 권한을 부여하고 싶지 않을 때 사용한다.

- 인수가 없는 생성자가 있을 수도 있고 없을 수도 있다. 

- 어떠한 자바 객체도 POJO에 속한다!

 

Java Bean

: 사용자에게 엔터티를 제공하고 엔터티의 일부만 제공하려는 경우에 사용된다.

1. 기본 생성자를 가진다.

2. 필드는 getter와 setter만 액세스할 수 있다.

3. 직렬화 가능한 인터페이스를 구현해야 한다. 

 

==> 이 둘은 모두 가독성과 재사용성을 높이기 위해 Java 객체를 정의하는데 사용한다. POJO에는 다른 제한 사항이 없지만 Bean은 몇 가지 제한 사항이 있는 특수 POJO라고 할 수 있다.

 

Spring Bean

프레임워크에 의해 관리되는 모든 자바 객체를 말한다.

- 스프링 컨테이너(IoC)에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트이다. 

💡스프링 컨테이너란?
스프링 컨테이너는 자바 객체의 생명 주기(빈의 생성, 관리, 제거 등)를 관리하며, 생성된 자바 객체들에게 추가적인 기능을 제공한다.
스프링 컨테이너는 Beanfactory와 ApplicationContext 두 종류의 인터페이스로 구현되어 있다. 빈 팩토리는 빈의 생성과 관계설정 같은 제어를 담당하는 IoC 오브젝트이고, 빈 팩토리를 좀 더 확장한 것이 애플리케이션 컨텍스트이다.

스프링 컨테이너는 XML, 어노테이션 기반의 자바 설정 클래스로 만들 수 있다. 스프링 부트(Spring Boot)를 사용하기 이전에는 xml을 통해 직접적으로 설정해 주어야 했지만, 스프링 부트가 등장하면서 대부분 사용하지 않게 되었다.

 

스프링 빈을 사용하면 어떤 이점이 있을까?

먼저 스프링 빈은 의존성 주입 방식을 이용한다. "스프링 컨테이너에서 객체 Bean을 먼저 생성해두고 생성한 객체를 지정한 객체에 주입하는 방식을 의존성 주입 이라고 한다" 객체 자체가 코드 상에서 객체 생성에 관여하지 않아도 되기때문에 객체 사이의 의존도를 낮출수 있다. 스프링 컨테이너에서 객체의 생명주기를 관리하며 객체의 의존관계 또한 관리해준다. 의존성 주입을 사용하면 유연하고 확장성이 뛰어난 코드 작성이 가능해진다! 

또한 스프링 빈은 싱글톤으로 관리된다. 덕분에 싱글톤을 직접 구현하지 않아도 되며, DIP/OCP 원칙에도 위반하지 않고 있다.

이 외에도 빈 생명주기 관리 등의 이점이 있다. 종료 시점에 안전하게 모두 종료해야 하는 객체들을 관리해 준다. 

 

의존성 주입에는 어떤 방식이 있나?

  • 필드 주입(Field Injection)
  • 수정자 주입(Setter Based Injection)
  • 생성자 주입(Constructor Based Injection)

필드 주입: 클래스에 선언된 필드에 생성된 객체를 주입한다. 스프링에서 제공하는 @Autowired 어노테이션을 필드 위에 명시한다.

(이 때 MiniService는 빈으로 등록되어 있어야 한다.)

@Controller
public class MiniController{
	@Autowired
    private MiniService miniService;
}

 

수정자 주입: 클래스의 Setter를 통해 의존성을 주입한다. 

@Controller
public class MiniController{

    private MiniService miniService;

	@Autowired
    public void setMiniService(MiniService miniService){
    	this.miniService = miniService;
    }
}

 

생성자 주입: 생성자를 통해서 의존성을 주입한다.

@Controller
public class MiniController{

    private final MiniService miniService;

	@Autowired
    public MiniController(MiniService miniService){
    	this.miniService = miniService;
    }
}

이는 Lombok을 사용하여 이렇게도 가능하다.

@Controller
@RequiredArgsConstructor
public class MiniController {
	private final MiniService miniService;
}

 

어떤 주입방식이 좋을까?

스프링에서는 생성자 주입 방식을 권장한다!

1) 객체의 불변성: 생성자 주입 방식을 사용할 경우 객체가 생성되는 시점에 생성자를 호출하여 최초 1회만 주입한다. 이와 같은 특성으로 불변(immutable)객체를 보장한다. 또한 객체를 포함한 클래스가 생성되는 시점에 포함된 객체들도 반드시 생성되기 때문에 객체가 비어있을 가능성도 배제한다. 

2) 순환 참조 문제 방지 가능: 순환 참조란 A, B 두 객체가 각각 서로를 필드에서 참조하고 있는 상태를 말한다. 이는 서로 참조를 위해 계속 객체를 생성하는 상태에 빠지는 문제가 발생한다. 3가지 방식 모두 순환 참조 문제가 발생하지만 필드주입, 수정자 주입은 실제 메소드가 호출되었을 때 런타임 에러가 발생하는 반면에 생성자 주입은 어플리케이션이 구동되는 순간에 에러가 발생한다. 즉 컴파일 타임에 에러가 발생하여 미리 예측할 수 있게 한다. 

3) 테스트 용이: 단위 테스트를 진행할 때 순수 자바 코드로 테스트가 가능하다. 필드 주입을 사용하는 경우에 순수 자바 코드에서는 DI가 이루어지지 않기 때문에 필드가 null 상태가 되어 에러가 발생한다. 


참고

https://ittrue.tistory.com/220

https://www.youtube.com/watch?v=lQ3svlKjs70

https://velog.io/@think2wice/Spring-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85DI%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC