2 분 소요


◆ Spring IoC(제어의 역전)와 Bean

Spring을 처음 공부하면 가장 많이 듣는 용어가 있다.

  • IoC(Inversion of Control)
  • DI(Dependency Injection)
  • Bean
  • Spring Container
  • @Autowired



객체를 직접 생성하는 일반 Java

일반 Java에서는 new를 사용하여 필요한 객체를 개발자가 직접 생성한다.

예를 들어 A 클래스와 B 클래스에서 각각 new MemberService()를 호출하면, 서로 다른 객체가 생성된다.

즉, 객체의 생성과 관리를 모두 개발자가 직접 담당한다.


Spring에서의 객체 생성

Spring에서는 개발자가 new를 사용하여 객체를 직접 생성하지 않는다.

대신 @Component, @Service, @Repository 등의 어노테이션이 붙은 클래스를 Spring이 실행될 때 찾아 객체를 자동으로 생성한다.

즉, 객체의 생성과 관리의 제어권이 개발자가 아닌 Spring으로 넘어간다.

이러한 개념을 IoC(Inversion of Control, 제어의 역전) 이라고 한다.




◆ Spring Container란?

Spring은 생성한 객체를 Spring Container라는 공간에 보관하고 관리한다. 쉽게 말하면 객체를 관리하는 창고라고 생각하면 된다.

Spring Container

┌────────────────────┐
│ MemberService 객체 │
└────────────────────┘

Spring은 실행되면서 필요한 객체를 생성한 뒤 이 창고에 보관한다.




◆ Bean이란?

Spring Container에 등록되어 관리되는 객체를 Bean이라고 한다.

즉,

  • Spring이 객체를 생성하고
  • Spring Container에 저장하여
  • 필요할 때마다 사용할 수 있도록 관리하는 객체

를 Bean이라고 한다.

따라서 Bean 등록이란 Spring이 객체를 생성하여 Spring Container에 저장하고 관리하는 것을 의미한다.




◆ @Autowired

Bean으로 등록된 객체는 필요한 곳에서 사용할 수 있다.

Spring에서는 @Autowired를 사용하여 Spring Container에 등록된 Bean을 자동으로 가져와 사용할 수 있다.

예를 들어

@RestController
public class MemberController {

    @Autowired
    private MemberService memberService;

}

를 작성하면

Spring은

MemberService가 필요하네.

↓

Spring Container에서 찾아본다.

↓

Bean이 있네.

↓

MemberController에 넣어준다.

즉,

Spring Container

┌────────────────────┐
│ MemberService Bean │
└────────────────────┘
        ▲
        │
        │
MemberController

처럼 자동으로 연결해 준다.

이 과정을

DI(Dependency Injection, 의존성 주입)

이라고 한다.




◆ @Autowired를 사용하면 같은 객체를 사용할까?

Spring Bean은 기본적으로 Singleton으로 생성된다. 즉, 하나의 객체를 생성한 뒤 필요한 클래스들이 함께 사용한다.

예를 들어

@Service
public class MemberService {

}

가 있다면

A와 B가

@Autowired
MemberService memberService;

를 사용해도

A
  \
   \
    MemberService
   /
  /
B

처럼 하나의 객체를 함께 사용된다.


그렇다면 하나의 객체를 여러 클래스에서 사용하면 데이터가 서로 섞이지 않을까?

만약 Service가 다음과 같이 멤버 변수에 데이터를 저장한다면 문제가 발생할 수 있다.

예를 들어

@Service
public class Calculator {

    private int result = 0;

    public void add(int n) {
        result += n;
    }

}

A가

calculator.add(10);

을 호출하면

result = 10

이 됩니다.

그런데

B가

calculator.add(20);

을 호출하면

result = 30

이 된다.

왜냐하면

같은 객체를 공유하기 때문이다.


그래서 Spring에서는 Service를 Stateless(상태가 없는 객체) 로 작성하는 것을 권장한다.

즉, 객체 내부에 데이터를 저장하지 않고 필요한 데이터는 메서드의 매개변수로 전달하여 처리한다.

@Service
public class Calculator {

    public int add(int a, int b) {

        return a + b;

    }

}

객체 안에는

result
price
member

같은 데이터를 저장하지 않는다.

필요한 데이터는

calculator.add(10, 20);

처럼 메서드의 매개변수(Parameter) 로 전달한다.

메서드가 종료되면 전달받은 데이터도 함께 사라진다.

이러한 객체를

Stateless(상태가 없는 객체)

라고 한다.




◆ Stateless가 중요한 이유

Spring에서는 하나의 Service 객체를 여러 사용자가 함께 사용한다.

하지만 Service 내부에 데이터를 저장하지 않기 때문에

사용자 A
      │
      ▼
MemberService
      ▲
      │
사용자 B

처럼 하나의 객체를 공유해도

각 요청의 데이터는 서로 영향을 주지 않는다.

태그: ,

카테고리:

업데이트:

댓글남기기