KOSA Spring - Spring이란? / Spring Container

채정윤·2025년 4월 16일

Spring

목록 보기
1/25

Spring

자바 기반의 경량 웹 프레임워크로, 효율적인 웹 애플리케이션 개발을 돕는 도구

POJO 기반으로 구성되어 있고, DIAOP, MVC 구조 등을 지원해서 유연하고 확장성 높은 개발이 가능

DI (Dependency Injection)

객체 간의 의존 관계를 외부에서 주입하는 방식

개발자가 직접 객체를 생성하지 않고, 필요한 객체를 Spring이 알아서 주입

유지보수성, 테스트 용이성이 좋아짐

// 예시
@Autowired
private UserService userService; // Spring이 주입해줌

스프링 컨테이너

"객체를 관리하고 의존성을 주입해주는 IoC(Inversion of Control) 컨테이너"

스프링에서는 개발자가 직접 객체를 new로 생성하고 의존성을 설정X

→ 객체를 대신 만들어주고, 서로 연결해주고, 잘 관리해주는 역할

💡 스프링 컨테이너가 하는 일

  1. 빈(Bean) 생성
    • 설정 파일이나 애노테이션을 바탕으로 객체를 만들어줌.
  2. 의존성 주입(Dependency Injection)
    • 필요한 의존 객체를 주입해줌. (@Autowired, 생성자 주입 등)
  3. 빈의 생명주기 관리
    • 초기화, 소멸 등의 과정을 관리함.
  4. AOP, 트랜잭션 등 기능 적용
    • 컨테이너가 빈에 대해 부가 기능을 붙여줌 (예: 로깅, 보안 등)

1. Constructor 방식

인터페이스 & 구현 클래스

public interface Dao {
    void insertBoard();
}

public class OracleDao implements Dao {
    public void insertBoard() {
        System.out.println("OracleDao InsertBoard() 호출");
    }
}

서비스 클래스

public class WriteService {
    private Dao dao;
    private MySql mySql;

    // 생성자 주입
    public WriteService(Dao dao, MySql mySql) {
        this.dao = dao;
        this.mySql = mySql;
    }

    public void insertService() {
        System.out.println("WriteService insertService() 호출");
        dao.insertBoard();
        mySql.printMySql();
    }
}

MySql 클래스

public class MySql implements Dao{
    public void insertBoard() {
        System.out.println("MySql InsertBoard() 호출");
    }
}

Main 실행 클래스

Resource resource = new ClassPathResource("applicationContext.xml");
BeanFactory factory = new GenericXmlApplicationContext(resource);
WriteService service = (WriteService)factory.getBean("writeService");
service.insertService();

XML 설정 파일 (applicationContext.xml)

<bean id="oracleDao" class="kosa.di.OracleDao"/>
<bean id="mySql" class="kosa.di.MySql"/>

<bean id="writeService" class="kosa.di.WriteService">
    <constructor-arg ref="oracleDao"/>
    <constructor-arg ref="mySql"/>
</bean>

2. Setter 방식으로 바꾸기

WriteService.java 수정

public class WriteService {
    private Dao dao;

    public void setDao(Dao dao) {
        this.dao = dao;
    }

    public void insertService() {
        System.out.println("WriteService insertService() 호출");
        dao.insertBoard();
    }
}

applicationContext.xml 수정

<bean id="oracleDao" class="kosa.di.OracleDao"/>
<bean id="mySql" class="kosa.di.MySql"/>

<bean id="writeService" class="kosa.di.WriteService">
    <property name="dao" ref="oracleDao"/>
    <property name="mySql" ref="mySql"/>
</bean>

3. Annotation 기반 DI 정리 (@Autowired 사용)

개념 요약

  • @Autowired를 사용하면 XML 설정 없이도 Spring이 자동으로 의존성 주입을 해줌.
  • @Component, @Service, @Repository , @Controller 어노테이션이 있는 클래스들 객체 생성
  • 데이터타입 기준으로 객체 자동 전달, 의존관계를 설정
  1. 인터페이스와 구현체는 그대로 사용
public interface Dao {
    void insertBoard();
}

@Repository
public class OracleDao implements Dao {
    public void insertBoard() {
        System.out.println("OracleDao InsertBoard() 호출");
    }
}

MySql.java

@Repository
public class MySql implements Dao{
    public void insertBoard() {
        System.out.println("MySql InsertBoard() 호출");
    }
}

WriteService.java (어노테이션 방식)

@Service
public class WriteService {
    @Autowired
    private Dao dao;

    public void insertService() {
        System.out.println("WriteService insertService() 호출");
        dao.insertBoard();
    }
}

💡 주입 방식:

  • @Autowired필드에 붙이면 자동 주입
상황결과
Dao 구현체가 1개@Autowired만 써도 주입 OK
Dao 구현체가 2개 이상@Autowired만 쓰면 오류 발생
이럴 땐?@Qualifier("bean이름")을 써서 명확히 지정

applicationContext.xml 수정 (annotation-scan)

<context:component-scan base-package="kosa.di" />

패키지 단위 객체들(클래스들) 일괄적으로 생성!
기본적으로 클래스이름이 id이다. ( 첫자는 소문자 )


⚖️ 어노테이션 기반 vs XML 기반 비교

항목XML 기반 DIAnnotation 기반 DI
설정 방법<bean> 태그로 명시적 설정클래스에 @Component 등 사용
유지보수설정 분리로 명확함코드와 설정이 가까워 관리 용이
가독성설정 파일 커질 수 있음코드 자체에서 구조 파악 가능
유연성다양한 설정을 외부에서 컨트롤 가능컴포넌트 스캔 범위 안에서만 적용됨
추천 상황외부 설정 관리 필요 시코드 기반 프로젝트, 간단한 프로젝트

📦 전체 구성 예시 (Annotation 완전 적용)

src/
└─ kosa/
   └─ di/
      ├─ Dao.java
      ├─ OracleDao.java      (→ @Repository)
      ├─ MySql.java          (→ @Component)
      ├─ WriteService.java   (→ @Service, @Autowired)
      └─ Main.java           (→ context load)
ApplicationContext context = new AnnotationConfigApplicationContext("kosa.di");
WriteService service = context.getBean(WriteService.class);
service.insertService();

AnnotationConfigApplicationContext 사용 시 applicationContext.xml 없이도 동작 가능.


4. Java Config 기반 DI (@Configuration + @Bean)

WriteService라는 객체를 생성하고, 그 안에서 사용하는 Dao 객체(여기선 OracleDao)도 함께 스프링이 관리하게 만드는 것.

  1. Factory 클래스 — 설정 클래스 (@Configuration + @Bean)
@Configuration
public class Factory {

	@Bean
	public Dao oracleDao() {
		return new OracleDao();
	}

	@Bean
	public WriteService writeService() {
		return new WriteService();
	}
}
  • @Configuration: 이 클래스는 설정 정보를 담은 클래스임을 의미.
  • @Bean: 스프링 컨테이너에 등록될 객체(Bean)를 정의.
    • oracleDao()OracleDao 객체를 Bean으로 등록.
    • writeService()WriteService 객체를 Bean으로 등록.

하지만 여기서 중요한 포인트WriteServiceDao를 직접 주입받고 있지 않다는 거야. 즉, WriteService 내부에서 Dao를 사용하는 방식이 명확하지 않으면 의존성 주입은 안 일어남.

  • 👉 참고) 이전에는 이렇게 해야 DI가 제대로 일어남:
    @Bean
    public WriteService writeService() {
        return new WriteService(oracleDao());
    }
    혹은 @Autowired 등을 이용해서 필드나 생성자에 명시적으로 의존성을 표시해야 함.
  1. Main 클래스 — 스프링 컨테이너 초기화
ApplicationContext factory = new AnnotationConfigApplicationContext(Factory.class);
WriteService service = (WriteService)factory.getBean("writeService");
service.insertService();
  • AnnotationConfigApplicationContext: 자바 기반 설정 파일(Factory.class)을 읽는 스프링 컨테이너.
  • getBean("writeService"): 스프링 컨테이너에 등록된 writeService Bean을 꺼냄.
  • insertService(): WriteService 객체의 메서드를 실행함.

📦 전체 구조 요약 그림 (의존관계)

Main
 └── ApplicationContext (Spring Container)
       ├── WriteService Bean
       │     └── Dao (OracleDao) Bean ← 이 부분이 제대로 연결되어야 함
       └── Dao (OracleDao) Bean

0개의 댓글