๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋ฐฑ์—”๋“œ/spring&springboot

[๋‚ด์ผ๋ฐฐ์›€์บ ํ”„_Spring Boot ์ˆ™๋ จ์ฃผ์ฐจ] Bean

by alswlfl 2026. 6. 26.

Bean์„ ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•

@ComponentScan์ด @Component๋ฅผ ์Šค์บ”ํ•ด ์ž๋™์œผ๋กœ Bean์„ ๋“ฑ๋กํ•ด์คŒ. ์ผ๋ฐ˜์ ์œผ๋กœ 3 Layer Annotation์ธ @Controller, @Service, @Repository๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž๋™์œผ๋กœ Bean์„ ๋“ฑ๋กํ•ด์ฃผ๋Š”๊ฒŒ ์ข‹์Œ

→ ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก Bean ์ž๋™ ๋“ฑ๋ก์„ ์‚ฌ์šฉํ•˜๋ฉด ํŽธ๋ฆฌํ•จ

 

ํ•˜์ง€๋งŒ, ๊ธฐ์ˆ ์ ์ธ ๋ฌธ์ œ(๊ธฐ์ˆ  ์ง€์› Bean)๋‚˜ ๊ณตํ†ต์ ์ธ ๊ด€์‹ฌ์‚ฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด๋“ค์€ ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ(ex: ๊ณตํ†ต ๋กœ๊ทธ ์ฒ˜๋ฆฌ, ๊ฐ™์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ)

 

ex) ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•”ํ˜ธํ™”ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ Bean์œผ๋กœ ์ˆ˜๋™ ๋“ฑ๋กํ•˜๊ธฐ

1. Bean์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์„ ์–ธ
2. ๊ทธ ๋ฉ”์„œ๋“œ ์œ„์— @Bean ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€
3. Bean์„ ๋“ฑ๋กํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์†ํ•ด ์žˆ๋Š” Class ์œ„์— @Configuration ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€ํ•˜๋ฉด
4. Spring Server๊ฐ€ ๋œฐ ๋•Œ Spring IoC Container์— Bean์œผ๋กœ ์ €์žฅ๋จ

package com.sparta.springauth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

// Bean์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์„ ์–ธ
// ๊ทธ ๋ฉ”์„œ๋“œ ์œ„์— @Bean ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€
// Bean์„ ๋“ฑ๋กํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์†ํ•ด ์žˆ๋Š” Class ์œ„์— @Configuration ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€ํ•˜๋ฉด
// Spring Server๊ฐ€ ๋œฐ ๋•Œ Spring IoC Container์— Bean์œผ๋กœ ์ €์žฅ๋จ
@Configuration
public class PasswordConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        // BCrypt๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•”ํ˜ธํ™”ํ•ด์ฃผ๋Š” Hash ํ•จ์ˆ˜๋กœ, Password๋ฅผ Encode ํ•ด์คŒ
        return new BCryptPasswordEncoder();
    }
}

 

ํ…Œ์ŠคํŠธ ์ˆ˜ํ–‰

package com.sparta.springauth;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.password.PasswordEncoder;

@SpringBootTest
public class PasswordEncoderTest {

    @Autowired
    PasswordEncoder passwordEncoder; // ๋นˆ ์ฃผ์ž… ๋ฐ›์•„์˜ด

    @Test
    @DisplayName("์ˆ˜๋™ ๋“ฑ๋กํ•œ passwordEncoder๋ฅผ ์ฃผ์ž… ๋ฐ›์•„์™€ ๋ฌธ์ž์—ด ์•”ํ˜ธํ™”")
    void test1() {
        String password = "Robbie's password";

        // ์•”ํ˜ธํ™”
        String encodePassword = passwordEncoder.encode(password);
        System.out.println("encodePassword = " + encodePassword);

        String inputPassword = "Robbie";

        // ํ•ด์‹œ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ•ด์‹ฑํ•œ ๊ฐ’์„ ๋น„๊ต
        // passwordEncoder.matches(์ž…๋ ฅ ๋ฐ›์€ ๋ฌธ์ž์—ด, ์•”ํ˜ธํ™”ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ)
        boolean matches = passwordEncoder.matches(inputPassword, encodePassword);
        System.out.println("matches = " + matches); // ์•”ํ˜ธํ™”ํ•  ๋•Œ ์‚ฌ์šฉ๋œ ๊ฐ’๊ณผ ๋‹ค๋ฅธ ๋ฌธ์ž์—ด๊ณผ ๋น„๊ตํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— false
    }
}

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ


๊ฐ™์€ ํƒ€์ž…์˜ Bean์ด 2๊ฐœ๋ผ๋ฉด?

Food ์ธํ„ฐํŽ˜์ด์Šค

package com.sparta.springauth.food;

public interface Food {
    void eat();
}

 

Chicken ํด๋ž˜์Šค

package com.sparta.springauth.food;

import org.springframework.stereotype.Component;

@Component
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("์น˜ํ‚จ์„ ๋จน์Šต๋‹ˆ๋‹ค.");
    }
}

 

Pizza ํด๋ž˜์Šค

package com.sparta.springauth.food;

import org.springframework.stereotype.Component;

@Component
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("ํ”ผ์ž๋ฅผ ๋จน์Šต๋‹ˆ๋‹ค.");
    }
}

 

  • ์ธํ„ฐํŽ˜์ด์Šค ํด๋ž˜์Šค ์ƒ์„ฑ ํ›„, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ตฌํ˜„์ฒด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“  ๋‹ค์Œ์— Bean์œผ๋กœ ๋“ฑ๋ก(@Component, @Controller, ๋“ฑ๋“ฑ)ํ•˜๋ฉด ํ•ด๋‹นํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋„ Bean์œผ๋กœ ๋“ฑ๋ก๋จ

Food ์ธํ„ฐํŽ˜์ด์Šค์˜ Bean ๋“ฑ๋ก

  • ์ฆ‰, ํ•˜๋‚˜์˜ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๋‘ ๊ฐœ์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๋Š”๊ฑด ํฐ ๋ฌธ์ œ๋Š” ์—†์Œ

  • ์ž๋™ ์ฃผ์ž…์„ ํ•˜๋ ค๊ณ  ํ•  ๋•Œ, Food๋ผ๋Š” ํƒ€์ž…์œผ๋กœ Bean์ด ํ•œ ๊ฐœ์ด์ƒ์ด์–ด์„œ ์—๋Ÿฌ ๋ฐœ์ƒํ•จ
  • ์ฆ‰, Food ํ•„๋“œ์— Bean์„ ์ฃผ์ž…์„ ํ•ด์•ผ ํ•˜๋Š”๋ฐ ๊ฐ™์€ ํƒ€์ž…์˜ Bean ๊ฐ์ฒด๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ์ด๋ผ ์–ด๋–ค Bean์„ ๋“ฑ๋กํ•ด ์ค˜์•ผ ํ• ์ง€ ๋ชจ๋ฅธ๋‹ค๋Š” ์˜๋ฏธ

๊ฐ™์€ ํƒ€์ž…์˜ Bean์ด 2๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ, ์ž๋™ ์ฃผ์ž… ์—๋Ÿฌ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

1. ๋“ฑ๋ก๋œ Bean์˜ ์ด๋ฆ„ ๋ช…์‹œ

๊ธฐ๋ณธ์ ์œผ๋กœ @Autowired๋Š” Bean DI๋ฅผ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Food๋ผ๋Š” ํƒ€์ž…์œผ๋กœ Bean์„ ์ฐพ์Œ → ํƒ€์ž…์œผ๋กœ ์ฐพ์„ ๋•Œ Bean์ด 2๊ฐœ์ธ ๊ฒƒ์„ ํ™•์ธ → ๊ทธ ๋‹ค์Œ ์ด๋ฆ„์œผ๋กœ Bean์„ ์ฐพ์Œ(chicken, pizza)

@SpringBootTest
public class BeanTest {

    @Autowired
    Food pizza; // Bean ์ฃผ์ž… ๋ฐ›๊ธฐ

    @Autowired
    Food chicken; // Bean ์ฃผ์ž… ๋ฐ›๊ธฐ
}

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

2. @Primary ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

๊ฐ™์€ ํƒ€์ž…์˜ Bean์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๋”๋ผ๋„ ์šฐ์„ ์ ์œผ๋กœ @Primary๊ฐ€ ์ ์šฉ์ด ๋˜์–ด์žˆ๋Š” Bean ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•ด์คŒ

@Component
@Primary
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("์น˜ํ‚จ์„ ๋จน์Šต๋‹ˆ๋‹ค.");
    }
}
@SpringBootTest
public class BeanTest {

    @Autowired
    Food food; // Bean ์ฃผ์ž… ๋ฐ›๊ธฐ

    @Test
    @DisplayName("ํ…Œ์ŠคํŠธ")
    void test1() {
        food.eat();
    }
}

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

3. @Qualifier ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

@Component
@Qualifier("pizza")
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("ํ”ผ์ž๋ฅผ ๋จน์Šต๋‹ˆ๋‹ค.");
    }
}
@SpringBootTest
public class BeanTest {

    @Autowired
    @Qualifier("pizza")
    Food food; // Bean ์ฃผ์ž… ๋ฐ›๊ธฐ

    @Test
    @DisplayName("ํ…Œ์ŠคํŠธ")
    void test1() {
        food.eat();
    }
}

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

๏นก๊ฐ™์€ ํƒ€์ž…์˜ Bean๋“ค์— @Qualifier๋ž‘ @Primary๊ฐ€ ๋™์‹œ์— ๊ฑธ๋ ค ์žˆ๋‹ค๊ณ  ํ•˜๋ฉด, @Qualifier ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋” ๋†’์Œ! ํ•˜์ง€๋งŒ, Qualifier๋Š” ์ฃผ์ž… ๋ฐ›๊ณ ์ž ํ•˜๋Š” ๊ณณ์— ๋ฐ˜๋“œ์‹œ @Qualifier๋ฅผ ๋ฐ˜๋“œ์‹œ ๋ถ™์—ฌ์ค˜์•ผ ํ•จ

  • ๋ฒ”์šฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” Bean ๊ฐ์ฒด์—๋Š” @Primary๋ฅผ ์‚ฌ์šฉ
  • ์ง€์—ญ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” Bean ๊ฐ์ฒด์—๋Š” @Qualifier๋ฅผ ์‚ฌ์šฉ