top bar

글 목록

2017년 7월 9일 일요일

[Spring] POJO의 이해

개요



'POJO'란, 'Plain Old Java Object'의 약자이다. 이 용어의 유래를 잘 찾아보면 굉장히 허무할 것이다. 이유는 아래와 같다.

2000년 즈음에, 마틴파울러는 '평범한' JAVA 오브젝트에 비즈니스 로직을 넣어 사용하는 것이 기존에 널리 사용되던 EJB 빈보다 뛰어난 점에 주목하고 있었는데, 이러한 장점에 비해 폼나는 용어가 없어서 만들었다는 것이 바로 'POJO' 라는 것이다. 링크 참고

아래의 spring.io 웹사이트에, 스프링 관점에서 POJO의 이해를 돕는 글이 있다.

https://spring.io/understanding/POJO#understanding-pojos

위의 글 또한, POJO를 한 문장으로 잘 설명하고 있다.






여기서 'be bogged down' 이라는 문구가 낯설었는데, 이 숙어의 뜻을 찾아보니 '너무 복잡하거나 어려워서 다른것을 할 수 없는' 이라는 뜻이었다. 따라서 위 문장은 "프레임워크에 의해 확장된 즉, 그것으로 인해 'bogged down' 되지 '않은' 자바 오브젝트" 정도의 뜻이 되지 않을까 싶다. 뭐 이러한 뜻풀이는 난해 할 수도 있으니, 그냥 '평범한 자바 오브젝트' 라고 이해해야 겠다.


예시를 통한 이해



가령, 'JMS'를 통해 메시지 수신의 기능을 하는 클래스를 설계한다고 해보자. 아래와 같을 것이다.

public class ExampleListener implements MessageListener {

    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            try {
                System.out.println(((TextMessage) message).getText());
            }
            catch (JMSException ex) {
                throw new RuntimeException(ex);
            }
        }
        else {
            throw new IllegalArgumentException("Message type error");
        }
    }
}

위 클래스는 특정 메시징 솔루션(JMS)의 인터페이스를 구현(implements) 하고 있다. 다시 말하면 해당 인터페이스에 '종속'되어 있는 것이다. 따라서 다른 대안적인 메시징 솔루션을 적용하려고 한다면 매우 큰 변경 비용이 들 것은 자명하다. (당연히, 거대한 코드 베이스를 가지고 있는 대규모 프로젝트의 경우를 말한다)

이것을 'POJO'의 관점에서 접근한다면, 메시지를 처리하는 클래스가 특정 솔루션에 종속되지 않은, (원문에서는 'solution free'라고 표현한다) 상태로 설계 되어야 한다. 아래와 같다.

@Component
public class ExampleListenerPojo {

    @JmsListener(destination = "myDestination")
    public void processOrder(String message) {
        System.out.println(message);
    }
}

이것이 스프링이 추구하는 'POJO' 클래스의 모습이다. 'JMS'와 관련된 확장 코드가 보이지 않으며, 따라서 'JMS'와 커넥션을 연결하고 메시지를 처리하는 책임은 모두 어노테이션에 위임 된 것을 볼 수 있다.

그리고 만약 'JMS'에서 'RabbitMQ'로 메시징 솔루션을 변경한다고 했을때, 개발자는 '@JmsListener' 어노테이션을 '@RabbitListener' 어노테이션으로 교체 하기만 하면 된다. 또한 이러한 설계는 라이브러리에 종속적이지 않아 단위 테스트를 용이하게 해 준다. 여기서 스프링 'POJO'의 강력함이 드러난다고 볼 수 있다.

이렇듯 'POJO'를 통해, 스프링은 개발자의 코드와 외부 라이브러리의 'Coupling' 을 최소화 시켜준다. 이것은 다시말하면 개발자가 작성한 서비스 코드는 그 서비스 자체로 주체가 되는 것이 아니라 전체 어플리케이션의 한 part로서 동작하고, 전체 어플리케이션에 '연결'(wiring) 되게 함으로서, 좀더 확장성 있는 소프트웨어 설계를 가능하게 해준다는 것이다. 또한 이것은 'Inversion Of Control(IOC)'과 'Dependency Injection(의존성 주입)' 의 메인 컨셉이기도 하다.

하지만 단순히 클래스 설계시 'implements'와 'extends' 키워드를 사용하지 않는다고 해서 POJO 인가? 라고 했을때는 조금은 의아하다. 스프링을 사용한 프로젝트는 이미 어노테이션으로 떡칠(?)되어 있을 것이고, 이 어노테이션 자체도 특정 라이브러리에 종속되어 있기 때문이다.

'스프링은 완전한 POJO를 제공한다'에 대해선 반대의 입장이지만,
흠.. 내공이 부족해서 일까. POJO의 관해선 조금 더 연구가 필요 할 것 같다.



댓글 없음:

댓글 쓰기