본문 바로가기

Language/Java

[Java] POJO(Plain Old Java Object)란?

728x90
POJO(Plain Old Java Object)란?
  • 특정 프레임워크나 라이브러리에 의존하지 않는 순수한 자바 객체를 의미
  • 즉, Java의 기본 문법으로만 작성된 클래스 extends, implements를 강제하는 특정한 인터페이스나 클래스를 상속받지 않고 자유롭게 사용 가능
POJO의 특징
  • 특정 라이브러리나 프레임워크에 종속되지 않음
    • 예를 들어, @Entity 같은 JPA 어노테이션을 포함하면 그 클래스는 JPA에 종속적이지만, POJO는 이런 종속성이 없음
  • Getter, Setter 등의 일반적인 메서드를 가짐
    • 필드를 설정하고 가져오는 단순한 메서드들을 주로 포함
  • 비즈니스 로직을 순수하게 유지할 수 있음
    • 특정한 기술에 의존하지 않으므로 유지보수가 쉽고, 테스트하기 쉬운 구조가 됨
POJO의 예시
POJO인 경우
  • 다음의 User 클래스는 어떤 특정 프레임워크에도 의존하지 않는 순수한 Java 객체이므로 POJO
public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

 

POJO가 아닌 경우
  • @Component 어노테이션이 붙어 있어 Spring 프레임워크에 종속적
  • 따라서 POJO라고 할 수 없음
import org.springframework.stereotype.Component;

@Component
public class UserService {
    public String getUserInfo() {
        return "User Info";
    }
}
POJO는 상속을 받으면 안 되는가?
  • 가장 처음에 'extends, implements를 강제하는 특정한 인터페이스나 클래스를 상속받지 않고'라고 설명을 했는데, 이는 상속을 받으면 안 된다는 것이 아니라 특정 프레임워크나 기술에 종속되지 않아야 한다는 의미
  • Java 기본 라이브러리(예: Thread, Serializable, Comparable 등)의 클래스를 상속받거나 인터페이스를 구현하는 것POJO의 개념에 포함될 수 있음
  • 하지만 JPA의 JpaRepository, Spring의 CrudRepository 등을 상속받으면 특정 프레임워크(Spring Data JPA)에 종속되므로 POJO라고 보기 어려움
POJO인 경우 (Java 기본 클래스 상속)
  • Thread는 Java 표준 라이브러리이므로 프레임워크에 종속되지 않음
  • 따라서 아래의 클래스는 POJO
public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread is running...");
    }
}
POJO가 아닌 경우 (Spring JPA 종속)
  • JpaRepository는 Spring Data JPA에서 제공하는 인터페이스이므로 Spring 프레임워크에 종속적
  • 따라서 아래의 클래스는 POJO가 아님
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
}

Lombok을 사용하면 POJO가 아닌가?
  • Lombok은 개발자가 자주 사용하는 Getter, Setter, ToString 메서드 등을 어노테이션으로 간단히 구현하여 개발 향상성, 가독성, 유지보수성을 높이는 라이브러리인데, 그렇다면 Lombok에 종속적이게 된다고 생각할 수 있음
  • POJO의 핵심특정한 프레임워크나 기술 스택에 종속되지 않는 순수한 Java 객체를 의미하는 것이지, 빌드 타임(컴파일 과정)에서 코드 생성을 돕는 도구(Lombok)를 사용하느냐 마느냐가 기준이 아님
  • Lombok은 애플리케이션이 실행될 때 동작하는 라이브러리가 아니라 컴파일 타임에 코드 생성을 도와주는 도구이므로 런타임에서 특정 프레임워크에 의존하는 것이 아님
  • 즉, Lombok을 사용해도 객체의 행동 방식은 일반 Java 클래스와 다를 바 없기 때문 POJO로 볼 수 있음
Lombok 예시
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class User {
    private String name;
    private int age;
}

 

  • 위 코드는 Lombok을 사용한 것이지만, 컴파일 후에는 결국 아래와 같은 POJO 형태가 됨
public class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
  • 즉, Lombok을 사용하더라도 POJO의 기본 원칙을 따르고 있기 때문POJO라고 볼 수 있음
Lombok은 무조건 POJO인가?
  • Lombok 자체가 필수적인 의존성이 될 경우
    • Lombok은 Java 코드의 가독성과 유지보수성을 높이지만, 만약 Lombok이 없을 경우 코드가 정상적으로 동작하지 않는다면 이는 POJO의 개념에서 벗어날 수 있음
    • 예를 들어, @ToString, @EqualsAndHashCode 등을 사용할 때 예상치 못한 동작을 할 수 있으므로 조심해야 함
  • 이식성을 고려할 때
    • Lombok을 사용하면 프로젝트를 다른 개발 환경(예: Lombok이 지원되지 않는 환경)으로 옮길 때 문제가 생길 수 있음
    • 이런 경우 POJO 원칙을 철저히 지키려면 Lombok 대신 직접 getter/setter를 작성하는 것이 필요할 수 있음
결론 : Lombok을 사용해도 POJO이다
  • Lombok을 사용해도 POJO이지만 Lombok이 필수적인 의존성이 되어 POJO의 독립성을 해치는 방식으로 사용하면 주의가 필요
  • 즉, Lombok을 적절히 활용하면서도 만약 Lombok을 제거하더라도 객체가 정상적으로 동작할 수 있도록 신경 쓰는 것이 중요

결론 : POJO를 유의해서 코딩해야 하는가?
  • 반드시 POJO로만 코딩해야 하는 것은 아니지만, 유지보수성과 확장성을 높이기 위해 POJO를 지향하는 것이 좋음
  • 프레임워크에 종속되지 않기 때문테스트하기 쉽고, 다른 환경에서도 재사용이 용이함
  • Spring, Hibernate 같은 프레임워크도 결국 POJO를 지원하는 방향으로 발전
  • POJO를 기반으로 DI(Dependency Injection)를 적용하면 코드가 더욱 깔끔해지고 유연해짐
728x90