- 이따금씩 강의를 들으면 POJO라는 단어가 제법 나온다. 이참에 한 번 정리를 해보기 위해 글을 적어본다. 기술 면접에서도 질문을 받아본 적이 있다
단순함으로 돌아가다
- POJO는 특정 기술이나 프레임워크에 얽매이지 않고, 순수한 자바 객체 지향 원리에 따라 설계된 일반적인 자바 객체를 의미한다. 2,000년대 초, EJB(Enterprise JavaBeans)와 같은 ‘무거운’ 프레임워크들이 특정 기술 스펙에 강하게 종속되어 복잡하고 재활용이 어려운 객체를 만들게 되자, 이에 대한 반작용으로 마틴 파울러(Martin Fowler)를 포함한 여러 개발자들이 ‘간단한 객체’의 중요성을 강조하며 POJO라는 용어를 만들었다.
POJO가 등장한 배경: EJB의 복잡성
POJO가 등장하기 이전의 기술들, 예를 들어 EJB, 애플릿, 서블릿, JSP 등 여러 기술들은 아래와 같은 특징이 있다
- 강력한 규칙과 제약: 특정 패키지를 임포트해야 하고, 특정 클래스를 상속받아야 하며, 미리 정해진 메서드 시그니처를 오버라이딩해야 하는 등 엄격한 규칙을 따라야 한다
- 높은 기술 종속성: 이러한 규칙들은 곧 특정 기술이나 프레임워크에 대한 강한 종송석을 의미한다. 코드가 특정 환경에 묶여 유연성이 떨어지고 재활용이 어렵다
- 높은 메모리 사용량: 불필요한 객체 생성을 강제하거나 복잡한 구조로 인해 메모리 사용량이 많다
EJB를 사용하며 불편함을 느낀 개발자가 직접 만든 오픈소스
- Spring: EJB를 사용하며 프로젝트를 진행하던 로드 존슨(Rod Johnson)이 EJB를 비판하면서 쓴 책(expert one on one j2ee development without ejb)이 스프링의 전신이 되었다
- Hibernate: EJB의 Entity Bean을 사용하며 개발하던 개빈 킹(Gavin King)이 퇴근 후 오픈소스를 만들었는데 그게 바로 하이버네이트이다. JPA(하이버네이트를 기반으로 Java Persistence API의 새로운 표준 정의)
서블릿 예시
- HttpServlet을 상속하고 public 클래스로 선언해야 하며, 기본 생성자와 특정 콜백 메서드(service)를 오버라이딩 해야한다. 심지어 사용하지 않을 HttpServletRequest, HttpServletResponse 객체를 매개변수로 받아야 하는 제약도 있다.
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public HelloServlet() {
super();
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 비즈니스 로직
}
}
POJO의 특징 및 장점
- 순수함 (Plain): 특정 기술이나 프레임워크에 종속되지 않고, 일반적인 자바 언어와 표준 API만으로 작성된다
- 익숙함 (Old): 객체 지향의 원리에 충실하여 복잡한 기술적 의존성 없이 비즈니스 로직 구현에 집중할 수 있다록 설계된다
- 자바 오브젝트 (Java Object): 자바의 표준 기능을 사용하여 개발되며, 기술적인 복잡성을 줄이고 재활용성을 높인다
스프링에서의 POJO
스프링 프레임워크에서는 POJO를 기반으로 객체를 설계한다. 메서드 이름, 리턴 타입, 매개변수 등 어떤 제약도 없다
public class MySerevice {
public String doSomething(String input) {
return "Hello, " + input;
}
protected void anotherMethod() {
// 자유로운 로직 구현
}
}
- MyService 클래스는 어떠한 특정 클래스도 상속하지 않고, 특별한 인터페이스를 구현할 필요도 없으며, 메서드의 시그니처로 개발자가 자유롭게 정의할 수 있다. 이것이 바로 POJO의 핵심이다
POJO의 장점
- 높은 가독성과 유지보수성: 코드가 간결하고 특정 기술에 대한 의존성이 적어 이해하기 쉽고 유지보수가 용이하다
- 뛰어난 재사용성: 특정 환경이나 기술에 묶이지 않으므로 다양한 프로젝트나 모듈에서 쉽게 재활용할 수 있다
- 쉬운 테스트: 외부 의존성이 적어 단위 테스트를 작성하기 매우 용이하다. 이는 개발 과정에서 코드 품질을 높이는 데 크게 기여한다
- 유연하고 확장 가능한 설계: 기술 종속성이 낮아 변화하는 요구사항에 빠르게 대응하고, 시스템을 유연하게 확장할 수 있다
- 메모리 효율성: 불필요한 객체 생성이나 복잡한 구조를 강제하지 않아 메모리 사용량을 줄일 수 있다
스프링과 POJO
- Juergen Hoeller(유겐 휠러), Yann Caroff(얀 카로프)가 로드 존슨에게 오픈소스 프로젝트를 제안하였다. 스프링이랑 이름은 얀 카로프가 지었다고 한다
- 스프링 프레임워크는 POJO 기반의 개발을 적극적으로 지원하며, 이를 통해 엔터프라이즈 애플리케이션 개발의 복잡성을 크게 줄였다. 스프링은 POJO에 IoC / DI(제어의 역전 / 의존성 주입), AOP(관점 지향 프로그래밍), PSA(Portable Service Abstraction)와 같은 강력한 엔터프라이즈 서비스 기능을 제공하여, 개발자들이 비즈니스 로직에만 집중할 수 있도록 돕는다
- POJO는 단순히 ‘오래된 방식의 간단한 자바 객체’라는 의미를 넘어, 소프트웨어 개발에서 객체 지향의 본질로 돌아가고가 하는 철학을 담고 있다. 이를 통해 개발자는 더 유연하고, 테스트하기 쉬우며, 유지보수가 용이한 애플리케이션을 구축할 수 있게 되었다
PS – 왜 ‘Old’일까?
- 개인적으로 ‘Old’라는 단어가 주는 어감 때문에 혼동이 된다. ‘Old’는 시간적인 ‘과거’나 ‘오래됨’ 등으로 인식하고 있었기 때문이다. 하지만 ‘Old’는 긍정적인 뉘앙스로 ‘숙성된’, ‘경험 많은’ ‘변치 않는 가치를 지닌’등의 의미를 내포한다고 한다
- ‘새로움’과 ‘발전’지향 문화: ‘새로운 것(New)’은 ‘발전’과 ‘진보’를 상징하고 ‘오래된 것(Old)’은 ‘뒤쳐진 것’, ‘개선이 필요한 것’으로 인식되는 경향이 있다
- 세대 간 격차 및 급변하는 트랜드: 한국 사회는 세대 간의 문화적, 기술적 격차가 매우 빠르게 벌어지는 편이다. ‘Old’는 종종 ‘나이 든 세대’ 또는 ‘과거의 방식’과 연결되며, 젊은 세대에게는 ‘고루함’, ‘답답함’ 등의 부정적인 의미로 받아들여지기 쉽다. 또한 ‘Old’는 ‘유행에 뒤처진’, ‘촌스러운’ 이미지와 쉽게 결부된다.
- 번역 및 언어 사용의 미묘한 차이: 영어 ‘Old’는 ‘오래된’, ‘나이든’ 외에도 ‘숙련된(old hand)’, ‘오랜 친구(old friend)’, ‘고전적인(old school)’등 긍정적인 의미를 가질 수 있지만, 한국어의 ‘오래된’은 단순히 시간적 경과만을 나타낼 뿐, 영어처럼 그 자체로 ‘숙성된 가치’나 ‘친밀함’을 내포하는 경우가 드물다. ‘낡았다’는 표현은 ‘오래되어 망가진’, ‘쓸모 없어진’ 이라는 부정적인 뉘앙스가 강하다. ‘오래된 물건’이라는 표현은 ‘낡은 물건’과 거의 동의어로 쓰이며, ‘오래된 가게’는 ‘낡고 허름한 가게’의 느낌을 줄 때가 많다
- 역사적 유산 보존의 대한 인식: 서구권에서는 ‘Old Town’, ‘Old Master’등 ‘Old’가 역사적 가치와 전통, 품격을 나타내는 긍정적인 의미로 많이 사용된다. 반면 한국은 근대화를 겪으면서 전통적인 것들이 많이 파괴되거나 소외되었고 ‘Old’가 ‘보존해야 할 가치’보다는 ‘개발해야 할 대상’으로 인식된 시기가 길었다. 최근에는 인식이 많이 변하고 있지만, 여전히 저변에 이러한 경향이 남아있다
- ‘오래된 친구’, ‘오래된 맛집’, ‘오래된 책’등 긍정적으로 사용되는 경우도 분명히 있지만, ‘Old’라는 단어 자체보다는 ‘신뢰’, ‘전통’, ‘역사’, ‘추억’ 등 다른 긍정적인 맥락이나 부연 설명과 함께 붙어야 그 의미가 강화되는 경향이 있다. 단순히 ‘Old’만 단독으로 사용될 때는 부정적이거나 중립적인 뉘앙스로 기울기 쉽다
POJO의 ‘Old’의 긍정적이고 본질적인 의미
- 초심으로의 회귀 (Back to Basics): ‘Old’는 ‘최신 유행이나 복잡한 꾸밈이 없는’상태를 의미한다. 마치 ‘Old school’이라는 표현이 ‘구식’이라는 부정적인 의미보다는 ‘고전적이고 기본적인 원칙에 충실한’이라는 긍정적인 의미로 쓰이듯이, POJO의 ‘Old’는 자바 객체 지향의 본질적인 단순함과 순수함으로 돌아가자는 개발자들의 열망을 나타낸다. EJB처럼 복잡하게 진화된 형태가 아니라, 자바가 처음 등장했을 때 지향했던 그 평범한 객체의 의미이다
- 변치 않는 가치 (Enduring Value): 와인이 오랜 시간 숙성되어 그 가치를 인정받듯이, POJO의 ‘Old’는 특정 기술이나 시대의 유형을 타지 않고 항상 변치 않는 기본적인 객체 지향 원칙의 중요성을 강조한다. 아무리 새로운 기술이 나와도, 잘 설계된 단순한 객체는 그 자체로 강력한 가치를 지닌다는 의미이다.
- 간결하고 익숙함 (Simple and Familiar): ‘Old’는 ‘오랫동안 존재해왔기에 익숙하고 이해하기 쉬운’이라는 느낌도 준다. EJB가 새로운 규칙과 복잡한 개념으로 개발자들을 혼란스럽게 했다면, POJO는 누구나 자바를 배우면서 가장 먼저 접근한 ‘평범한 클래스’처럼 간결하고 익숙한 형태로 코드를 작성하자는 메시지를 담고 있다
POJO의 ‘Old’는 단순히 시간적인 ‘과거’나 ‘낡음’이 아니라, ‘본질적 가치’, ‘기본 원칙’, ‘순수함’으로 회귀하자는 긍정적이고 철학적인 의미를 내포한다. 복잡하고 무거워진 기존 기술들에 대한 반동으로 자바 객체가 처음부터 지니고 있던 ‘Plain’하고 ‘Simple’한 특성을 다시 강조하기 위한 선택이었다고 볼 수 있다