소프트웨어 개발에 있어서 객체 지향 프로그래밍은 매우 중요한 개념입니다. 객체 지향 프로그래밍은 코드의 재사용성, 유지보수성, 확장성 등을 높여주는 강력한 패러다임으로서 개발자들이 많이 사용하고 있습니다. 그 중에도 IoC (Inversion of Control)와 DI (Dependency Injection)는 스프링 프레임워크에서 필수적인 개념입니다.
1. IoC (Inversion of Control)
IoC란 "제어의 역전"이라는 뜻으로, 기존의 컨트롤 흐름을 개발자가 아닌 프레임워크 또는 컨테이너가 가져가는 것을 의미합니다. 기존의 어플리케이션 개발에서는 개발자가 객체의 생성과 관리를 직접 수행하는 경우가 많았습니다. 하지만 IoC에서는 이러한 객체의 생명주기와 의존성 관리를 프레임워크에 위임합니다.
IoC의 핵심 개념은 제어의 흐름이 개발자가 작성한 코드에 의해 결정되는 것이 아니라, 프레임워크가 객체들의 생성과 관계를 관리하는 것입니다. 이를 통해 애플리케이션의 객체들이 느슨하게 결합되어 유연하고 재사용 가능한 구조를 갖게 됩니다.
2. DI (Dependency Injection )
DI는 객체가 직접 의존하는 객체를 생성하거나 참조하는 것이 아니라 외부에서 의존하는 객체를 주입받는 방식입니다.
즉, 객체가 필요로 하는 의존성을 외부로부터 주입받는 것을 의미합니다.
DI를 사용하면 객체들 간의 결합도를 낮출 수 있으며, 유연하고 재사용 가능한 코드를 작성할 수 있습니다. 예를 들어, 서비스 객체가 데이터 액세스 객체에 의존하는 경우, DI를 통해 서비스 객체에 데이터 액세스 객체를 주입하여 애플리케이션의 구조를 단순화하고 테스트하기 쉬운 코드를 작성할 수 있습니다.
DI의 세 가지 주요 방법은 다음과 같습니다:
2.1. 생성자 주입
Constructor Injection은 객체의 생성자를 통해 의존성을 주입하는 방식입니다. 클래스의 생성자를 정의하고, 프레임워크가 해당 생성자를 호출하여 의존성을 주입합니다.
public class UserService {
private final UserDao userDao;
public UserService(UserDao userDao)
{ this.userDao = userDao; } // UserService 객체내에서 userDao 사용
}
2.2. Setter Injection
Setter Injection은 객체의 setter 메서드를 통해 의존성을 주입하는 방식입니다. 클래스의 속성에 해당하는 setter 메서드를 정의하고, 프레임워크가 해당 setter 메서드를 호출하여 의존성을 주입합니다.
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao; // UserService 객체 내에서 setter로 주입받은 userDao 사용
}
}
2.3. Interface Injection
Interface Injection은 의존성을 주입받을 인터페이스를 정의하는 방식입니다.
해당 인터페이스를 구현하는 클래스를 프레임워크가 주입합니다.
public interface UserDao { // 인터페이스 메서드 선언 }
public class UserService implements UserDao { // 인터페이스 메서드 구현 }
3. Spring IoC Containr
Spring Framework는 IoC와 DI를 기반으로 하는 Java 기반의 오픈 소스 애플리케이션 프레임워크입니다.
Spring IoC Container는 IoC를 구현한 것으로, 객체의 생성, 초기화, 의존성 주입, 생명주기 관리 등을 담당합니다.
Spring IoC Container는 크게 두 가지 방식으로 동작합니다:
3.1. XML 기반 설정 방식
기존의 XML 설정 파일을 사용하여 객체들의 의존성을 관리하는 방식입니다. 설정 파일에 객체들의 의존성과 속성을 정의하고, Spring IoC Container가 이를 읽어와 객체들을 생성하고 의존성 주입을 합니다.
applicationContext.xml
<bean id="userService" class="com.example.UserService">
<property name="userDao" ref="userDao" />
</bean>
<bean id="userDao" class="com.example.UserDao" />
3.2. Annotation 기반 설정 방식
Java의 Annotation을 사용하여 객체들의 의존성을 관리하는 방식입니다. 개발자는 코드 상에서 Annotation을 사용하여 객체를 정의하고, Spring IoC Container가 이를 스캔하여 객체들을 생성하고 의존성을 주입합니다.
Java Config
@Configuration
public class AppConfig {
@Bean public UserService userService() {
return new UserService(userDao());
}
@Bean public UserDao userDao() {
return new UserDao();
}
}
위의 예시에서는 AppConfig 클래스가 Spring IoC Container를 설정하는 Java Config 클래스입니다.
@Configuration 어노테이션은 설정 클래스임을 나타내고, @Bean 어노테이션을 사용하여 빈(Bean)을 정의합니다. userService 빈은 userDao 빈을 의존성 주입 받습니다.
4. Spring IoC Container의 장점
4.1. 메모리 절약
Spring IoC Container은 객체의 생성 관련하여 싱글톤을 지원하여 동일한 빈(Bean) 정의에 대해 단 하나의 객체 인스턴스만 생성하여 컨테이너 내에서 공유합니다. 이로 인해 객체 인스턴스가 중복 생성되지 않고, 메모리를 절약할 수 있습니다.
4.2. 성능 향상
싱글톤 객체는 한 번 생성된 이후에는 재사용되므로 객체 생성 비용이 줄어듭니다. 따라서 애플리케이션의 성능을 향상시킬 수 있습니다.
4.3. 의존성 관리의 용이성
Spring IoC Container는 객체들의 의존성을 주입해주므로, 개발자는 객체의 생성과 의존성 관리에 대해 신경쓰지 않아도 됩니다. 이를 통해 코드의 복잡성을 낮출 수 있습니다.
4.4. 객체의 라이프사이클 관리
Spring IoC Container는 객체의 생성, 초기화, 소멸과 같은 라이프사이클을 관리해주므로, 개발자는 객체의 라이프사이클을 직접 관리하지 않아도 됩니다. 이를 통해 객체의 라이프사이클에 대한 부담을 줄일 수 있습니다.
이렇게 Spring IoC Container을 사용하면, 객체 지향 프로그래밍의 장점을 최대한 활용할 수 있으며, 유지보수성이 높고 확장성이 좋은 애플리케이션을 개발할 수 있습니다. 스프링 프레임워크는 이러한 기능들을 지원하여 개발자가 보다 효율적으로 개발할 수 있도록 도와줍니다.
'Spring Framework' 카테고리의 다른 글
서비스 추상화와 트랜잭션 (0) | 2024.04.08 |
---|---|
Jdbc Template (0) | 2024.04.08 |
템플릿 메서드 패턴 & 콜백 패턴 (0) | 2024.04.08 |
junit5 - 단위 테스트 프레임워크 (0) | 2024.04.08 |
싱글톤 레지스트리 (0) | 2024.04.08 |