본문 바로가기
서버/스프링

스프링을 배우기 전에(2) - 빈(bean)

by 나이아카 2021. 3. 8.

 스프링을 배우기 전, 두 번째로 제가 할 일은 빈에 대해 이해하는 것입니다. 물론 제가 공부하는 순서대로 공부를 하시는 분이 많지는 않으실 것 같습니다. 사실 공부 방향은 책에서 참고하는게 좋고, 다들 각자가 생각하는 방향에 맞춰 공부를 하고 있다고 생각합니다.

 

 저는 일단 빈에 대한 개념을 알아야 스프링을 공부할 수 있다고 생각을 해서 빈에 대해서 먼저 작성해 보겠습니다.

 이 빈이라는 것은 java bean도 있고, spring bean도 있습니다. 근래 자바 빈의 의미가 퇴화되면서 빈의 개념이 점점 같은 의미로 수렴 중이라는 말이 많습니다. 그래서 특정 언어에서의 빈의 의미를 찾는다면 모를까, 더 이상 빈이 세부적인 내용만 다를 뿐 틀은 결국 동일하다고 생각할 수 있겠습니다.

 

자바 빈

 자바 빈의 경우는 간단하게 말해서 JavaBean 규격서에 맞춰 작성된 자바 클래스를 의미합니다. DTO와 VO가 자바 빈의 형태라고 볼 수 있습니다. 아래는 javaBean의 규격을 의미합니다.

 

  • 모든 클래스의 프로퍼티는 private이며 getter, setter 메소드로 제어한다.
  • 인자가 없는 public 생성자가 있어야 한다.
  • Serializable 인터페이스를 구현해야 한다.

 

스프링 빈

 

 스프링 빈의 경우는 Spring Ioc 컨테이너에 등록해 관리하는 객체를 의미합니다. @Bean 어노테이션을 통해서도 생성할 수 있습니다. 애플리케이션의 핵심을 이루는 객체이며 또한 컨테이너에 의해 인스턴스화, 관리, 생성이 됩니다.

 기본적으로 스프링 컨테이너에서 관리되는 빈은 특별한 설정을 하지 않는다면 싱글톤 타입이 됩니다.

 

Class Main() {
    fun main(args: Array<String>) { 
        val context = AnnotationConfigApplicationContext(AppContext::class.java)
        var class1 = context.getBean("data", TempClass::class.java)
        var class2 = context.getBean("data", TempClass::class.java)
        println("${class1 == class2}")
        context.close
    }
}

 이런식으로 작성된 예제에서 class1과 class2는 동일한 bean 객체(TempClass를 @Bean 어노테이션을 통해 미리 빈으로 설정)를 가지고 있다는 것을 확인할 수 있습니다. 

 

 getBean에서 "data"는 beanName을 의미합니다. beanName은 TempClass를 가지고 오는 메소드에서 @Bean(name= ["data"])을 선언하거나 <bean id="data" class="com.example.demo.TempClass" />처럼 빈을 생성할 때 직접 작성해줄 수 있습니다. 또는, class에서 @Component(name="data")를 이용해 생성해 줄 수도 있습니다.

 

 이러한 빈을 사용하는 코드를 보고나면 빈을 선언해주는 코드를 당연히 알고 넘어가야겠죠. 이러한 빈을 만들기 위한 대표적인 어노테이션이 두 개 있습니다.

 

@Bean vs @Component

 

 먼저 @Bean은 메소드 단계에서의 빈 생성을 하는 어노테이션입니다. @Bean을 이용하는 경우는 외부 라이브러리와 같이 class를 직접 건드릴 수 없는 코드를 이용할 때 사용하게 됩니다. 만약 어디선가 받아온 라이브러리의 class를 빈으로 만들고 싶다면 class에 Component를 달아줘야 하지만, read-only이기 때문에 불가능합니다. 그럴때 그 class를 가져오는 메소드를 만들어 @Bean을 통해 생성할 수 있습니다.

 

@Configuration
class TempClass {
    @Bean(name = ["external"])
    fun getExternalLibrary(): ExternalLibrary {
        return ExternalLibrary()
    }
}

 

 위의 코드처럼 외부라이브러리를 사용하는 코드에 @Bean 어노테이션을 통해 생성할 수 있습니다. 또한 @Bean을 사용하고 싶은 경우 class에서 @Configuration을 명시해주어야 합니다.

 

 

 @Component의 경우, 클래스 위에 직접 어노테이션을 달아 나머지 기능들을 스프링에게 위임하는 역할을 합니다.

 

@Component(Value = "data")
class TempClass {

    fun getData (): TempClass {
        return TempClass()
    }
}

 

 매우 간단하게 작성되었습니다. 이런식으로 두 어노테이션을 사용할 수 있습니다. 여기서 주의해야할 점은 beanName을 정확하게 입력해야 한다는 것입니다. 이름이 틀리면 NoSuchBeanDefinitionException이 발생할 수 있으니 말이죠.

 

 빈이라는 개념이 쉬운 것은 아니지만, 여러가지를 이미 알고 있는 가운데 배우는 과정이라면 그렇게 어려운 부분도 아닐것이라 생각합니다. 모든 프로그래밍은 연결점이 있으니 그것만 잘 찾는다면요. 이번 게시글에서는 아직 배우지 않은 DI에 관한 내용이 빠져 있어 부족한 부분이 많습니다. 그렇지만 조금이마나 쓸모 있는 정보가 있었으면 좋겠습니다.

댓글