POJO와 JavaBeans

헙크·2023년 5월 6일
2

POJO

1. POJO란 무엇인가?

POJO(Plain Old Java Object)라는 개념은 2000년대 초반에 마틴 파울러(Martin Fowler), 레베카 파슨스(Rebecca Parsons), 조쉬 맥킨리(Josh MacKenzie) 등이 처음 사용했습니다. 이 개념은 자바 프로그래밍 커뮤니티에서 복잡한 프레임워크와 라이브러리를 사용하는 대신, 간단하고 이해하기 쉬운 자바 객체를 사용하는 것을 강조하기 위해 만들어졌습니다.

2. 무엇을 POJO라 할 수 있을까?

  1. 특정 프레임워크나 라이브러리에 종속되지 않은 객체

    순수한 자바 객체는 특정 프레임워크나 라이브러리의 클래스를 상속받거나, 인터페이스를 구현하지 않습니다. 이로 인해 코드의 의존성이 낮아지고, 다양한 환경에서의 사용이 용이해집니다.

  2. 객체 지향 원칙에 따라 작성된 객체

    순수한 자바 객체는 객체 지향 프로그래밍의 원칙을 따르며, 캡슐화, 상속, 다형성 등의 원칙을 사용하여 작성됩니다.

  3. 간단한 자바 클래스

    순수한 자바 객체는 복잡한 구조나 로직이 없는 간단한 자바 클래스입니다. 이는 코드의 가독성과 유지보수성을 높이며, 다른 개발자들이 쉽게 이해할 수 있는 코드를 작성할 수 있습니다. 한편으로 ‘간단하다’라는 것이 매우 주관적이기 때문에, 이 부분에서 많은 혼란이 오는 것 같습니다 ㅎㅎㅎ

  4. 제약 조건이 적은 객체

    순수한 자바 객체는 자바 빈즈처럼 특정 스펙에 따라 작성될 필요가 없으며, 필요한 로직과 구조를 자유롭게 작성할 수 있습니다. 이를 통해 개발자는 객체의 구현 방식에 대한 유연성을 가질 수 있습니다.

3. POJO의 목적

POJO의 목적은 크게 세 가지가 있습니다.

  1. 코드의 의존성을 낮춘다.

    특정 프레임워크나 라이브러리에 의존하지 않고 순수한 자바 객체를 사용함으로써, 코드의 의존성을 낮추고 유연한 구조를 만들 수 있습니다.

  2. 확장성 및 재사용성을 높인다.

    POJO를 사용하면 다양한 프레임워크와 라이브러리 간의 호환성이 높아집니다. 이로 인해 컴포넌트의 확장성과 재사용성이 증가합니다.

  3. 코드의 가독성과 유지보수성 개선한다.

    순수한 자바 객체를 사용하면 복잡한 구조와 로직이 없기 때문에 코드의 가독성과 유지보수성이 향상됩니다.

따라서 POJO는 순수하게 자바의 OOP 특성을 잘 살리면서 프로그래밍을 할 수 있는 하나의 지침으로 보입니다. OOP의 원칙인 SOLID처럼 우리는 항상 POJO를 만족하는 객체를 설계하도록 되도록이면 염두에 두어야 할 것으로 생각하면 될 것입니다.

JavaBeans

1. JavaBeans란?

JavaBeans는 Java에서 재사용 가능한 소프트웨어 컴포넌트(객체)를 생성하기 위한 기술 및 명세입니다. JavaBeans는 객체 지향 원칙에 따라 작성되며, 소프트웨어의 모듈성, 재사용성, 확장성을 증가시키는 데 도움이 됩니다. 주로 객체의 상태를 저장하고 조회하는데 사용되는 데이터 객체(Data Objects) 또는 데이터 전송 객체(Data Transfer Objects, DTO)로 사용됩니다.

2. JavaBeans 스펙

JavaBeans Specification(자바 빈즈 스펙)은 JavaBeans를 정의하는 규약으로, 다음과 같은 요소를 포함합니다.

  1. 기본 생성자

    자바 빈은 기본 생성자(인자가 없는 생성자)를 가져야 합니다. 이를 통해 프레임워크나 라이브러리가 빈 객체를 동적으로 생성할 수 있습니다.

  2. 필드

    자바 빈은 필드를 사용하여 객체의 상태를 저장합니다. 필드는 private으로 선언되어 클래스 외부에서 직접 접근할 수 없도록 합니다.

  3. getter

    각 속성에 대해 getXXX 형태의 접근자 메서드를 제공해야 합니다. 이 메서드는 해당 속성의 값을 반환합니다. boolean 타입의 속성의 경우 isXXX 형태의 메서드를 사용할 수도 있습니다.

  4. setter

    각 속성에 대해 setXXX 형태의 설정자 메서드를 제공해야 합니다. 이 메서드는 해당 속성의 값을 설정합니다.

3. JavaBeans 스펙을 따라야하는 부분

어찌됐든 JavaBeans 스펙은 정해진 것입니다. 이 스펙을 따르지 않는다면 JavaBeans라고 할 수 없겠죠. 그렇다면 이 스펙을 따르는 데에는 나름의 이유가 있을 것입니다!

만약 이 스펙을 따른다고 하면 많은 프레임워크와 라이브러리에서 개발자가 작성한 객체를 조작하기 쉬워질 것입니다. 실제로 많은 프레임워크와 라이브러리에서 자바 빈즈 스펙을 따라야만 리플렉션 및 직렬화, 데이터 바인딩 등과 같은 기술을 적용할 수 있게 해놨습니다.

스프링에서 요청값을 DTO로 매핑할 때에 Jackson 라이브러리가 DTO를 리플렉션을 사용해 직렬화를 진행하는 것을 예시로 들 수 있을 것 같습니다. 이때, 기본 생성자와 getter들이 모두 열려있어야 정상적으로 동작이 수행됩니다.

4. Trouble Shooting

프레임워크 혹은 라이브러리의 입장에서 한편으로 리플렉션을 사용한다면 필드값을 바로 가져올 수 있음에도 불구하고, 왜 getter를 통해서 가져오도록 해놨는지 의문이 들었습니다. 리플렉션 자체를 사용하면서 캡슐화를 논하는 것 자체가 이상할 것이고, 그렇다면 필드를 바로 접근해도 되는 것 아닌가라는 생각이 들었습니다.

필드가 아닌 getter를 사용해 필요한 값들을 가져오는 이유는 크게 두 가지라고 합니다.

  1. 캡슐화

    필드에 직접적으로 접근하는 것은 리플렉션을 통해 가능함에도 불구하고, 캡슐화를 지키기 위해 필드에 직접 접근하지 않는다고 합니다. 사실 잘 이해가 가지는 않지만, 라이브러리나 프레임워크 단에서 양심상 객체지향적으로 우리의 필드에 바로 접근하는 것이 아닌, getter로 public하게 열려 있는 값들을 통해 객체를 조작하는 것이라고 이해하면 좋을 것 같습니다.

  2. 일관성

    위와 같은 방식으로 많은 라이브러리와 프레임워크가 이미 설계되고 동작하고 있습니다. 따라서 관례적인 부분도 있고, getter는 어차피 열어두어도 큰 문제가 없기에 getter를 통해 값을 가져오도록 하는 것 같습니다.

POJO와 JavaBeans의 차이점

  1. 자바 빈즈는 자바 빈즈 스펙에 따라 작성되어야 하므로, 기본 생성자와 getter, setter 메서드를 반드시 포함해야 합니다. 반면, POJO는 이러한 제약 조건이 없으며 필요에 따라 다양한 생성자와 메서드를 가질 수 있습니다.
  2. 자바 빈즈는 객체를 재사용 가능하고, 컴포넌트 간 의사소통을 용이하게 하기 위해 설계되었습니다. 반면, POJO는 특정 기술이나 스펙에 종속되지 않고, 순수한 자바 객체를 작성하는 것을 목표로 합니다.
    (물론 POJO로 작성하더라도, 외부에서 리플렉션 혹은 데이터 바인딩이 가능할 것입니다.)
  3. 자바 빈즈는 속성의 값을 직렬화할 수 있어야 하므로, Serializable 인터페이스를 구현해야 할 때가 있습니다. 반면, POJO는 Serializable 인터페이스를 구현할 필요가 없습니다.

마치며

프로그래밍을 하다보면 POJO와 JavaBeans라는 용어를 들어보셨을 것 같습니다. 저도 리플렉션에 대해서 공부하다가 이를 마주치게 되었습니다.

POJO는 제가 느끼기에 매우 이론적인 개념인 것 같아서 쉽게 이해가되지 않았습니다. SOLID처럼 그저 객체지향 프로그래밍을 하기 위해 지키면 좋을 가치 정도로 생각하고 넘어가려고 합니다. JavaBeans는 엄연히 스펙이 존재하기 때문에 조금 더 이해하기 쉬웠습니다. JavaBeans 스펙을 만족하도록 객체를 만들면, 이를 따르고 있는 라이브러리와 프레임워크에서 리플렉션, 직렬화/역직렬화, 데이터 바인딩 등을 용이하게 할 수 있다고 이해했습니다.

이번 글은 간단하게 요런 개념들이 있구나~ 하고 가볍게 읽으셨으면 좋겠네요 :)

1개의 댓글

comment-user-thumbnail
2023년 5월 7일

잘 보고 갑니다~ 포조는 알았는데 빈즈는 처음 알았네요 👍

답글 달기