POJO(Plain Old Java Object)
스프링 백엔드 개발자를 위한 관점으로 POJO(Plain Old Java Object) 를 정리해보자.
POJO 란 무엇인가?
POJO는 "Plain Old Java Object"의 약자로, 특정 프레임워크나 기술에 종속되지 않은 순수한 자바 객체를 의미한다. 스프링 개발에서 POJO는 매우 중요한 개념이다. 스프링 프레임워크 자체가 POJO 중심의 개발을 강력하게 지원하기 때문이다.
자바의 기본에 충실: 특정 규약(예: 특정 클래스 상속, 특정 인터페이스 구현 강제) 없이, 자바 언어 명세에 따라 작성된 객체이다.
독립성: 객체가 특정 프레임워크 API나 환경에 직접적으로 의존하지 않아, 객체 자체의 생명주기나 동작 방식이 프레임워크에 의해 크게 좌우되지 않는다.
POJO는 객체지향의 핵심 원칙, 특히 객체 간의 명확한 책임 분담을 프레임워크의 간섭 없이 지켜나갈 수 있도록 돕는 중요한 접근 방식 또는 스타일이라고 할 수 있다.
POJO 의 등장 배경
POJO라는 용어는 2000년대 초반에 등장했다. 당시 엔터프라이즈 자바 개발 환경은 EJB(Enterprise JavaBeans) 같이 무겁고 침투적인(invasive) 프레임워크가 주를 이루었다.
과거 프레임워크의 문제점:
높은 결합도: 개발자는 비즈니스 로직을 구현하기 위해 프레임워크에 특화된 클래스(예: javax.ejb.SessionBean)를 상속받거나, 특정 인터페이스(예: javax.ejb.EntityBean)를 구현해야 했다. 이로 인해 비즈니스 로직이 담긴 객체가 프레임워크 기술에 깊숙이 결합되었다.
테스트의 어려움: 객체가 프레임워크 환경에 강하게 의존했기 때문에, EJB 컨테이너와 같은 특정 환경 없이는 단위 테스트를 수행하기 매우 어려웠다. 이는 개발 생산성을 저해하고 코드 품질 관리를 어렵게 만들었다.
과도한 복잡성: 프레임워크를 사용하기 위해 많은 설정과 규약을 따라야 했고, 이는 개발의 복잡성을 증가시켰다.
POJO로의 전환: 이러한 문제들에 대한 반작용으로, "단순한 자바 객체로도 충분히 엔터프라이즈 애플리케이션을 개발할 수 있어야 한다"는 생각이 확산되었다. 즉, 개발자가 비즈니스 로직에만 집중하고, 객체가 특정 기술의 복잡성으로부터 자유로워져야 한다는 요구가 POJO라는 개념을 탄생시켰다.
왜 스프링 개발에서 POJO 가 중요한가?
스프링의 핵심 철학은 POJO의 등장 배경과 맞닿아 있다. 스프링은 "비침투적(non-invasive)" 프로그래밍 모델을 제공하여, 개발자가 비즈니스 로직에 집중할 수 있도록 돕는다. POJO는 이러한 철학을 가능하게 하는 핵심 요소이다.
낮은 결합도(Decoupling): 비즈니스 로직을 담은 POJO는 스프링 프레임워크 코드로부터 분리된다. 이를 통해 시스템의 다른 부분에 영향을 주지 않고 특정 부분을 수정하거나 확장하기 용이해진다.
향상된 테스트 용이성: POJO는 스프링 컨테이너나 복잡한 설정 없이도 일반적인 JUnit 같은 도구를 사용하여 쉽게 단위 테스트를 할 수 있다. 이는 개발 속도와 코드 품질을 크게 향상시킨다.
코드의 단순성 및 가독성: POJO는 필요한 비즈니스 로직과 상태만을 가지므로 코드가 단순하고 이해하기 쉽다. 개발자는 프레임워크의 복잡한 내부 구조보다는 실제 구현하려는 기능에 더 집중할 수 있다.
유연성 및 재사용성: 특정 기술이나 환경에 묶여있지 않아, 필요에 따라 다른 환경이나 프레임워크로 이전하거나 핵심 로직을 재사용하기 유리하다.
스프링에서 POJO 는 어떻게 활용되는가?
스프링은 POJO를 사용하여 애플리케이션의 주요 구성 요소를 만든다.
빈(Beans)으로서의 POJO: 스프링 컨테이너는 POJO로 작성된 클래스들을 빈(Bean)으로 관리한다. 이 빈들은 애플리케이션의 핵심 로직을 수행하는 서비스 객체, 데이터 접근 객체(DAO), 도메인 객체 등이 될 수 있다.
의존성 주입 (Dependency Injection - DI): 스프링은 DI를 통해 POJO 객체들이 필요로 하는 다른 객체(의존성)들을 외부에서 주입해준다. POJO 자체는 의존성을 직접 생성하거나 검색할 필요가 없어 코드의 결합도가 낮아지고 유연성이 증가한다.
관점 지향 프로그래밍 (Aspect-Oriented Programming - AOP): 트랜잭션 관리, 보안, 로깅과 같은 **횡단 관심사(cross-cutting concerns)**를 POJO 코드의 변경 없이 적용할 수 있게 한다. AOP를 통해 POJO는 순수하게 비즈니스 로직에만 집중할 수 있다.
애노테이션과 POJO:
스프링에서 사용하는 @Component, @Service, @Repository, @Autowired, @Transactional 등의 애노테이션은 POJO에 메타데이터를 추가하여 스프링 컨테이너가 해당 객체를 어떻게 처리해야 할지 알려준다.
이러한 애노테이션들은 객체에게 특정 클래스 상속이나 인터페이스 구현을 강제하지 않으므로, POJO의 본질을 크게 해치지 않는다. 오히려 POJO가 스프링의 강력한 기능을 손쉽게 활용할 수 있도록 돕는 역할을 한다. 애노테이션이 붙은 클래스도 여전히 핵심 로직은 순수 자바로 유지되며 테스트 가능하다.
스프링 백엔드 개발자를 위한 POJO 실천 가이드
핵심 비즈니스 로직은 POJO로 작성한다: 서비스 계층, 도메인 모델 등은 특정 프레임워크에 대한 의존 없이 순수 자바 객체로 구현하는 것을 목표로 한다.
인터페이스를 활용한 설계: 구체 클래스보다는 인터페이스에 의존하게 만들어 유연성을 높이고 POJO 원칙을 지키는 데 도움이 된다.
DI 적극 활용: 객체 생성과 의존성 관리는 스프링 컨테이너에 맡기고, POJO는 필요한 의존성을 주입받아 사용하도록 한다.
단위 테스트 생활화: POJO로 작성된 코드는 테스트하기 쉬우므로, 견고한 애플리케이션을 위해 단위 테스트를 꾸준히 작성한다.
Last updated