[Spring] 왜 굳이 spring bean을 사용할까?

민지·2024년 2월 13일

Spring

목록 보기
6/6

이번 포스팅에서는 스프링 bean 사용방법과 왜 굳이 spring bean을 사용하는지, 그리고 @Autowired 존재 이유에 대해 정리해보겠다.

(글에서 자주 등장하는 TIL 참고 링크는 제일 하위에 작성해두었다.)

spring에서 java bean 만드는 2가지 방법

spring에서 java bean을 만드는 방법은 클래스에 @Component를 붙여 자동으로 만드는 방법과, 클래스에는 @Configuration을 메서드에는 @Bean을 붙여 수동으로 자바 빈을 만드는 2가지 방법이 있다.

각각의 예제를 간단히 살펴보자.

수동 - 클래스에 @Configuration, 메서드에 @Bean

@Configuration
public class App03GamingSpringBeans {

    @Bean
    public GameConsole game() {
        var game = new PacmanGame();
        return (game);
    }

    @Bean
    public GameRunner gameRunner(GamingConsole game){
        var gameRunner = new GameRunner(game);
        return (gameRunner);
    }

    public static void main(String[] args){
        var context = new AnnotationConfigApplicationContext(pp03GamingSpringBeans.class);

        System.out.println(context.getBean(GamingConsole.class));

        context.getBean(GamingConsole.class).up();

        context.getBean(GameRunner.class).run();
    }
}

자동 - 클래스에 @Component

위 수동으로 자바 빈을 만들었던 예제코드에서 코드를 더 지워 간결하게 만들 것이다.

이때 자동으로 스프링이 자바 빈을 만들 수 있는 이유는 컴포넌트 스캔에 있다.

스프링 프레임워크가 알아서 런타임 때 @ComponentScan의 기본 패키지 및 하위 패키지에 @Component로 등록된 컴포넌트를 스캔해 찾고, 자신이 관리할 스프링 빈 클래스로 등록해놓기에, 객체를 new 연산자없이도 자동으로 만들 수 있는 것이다.

package com.in28minutes.learnspringframework.game;

@Component
public class PacmanGame implements GamingConsole {

	public void up() {
		System.out.println("Up");
	}

	public void down() {
		System.out.println("Down");
	}

	public void left() {
		System.out.println("Left");
	}

	public void right() {
		System.out.println("Right");
	}

}

// Configuration 클래스의 gameRunner 클래스를 지우자.
package com.in28minutes.learnspringframework;

@Configuration
public class App03GamingSpringBeans {

	//@Bean
	//public GameRunner gameRunner(GamingConsole game) {
	//	var gameRunner = new GameRunner(game);
	//	return (gameRunner);
	//}

	public static void main(String[] args) {

		var context = new AnnotationConfigApplicationContext(App03GamingSpringBeans.class);

		System.out.println(context.getBean(GamingConsole.class));
		context.getBean(GamingConsole.class).up();

		context.getBean(GameRunner.class).run();
	}

}

// gameRunner클래스에 자동 관리를 위해 @Component 어노테이션 추가
// 참고로, 패키지 경로는 동일해서 별다른 설정이 필요없었다.
@Component
public class GameRunner {

	private GamingConsole game;

	public GameRunner(GamingConsole game) {
		this.game = game;
	}

	public void run() {
		System.out.println("run : " + game);

		game.up();
		game.down();
		game.left();
		game.right();

	}

}

이렇게 스프링 프레임워크가 PacmanGame과 GameRunner에 빈을 자동으로 생성하도록 @Component 어노테이션을 사용했다.

그 결과, @Configuration클래스 코드가 굉장히 간단하졌다. 수동으로 new 연산자로 자바객체를 직접 생성하지 않아도 되었다.

또한, 스프링은 런타임 시, 올바른 패키지를 스캔해 Component을 찾고, 객체를 생성하고, 이를 자동으로 추가해 전체 어플리케이션을 잘 작동시켜준다.


이처럼, 스프링에서 자바 빈을 만드는 2가지 방법에 대해 살펴보았다. 하지만 왜 굳이 스프링 프레임워크에서 자바 빈을 만들어 사용하는 것일까?

굳이 스프링에서 자바 빈을 만드는 이유

결론부터 말하자면, 동일한 역할을 수행하는 객체를 여러 번 만들지 않아도 되기 때문이다. 또한 주로 스프링 빈은 DI(의존성 주입)에서 사용된다.

게시판 웹사이트가 있다고 해보자. 해당 웹사이트에서는 login기능, add-article 기능, delete-article 기능 등등이 있다고 하자.

만일 스프링의 Bean객체를 사용하지 않는다면, 각각의 객체마다 new 연산을 수행해 객체를 만들어야 한다. 또한 동일한 객체가 아니기에 서로 가진 정보도 다르고, 메모리는 또 메모리대로 쓰는 등의 비효율적인 문제가 생긴다.

하지만, 싱글톤 - 특정 클래스의 동일 인스턴스가 생길 때마다 "동일한" 메모리의 인스턴스 사용 (TIL - 1.Spring - 2.2 참고) - 의 특징을 가진 스프링의 Bean을 사용한다면, 동일한 역할을 수행하는 객체를 여러 번 만들지 않아도 된다! 딱 1번 만들어두면, 동일한 역할의 인스턴스일 경우 앞서 만들어둔 자바 빈만 계속 재활용한다!

다시 말해, 스프링 컨테이너가 빈을 관리하므로 싱글톤 패턴을 적용시켜 동일한 인스턴스를 여러 곳에서 공유해 사용할 수 있다는 것이다. 훨씬 효율적이다!

또한, @Autowired 어노테이션을 사용해, Bean에 등록된 객체를 사용할 수 있게 된다. @Autowired가 없었다면 또 객체별로 new 연산자를 이용해 각각의 객체를 모두 초기화해야 했는데, 주로 생성자에서의 @Autowired를 사용해, 그럴 필요가 없어졌다. (TIL - 1. Spring - 3.3과 3-4 참고!)

따라서, 스프링을 사용하는 이유 중 하나는, 객체의 관리와 의존성 주입을 스프링 컨테이너에 위임해, 개발자가 보다 효율적으로 어플리케이션을 개발할 수 있도록 하기 위함이다.

출처 및 참고

출처 : https://cnu-jinseop.tistory.com/36

TIL : 2-2 and 3-1 정리 ; https://github.com/minjikimkim2222/TIL/blob/main/Spring-and-Springboot/1. Spring/2-2. Spring 개념 - Spring 컨테이너%2C 스프링 컨테이너의 생성과 빈 등록 과정.md

profile
배운 내용을 바로바로 기록하자!

0개의 댓글