토비의 스프링 3.1 2장 (vol.1)

dev_butler·2026년 4월 16일

테스트가 왜 중요하지?

public void addAndGet() throws Exception{ 
    UserDao dao = new DaoFactory().userDao();
    
    User user = new User();
    user.setId("user1");
    
    dao.add(user);
    User user2 = dao.get("user1");
    
    assertEquals(user.getId(), user2.getId());
}

작성한 dao가 제대로 동작하는지 확인해야한다.

위 코드처럼 작성하면, add()과 get()을 통해 비교하게 된다.

JUnit

테스트를 자동화하기 위해 사용한다

대표적인 어노테이션으로 @Test, @Before 가 있다.

@Test
public void addAndGet() {
    ...
}

주요 특징을 살펴보면 “자동실행”, “결과 비교(assert)”, “반복가능” 이 있다

DI가 테스트에 미치는 영향

만약 DI가 없다면,

UserDao dao = new UserDao();

내부에서 DB를 직접 생성하기 때문에, 테스트용 DB로 바꾸기가 어렵다

하지만 DI가 있다면?

UserDao dao = new UserDao(new TestConnectionMaker());

테스트용 DB로 쉽게 교체가 가능하다!

스프링 컨테이너

이제 아래와 같은 기존 코드를

UserDao dao = new DaoFactory().userDao();

스프링 방식으로 변화시켜보자

ApplicationContext context =
    new AnnotationConfigApplicaionContext(DaoFactory.class);
    
UserDao dao = context.getBean("userDao", UserDao.class);

달라진 점을 살펴보자면, 객체를 직접 만들지 않고 스프링이 대신 만들어준다는 것을 확인할 수 있다!

즉, 스프링 컨테이너는 객체를 대신 만들어주고 관리해주는 시스템이라고 생각하면 된다

Bean

Bean이 무엇일까? 한마디로 표현하면 스프링 컨테이너가 관리하는 객체다.

@Bean
public UserDao userDao() {
    return new UserDao(connectionMaker());
}

ApplicationContext

이게 뭘까?

ApplicationContext는 Bean을 저장하고 꺼내주는 창구와 같은 역할을 하는 스프링 컨테이너의 대표 인터페이스다.

ApplicationContext context = 
    new AnnotationConfigApplicationContext(DaoFactory.class);
    
UserDao dao = context.getBean("userDao", UserDao.class); 

핵심 흐름을 살펴보자면

  1. 설정 클래스 등록
  2. Bean 생성
  3. DI 수행
  4. 필요할때 꺼냄

의 과정을 통하는 것을 확인할 수 있다.

Singleton

스프링의 기본 전략은 “객체를 하나만 만들어서 공유” 하는것이다.

이럴 위해서 싱글톤을 활용한다

UserDao dao1 = new UserDao();
UserDao dao2 = new UserDao();

위와 같은 일반적인 방식으로는 서로 다른 객체 2개가 생성된다.

UserDao dao1 = context.getBean(...);
UserDao dao2 = context.getBean(...);

하지만 이러한 방식대로 작성하면, dao1 == dao2 즉 같은 객체가 된다!

주의해야할 점도 있는데, 싱글톤은 상태를 가지면 위험하다.

→ 싱글톤 객체는 상태없는 (Stateless)구조로 만든다.

핵심 개념 관계정리

각 개념들의 관계를 정리해보자면,

스프링 컨테이너 → ApplicationContext (인터페이스) → Bean (객체) → 싱글톤으로 관리 → JUnit으로 검증

0개의 댓글