Programming/Spring

[Spring] POJO(Plain Old Java Object)

Smile :DK 2023. 6. 4. 04:27

Spring Triangle

POJO는 Spring에서 사용하는 핵심 개념들(IoC/DI, AOP, PSA)을 통해 달성할 수 있음을 의미한다.

Spring은 POJO프로그래밍을 지향하는 Framework로 최대한 다른 환경이나 기술에 종속적이지 않도록 하기 위한 POJO 프로그래밍 코드를 작성하기 위해 Spring에서는 세 가지 기술을 지원하는데 그 세 가지 기술이 IoC/DI, AOP, PSA이다.

 

POJO 배경

Spring Framework를 사용하기 전에는 원하는 특정 기술이 있다면 해당 기술을 직접적으로 사용하는 객체를 만들어 사용했는데 프로젝트가 규모가 커지고 필요한 기술들이 늘어나면서 특정 기술과 환경에 종속되는 경우가 빈번하게 발생하였다. 또한, 작성된 코드의 유지/보수가 어렵고 Java에서 상속의 특성상 이미 특정 클래스를 상속하게되어 다른 상위 클래스를 상속하여 기능을 확장하기도 어려운 상황이 발생했다. 결국 좋은 객체지향 설계를 할 수 있는 Java 언어를 사용하면서, 객체지향 설계의 본질을 잃어버리는 문제점들을 해결하고자 POJO 라는 개념이 등장하였다.

 

POJO(Plain Old Java Object)란?

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

POJO라는 용어는 이후에 주로 특정 자바 모델이나 기능, 프레임워크 등을 따르지 않은 자바 오브젝트를 지칭하는 말로 사용되었다. 스프링 프레임워크는 POJO 방식의 프레임워크이다.
-위키 백과

그럼 특정 기술규약과 환경에 종속되지 않으면 모두 POJO라고 말할 수 있는가? 많은 개발자가 크게 오해하는 것 중의 하나가 바로 이것이다. ...(중략)...
진정한 POJO란 객체지향적인 원리에 충실하면서, 
환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 말한다.
-토비의 스프링-

오래된 방식의 간단한 자바 오브젝트란? 특정 기술에 종속되지 않는 순수한 자바 객체를 의미한다.

예를 들어 ORM(Object Relationship Mapping)기술을 사용하고 싶다면 ORM 프레임워크를 사용해야 한다. Java에서 대표적으로 하이버네이트(Hibernate) 프레임워크가 있다. 만약 Java객체가 ORM 기술을 사용하기 위해 하이버네이트를 직접 의존하는 순간 POJO라고 할 수 없다. 그 이유는 특정 기술에 종속되었기 때문이다.

 

특정 기술을 사용하고 싶다면?

Spring에서 POJO를 유지하면서 Hibernate를 사용할 수 있는 이유는 Spring에서 정한 표준 인터페이스가 있기 때문이다. 스프링 개발자들은 ORM 이라는 기술을 사용하기 위해 JPA라는 표준 인터페이스를 정의했다. 그리고 여러 ORM 프레임워크들은 JPA 표준 인터페이스의 규칙에 따라 구현되어 실행된다. 이 것이 스프링이 새로운 엔터프라이즈 기술을 도입하면서도 POJO를 유지할 수 있는 방법이다. 그리고 이러한 방법을 Spring의 PSA라고 이야기한다.

 

POJO 프로그래밍이란?

POJO를 이용해서 프로그래밍 코드를 작성하는 것을 의미한다.

단순히 순수 자바 객체만을 사용해서 프로그래밍 코드를 작성한다고 해서 POJO 프로그래밍이라고 볼 수 없다.

따라서 POJO 프로그래밍으로 작성한 코드라고 불리기 위해서는 아래의 두 가지 기본적인 규칙은 지켜줘야 한다.

 

 

POJO프로그래밍 두 가지 기본적인 규칙

1. Java나 Java의 스펙(사양)에 정의된 것 이외에는 다른 기술이나 규약에 얽매이지 않아야 한다.

// getter, setter만 가지고 있는 예시

public class User {
    private Long id;
    private String userId;
    private String password;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

위의 코드는 자바에서 제공하는 기능만을 사용하여 getter, settter만 가지고 있는 코드로 해당 클래스의 코드에서는 Java 언어 이외에 특정한 기술에 종속되어 있지 않은 순수한 객체이기 때문에 POJO라고 부를 수 있다. 

// 특정 기술에 종속적인 예시

public class MessageForm extends ActionForm{
	
	String message;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
	
}

public class MessageAction extends Action{
	
	public ActionForward execute(ActionMapping mapping, ActionForm form,
		HttpServletRequest request, HttpServletResponse response)
        throws Exception {
		
		MessageForm messageForm = (MessageForm) form;
		messageForm .setMessage("Hello World");
		
		return mapping.findForward("success");
	}
	
}

위의 코드는 Java 코드가 특정 기술에 종속적인 예를 보여주기 위한 코드로 ActionForm 클래스는 과거에 Structs라는 웹 프레임워크에서 지원하는 클래스이다. 

(1) MessageForm 클래스에서는 Structs라는 기술을 사용하기 위해 ActionForm을 상속받고 있다.

(2) MessageAction 클래스에서도 역시 Structs 기술을 사용하기 위해  Action 클래스를 상속받고 있다.

이렇게 특정 기술을 상속해서 코드를 작성하면 추후 애플리케이션의 요구사항이 변경되었을 때 Structs 클래스를 명시적으로 사용했던 부분을 전부 다 일일이 제거하거나 수정해야 한다.

또한, Java는 다중 상속을 지원하지 않기 때문에 'extends' 키워드를 통해 한 번 상속하게 되면 상위 클래스를 상속받아 하위 클래스를 확장하는 객체지향 설계 기법을 적용하기 어려워 진다.

 

2. 특정 환경에 종속적이지 않아야 한다. 

서블릿(Servlet) 기반의 웹 애플리케이션을 실행시키는 서블릿 컨테이너(Servlet Container)인 아파치 톰캣(Apache Tomcat)을 이용하여 순수 Java로 작성한 애플리케이션 코드 내에 Tomcat이 지원하는 API를 직접 가져다 사용한다고 가정해보자 

Tomcat 대신에 Zetty를 사용하세요!

만약 시스템의 요구사항이 변경되어 Tomcat 말고 Zetty라는 다른 Servlet Container를 사용해야 한다면 어떻게 될까 ?

 

애플리케이션에서 사용하고 있는 Tomcat API 코드를 모두 걷어내고 Zetty로 수정하거나 최악의 경우 애플리케이션을 전부 갈아 엎어야 할지도 모르는 상황에 직면할 수 있다.

 

 

 

애플리케이션 프로그래밍 코드를 작성할 때 항상 내가 작성한 코드가 객체지향스러운가? 에 대한 고민하는 습관을 들이자!

 


Reference.

https://ko.wikipedia.org/wiki/Plain_Old_Java_Object

https://siyoon210.tistory.com/120