POJO(IoC/DI, AOP, PSA)
POJO (Plain Old Java Object)
Java나 Java의 스펙(사양)에 정의된 것 이외에는 다른 기술이나 규약에 얽매이지 않아야 한다. 특정 환경에 종속적이지 않아야 한다.
POJO 프로그래밍이 필요한 이유
- 특정 환경이나 기술에 종속적이지 않으면 재사용 가능하고, 확장 가능한 유연한 코드를 작성할 수 있다.
- 저수준 레벨의 기술과 환경에 종속적인 코드를 애플리케이션 코드에서 제거함으로써 코드가 깔끔해진다.
- 코드가 깔끔해지기 때문에 디버깅하기도 상대적으로 쉽다.
- 특정 기술이나 환경에 종속적이지 않기 때문에 테스트 역시 단순해진다.
- 객체지향적인 설계를 제한 없이 적용할 수 있다. (가장 중요한 이유)
1. IoC(Inversion of Control): 제어의 역전
개념
- IoC는 제어의 역전을 의미합니다.
- 기존에는 애플리케이션 코드가 프레임워크나 라이브러리에 의존하며 제어를 받았지만, IoC에서는 애플리케이션 코드가 프레임워크에게 제어의 권한을 넘기는 개념입니다.
- 프레임워크가 애플리케이션의 제어 흐름을 조정하고 필요한 작업을 수행합니다.
POJO에서 IoC의 필요성
- POJO는 특정 환경이나 기술에 종속되지 않는 일반적인 객체를 의미합니다.
- IoC는 POJO를 활용하여 객체 간의 결합도를 낮추고, 유연하고 확장 가능한 애플리케이션을 구축할 수 있도록 합니다.
- POJO와 IoC를 함께 사용하면 애플리케이션의 제어 흐름을 프레임워크에 위임하면서도 객체의 종속성을 낮출 수 있습니다.
필요성
- POJO와 IoC를 결합하면 애플리케이션의 개발과 유지보수가 훨씬 용이해집니다.
- POJO를 사용하면 객체를 일반적으로 작성할 수 있으며, IoC는 객체를 조립하고 관리함으로써 애플리케이션의 구성을 쉽게 변경하고 유지보수할 수 있도록 도와줍니다.
- 이를 통해 애플리케이션의 유연성과 확장성을 크게 향상시킬 수 있습니다.
2. DI(Dependency Injection): 의존성 주입
개념
의존성 주입은 객체 간의 의존성을 외부에서 주입하는 디자인 패턴입니다. 객체는 직접 의존하는 객체를 생성하거나 관리하지 않고, 외부에서 필요한 의존 객체를 전달받아 사용합니다. 이를 통해 객체 간의 결합도를 낮추고 유연한 애플리케이션을 구축할 수 있습니다.
장점
- 유연성: 객체 간의 결합도가 낮아지므로 변경이 쉬워집니다. 새로운 구현체로의 교체나 기능의 변경이 용이해집니다.
- 재사용성: 독립적인 객체를 생성하여 재사용하기 쉽습니다. 코드의 중복을 줄이고 개발 시간을 단축시킵니다.
- 테스트 용이성: 의존 객체를 외부에서 주입받기 때문에 테스트할 때 모의 객체(mock object) 또는 가짜 객체(fake object)를 주입하여 테스트할 수 있습니다.
종류
- 생성자 주입(Constructor Injection): 의존 객체를 생성자를 통해 주입받습니다.
- 세터 주입(Setter Injection): 의존 객체를 세터 메서드를 통해 주입받습니다.
- 인터페이스 주입(Interface Injection): 의존 객체를 인터페이스를 통해 주입받습니다. (많이 사용되지 않습니다) 의존성 주입을 사용하면 서비스 객체가 데이터 액세스 객체를 직접 생성하거나 관리하지 않고, 외부에서 데이터 액세스 객체를 주입받아 사용할 수 있습니다.
3. AOP(Aspect Oriented Programming): 관심 지향 프로그래밍
개념
AOP는 OOP의 한계를 보완하여 핵심 비즈니스 로직과 공통적인 부가 기능(로깅, 트랜잭션 관리, 보안 등)을 분리하여 개발하는 방법론입니다. 핵심 비즈니스 로직에 집중할 수 있도록 공통적인 부가 기능을 여러 모듈에 분산시키는 것이 핵심 아이디어입니다.
장점
- 모듈성 향상: 공통 기능을 독립적인 모듈로 분리하여 관리하므로 코드의 모듈성이 향상됩니다.
- 중복 제거: 공통 기능을 여러 곳에 중복해서 구현하지 않고 하나의 모듈로 관리할 수 있습니다.
- 코드의 가독성 향상: 핵심 비즈니스 로직과 부가 기능이 분리되므로 코드의 가독성이 향상됩니다.
구성 요소
- Aspect(관점): 부가 기능을 담당하는 모듈을 의미합니다.
- Target(타겟): 부가 기능을 적용할 대상입니다. 대부분의 경우, 객체가 타겟이 됩니다.
- Advice(조언): 부가 기능을 구현한 코드를 의미합니다. Before, After, Around 등의 Advice가 있습니다.
- Join Point(결합 지점): 부가 기능이 적용될 수 있는 지점을 의미합니다.
4. PSA(Portable Service Abstraction)
PSA(Portable Service Abstraction)는 Spring Framework에서 제공하는 개념으로, 여러 서비스 프로바이더의 기술적인 차이를 추상화하여 동일한 인터페이스를 통해 서비스를 사용할 수 있도록 합니다.
개념
PSA는 서비스의 기술적인 구현과 서비스를 사용하는 클라이언트 코드 사이의 결합도를 낮춥니다. 여러 서비스 프로바이더의 기술적인 차이를 추상화하여 클라이언트 코드가 특정 기술에 종속되지 않도록 합니다. 클라이언트 코드는 동일한 인터페이스를 사용하여 여러 서비스를 사용할 수 있습니다.
장점
- 기술적인 변화에 대한 유연성: PSA를 사용하면 서비스의 구현체를 변경하더라도 클라이언트 코드를 변경할 필요가 없습니다.
- 단일화된 클라이언트 코드: 여러 서비스 프로바이더에 대해 동일한 방식으로 상호작용할 수 있으므로 클라이언트 코드가 단순해집니다.
- 테스트 용이성: PSA를 사용하면 서비스의 구현체를 대체하기 쉽기 때문에 테스트를 수행할 때 모의 객체(mock object)를 사용하여 테스트할 수 있습니다.