개발하면서/타인글보면서

Spring Framework 6.2 문서 읽고 이해하기 ... IOC Container (1)

오산돌구 2025. 2. 9. 16:00

현재 정산 백엔드 직군으로 일하고 있고 사용하는 기술은 Spring Boot와 Kotlin이다.

 

(사람마다 깊이에 대한 기준은 다르지만) Spring을 깊은 이해 없이 활용 가능한 정도로 공부한 후

사용하다가 문제 생기면 그때 필요한 부분만 알아가는 식이였다.

IOC Container라는 게 있어서 POJO + Meta정보를 이용해서 Bean을 생성하고 lifecycle도 관리해 주고,
Reflection을 이용해서 DI 해준다 정도... 아는 것도 모르는 것도 아닌 두리뭉실한 느낌

 

이를 반대로 말하면 문제없는 영역은 잘 모른다는 게 문제다.

 

Spring Boot가 알아서 해주는 게 많아 개발자는 비즈니스 로직에만 집중한다는 장점이 있지만
프로젝트가 커지다 보면 비즈니스 로직만 알아서는 부족함을 느낀다. 개발 속도가 느려진다.

지금 상황이 그렇다.

 

코드를 봐야겠다고 결심하게 된 결정적인 계기는
지금 프로젝트를 리팩토링 하려고 테스트 코드 작성하는데 감으로만 알고 있던 걸로는 진행이 안 됐다.

더 이상 구글 검색결과에 나온 방법들로는 해결되지 않았다.

 

내가 생각한 개발자의 가장 큰 장점은 공개되어 있는 코드들이 많아

시간과 노력을 투자한다면 내부 동작 원리를 알 수 있다는 점이다.

 

그래서 당장 업무에 도움 될지를 상상하며 내부 동작을 알아보려고 한다.

 

첫 시작은

Spring framework 6.2!!

나의 지적호기심 채우려고 너무 깊게 알아가는 모습을 항상 경계하자.


Core Technologies / The IoC Container 

IOC는 Inversion of Control의 약자로 제어를 내부가 아닌 외부에서 한다는 개념이고

DI는 생성자, property, factory method, setter method 등을 이용하여 의존 관계에 있는 객체를 주입받는 걸 말한다.

 

IoC 컨테이너는 두 개 패키지가 기본이고 `org.springframeowrk.beans`, `org.springframeowrk.context`

beans 패키지는 BeanFactory interface를, context 패키지는 ApplicationContext interface를 root로 보면 된다.

 

BeanFactory는 모든 유형의 객체를 관리할 수 있는 메커니즘을 제공하고,
ApplicationContext는 BeanFactory의 하위 interface로 아래와 같은 추가 기능을 제공한다.

  • Spring AOP 기능과 쉬운 연동
  • i18n 관리
  • 이벤트 메시지 관리
  • 웹에서 사용하기 위한 WebApplicationContext 같은 계층별 Context

 

BeanFactory는 프레임워크 설정과 기본 기능을 제공하고, ApplicationContext는 추가로 엔터프라이즈 기능을 제공한다.

이후 Spring IoC Container 설명 ApplicationContext으로 진행한다.
※ BeanFactory에 대한 자세한 내용은 The BeanFactory API 읽을 때 알아보겠습니다.

 

Container Overview

Spring IoC Container = ApplicationContext interface 느낌.

bean의 인스턴스화, 설정, 조합등을 책임지는데 메타정보를 읽어 처리한다.

다양한 ApplicationContext interface 구현체가 있는데 그중에 

AnnotationConfigApplicationContext, ClassPathXmlApplicationContext 가 단독으로 생성 가능하다.

 

비즈니스 로직이 있는 객체(POJO)와 메타정보를 가져와서 ApplicationContext에서 즉시 사용가능한 Bean 만들어준다.

 

 

Configuration Metadata

메타정보는 다양한 방식으로 정의할 수 있는데 대부분의 개발자들은 주로 Java-based configuration 방식을 사용한다.

  • Annotation-based configuration: 애플리케이션 컴포넌트 클래스에 annotation을 사용해서 bean을 정의하는 방식
  • Java-based configuration: 애플리케이션과 별개의 클래스에 bean을 정의하는 방식

XML 방식도 있는데 XML에 <beans/>를 적고 하위에 <bean/>을 적어서 bean을 정의한다.

※ <import /> element를 이용해서 다른 xml파일에 정의한 bean 내용을 가져올 수도 있다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- services -->
    <bean id="petStore" class="com.tistory.dol9.context.support.PetStore"/>
</beans>

 

ClassPathXmlApplicationContext 생성자 argument로 Java classpath 기준 xml을 넘겨주면 IoC container가 생성된다.

XML 경로는 상대경로 대신 절대경로 사용을 권장한다.

추가로 GenericApplicationContext와 reader delegate를 이용해서 container를 생성할 수도 있다.

// create and configure beans using ClassPathXmlApplicationContext
val context: ApplicationContext = ClassPathXmlApplicationContext(SINGLE_CONTEXT)

val service: PetStore = context.getBean("petStore", PetStore::class.java)

// create and configure beans using GenericApplicationContext
val context = GenericApplicationContext()
val beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(PetStore::class.java).beanDefinition
context.registerBeanDefinition("petStore", beanDefinition)
context.refresh()

val service: PetStore = context.getBean("petStore", PetStore::class.java)
val userList = service.userName


// PetStore
class PetStore {
	val userName: List<String>
		get() = mutableListOf("dol9", "dol10")
}

 

위에 작성한 XML과 코드

https://github.com/kgcrom/learn-something/commit/e95a391445213127ff9eb6e7017b7c9a833d98bc

 

Spring Framework 6.2 git clone 한 뒤 코드를 봤지만 이해 안 되는 게 참 많았다.

문서 Resource까지 보면서 대강 분위기 익히고 코드를 봐야겠다.