2024.07.17 - [Spring] - [Spring] 스프링 빈과 의존관계-컴포넌트 스캔으로 의존관계 설정(1)

 

[Spring] 스프링 빈과 의존관계-컴포넌트 스캔으로 의존관계 설정(1)

📍스프링 빈과 의존관계  이번 시간에는 저번 포스팅에서 진행했던 유저 관리 로직을 프론트엔드와 같이 엮어 보려고 한다. 이때, 필요한것은 유저 컨트롤러와 뷰 템플릿이다. 그럴려면, 멤버

jghdg1234.tistory.com

 

이전 포스팅에는 어노테이션을 활용해 자동으로 의존 관계를 설정 해주었다. 다시 기억해 보자면... Raw 자바 코드는 Spring인지 아닌지 알 수 없으므로 @Service라는 어노테이션을 추가 해야하고, 또한, 의존성 주입을 위해 생성자 위에 @Autowired 라는 어노테이션을 추가 해야하고, 저장소에는 @Repository라는 어노테이션 등을 추가 해야한다.

 

그렇지만 이번에는, 어노테이션이 아니라 자바 코드로 직접 스프링 빈을 등록하는 방법을 알아보자.

 

먼저, src/main/java/Jihoo.hello_spring 에다가 SpringConfig라는 파일을 하나 만들어 준다.

package Jihoo.hello_spring;

import Jihoo.hello_spring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService();
    }
}

 

이렇게 작성이 되면, 스프링이 시작될때 @Configuration 어노테이션과 그 안의 @Bean을 읽고, 스프링 빈에 객체를 등록 해준다.

하지만 MemverService의 생성자는 memberRepository를 인자로 받는다. 그 말은 memberRepository도 스프링 빈에 등록이 되어야 한다. 아래와 같이 memberRepository도 빈으로 생성을 해준 후, memberService의 파라미터로 던져준다.

package Jihoo.hello_spring;

import Jihoo.hello_spring.repository.MemberRepository;
import Jihoo.hello_spring.repository.MemoryMemberRepository;
import Jihoo.hello_spring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}

 

- MemberService와 MemberRepository를 모두 스프링 빈에 등록 한 후, 스프링 빈에 등록되어있는 memberRepo를 memberService에 넣어준다.

이렇게 하면 이전 포스팅에서 본 그림과 같이 서로 의존 관계가 형성이 되었다. 의존 관계는 실행중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다.

 

다시 모든 내용을 정리하자면....

 

스프링 빈 (Spring Bean)이란?

스프링 빈은 스프링 애플리케이션 컨텍스트가 관리하는 자바 객체이다. 스프링 빈은 스프링 컨테이너에 의해 생성되고 관리된다. 스프링 프레임워크는 의존성 주입(Dependency Injection)을 통해 빈들의 생명주기를 관리하며, 애플리케이션의 컴포넌트 간 결합도를 낮추어 유지보수성과 테스트 용이성을 높여준다.

스프링에서는 의존성을 주입하는 방식으로 두 가지 주요 접근 방법이 있다:
1. 컴포넌트 스캔 방식 (Component Scan)
2. 직접 자바 코드로 설정하는 방식 (Java Configuration)

1. 컴포넌트 스캔 방식 (Component Scan)

스프링의 컴포넌트 스캔은 클래스에 어노테이션을 붙여 스프링 빈으로 등록하는 방식이다.

주로 `@Component`, `@Service`, `@Repository`, `@Controller`와 같은 어노테이션을 사용한다.

장점:
- 코드가 간결해지고, 설정이 쉽다.
- 클래스 파일만으로 구성 요소를 쉽게 식별할 수 있다.

단점:
- 자동으로 스캔되기 때문에 클래스 경로 내의 모든 어노테이션이 스캔되어 빈으로 등록된다.
- 어노테이션을 사용하므로 코드의 가독성이 떨어질 수 있다.

예제:

import org.springframework.stereotype.Service;

@Service
public class MemberService {
    // 서비스 로직
}


위 예제에서 `@Service` 어노테이션을 사용하여 `MemberService` 클래스가 스프링 빈으로 등록된다.

설정:
스프링 부트에서는 `@SpringBootApplication` 어노테이션이 포함된 클래스가 있는 패키지와 그 하위 패키지를 자동으로 스캔한다.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloSpringApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloSpringApplication.class, args);
    }
}


2. 직접 자바 코드로 설정하는 방식 (Java Configuration)

이 방식은 자바 클래스를 사용하여 스프링 빈을 명시적으로 등록하는 방식이다. 주로 `@Configuration`과 `@Bean` 어노테이션을 사용한다.

장점:
- 빈의 생성과 설정을 명확하게 제어할 수 있다.
- 코드 기반 설정으로 더 많은 유연성과 가독성을 제공한다.

단점:
- 설정 클래스와 메서드를 따로 작성해야 하므로 설정 파일이 많아질 수 있다.
- 컴포넌트 스캔에 비해 초기 설정 작업이 더 많다.

예제:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService();
    }
}


위 예제에서 `@Configuration` 어노테이션이 붙은 `AppConfig` 클래스는 스프링 설정 클래스임을 나타내며, `@Bean` 어노테이션을 사용하여 `memberService` 메서드가 반환하는 객체를 스프링 빈으로 등록한다.

설정:
스프링 부트에서 자바 설정 클래스를 사용하려면, 애플리케이션 시작 클래스에서 `@SpringBootApplication` 어노테이션과 함께 사용된다.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;

@SpringBootApplication
@Import(AppConfig.class) // Java 설정 클래스 임포트
public class HelloSpringApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloSpringApplication.class, args);
    }
}



의존성 주입 방식의 차이점

컴포넌트 스캔 방식:
- 주로 어노테이션(`@Component`, `@Service`, 등)을 사용
- 설정이 간단하고 코드가 간결해짐
- 자동으로 스캔하여 빈을 등록
- 자동 스캔의 범위를 제어하기 어려움
- 스프링 부트의 `@SpringBootApplication`이 자동 스캔을 수행

자바 코드 설정 방식:
- 주로 자바 설정 클래스(`@Configuration` + `@Bean`)을 사용
- 설정과 생성을 명확하게 제어할 수 있음
- 명시적으로 빈을 등록
- 설정 파일을 통해 관리 범위를 명확히 할 수 있음
- 설정 클래스를 `@Import`를 통해 명시적으로 포함

작은 프로젝트에서는 컴포넌트 스캔 방식을, 복잡한 설정이 필요한 경우에는 자바 코드 설정 방식을 사용하는 것이 일반적이다.

 

 

+ Recent posts