Backend/๐ŸŒฑ Spring

[Spring]Spring Bean

HS0601 2025. 7. 28. 10:32
๋Œ€์ฒด Bean์ด ๋ญ๊ณ  ์™œ ํ•„์š”ํ•œ๋ฐ???

 

 

๋นˆ(Bean)์ด๋ž€?
์Šคํ”„๋ง์ด ๋Œ€์‹  newํ•ด์„œ ์ƒ์„ฑํ•˜๊ณ  ์•ฑ ์ „๋ฐ˜์—์„œ ์“ธ ์ˆ˜ ์žˆ๋„๋ก ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ๊ฐ์ฒด

๋ฆฌ์•กํŠธ๋กœ ๋น„์œ ํ•ด ๋ณด์ž๋ฉด,
๋นˆ(Bean) = Context Provider์— ๋“ฑ๋ก๋œ ๊ฐ’.
์Šคํ”„๋ง์ด Provider์—ญํ• ์„ ํ•ด์„œ ๋นˆ์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘๊ณ  ์–ด๋””์„œ๋“  @Autowired (โ‰’useContext)๋กœ ๊บผ๋‚ด๋Š” ๊ตฌ์กฐ!


๋นˆ(Bean)์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹ฑ๊ธ€ํ†ค(ํ•œ ๋ฒˆ๋งŒ ๋งŒ๋“ค์–ด์ ธ์„œ ์ „์ฒด ๊ณต์œ )

๋นˆ(Bean)์— ๋“ค์–ด๊ฐˆ ๊ฐ’์€ new ํด๋ž˜์Šค()๋กœ ๋งŒ๋“  ๊ฐ์ฒด(=์ธ์Šคํ„ด์Šค)์ด๋‹ค.
์ฆ‰, ํด๋ž˜์Šค๋Š” ์„ค๊ณ„๋„์ด๊ณ , ๊ทธ ์„ค๊ณ„๋„๋กœ ๋งŒ๋“  ๊ฐ์ฒด๊ฐ€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— Bean์œผ๋กœ ๋“ค์–ด๊ฐ„๋‹ค.
์ด ๊ฐ์ฒด๋Š” ์Šคํ”„๋ง์ด ๋Œ€์‹  new ํ•ด์„œ ๋งŒ๋“ค์–ด์ฃผ๊ณ , ์•ฑ ์ „์ฒด์—์„œ ๊บผ๋‚ด์“ธ ์ˆ˜ ์žˆ๊ฒŒ ๊ด€๋ฆฌํ•ด์ค€๋‹ค.

 

 

์™œ ๊ตณ์ด ์Šคํ”„๋ง์ด ๊ฐ์ฒด๋ฅผ ๋Œ€์‹  ๋งŒ๋“ค๊ณ  ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•˜๋Š”๋ฐ

 

 

1. new๋ฅผ ์•ˆ์จ๋„ ๋จ.(์ž๋™์—ฐ๊ฒฐ)

์˜ˆ๋ฅผ๋“ค๋ฉด React์—์„œ props๋‚ด๋ ค์ฃผ๋Š” ๊ตฌ์กฐ๊ฐ€ ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™๋‹ค๋ฉด

<App>
  <Page user={user}>
    <Profile user={user} />
  </Page>
</App>

 

๋ฌธ์ œ๋Š” ์ค‘๊ฐ„ ์ปดํฌ๋„ŒํŠธ(Page)๋Š” user์•ˆ์”€, ๊ทธ๋Ÿผ์—๋„ ๋‚ด๋ ค์ค˜์•ผ ํ•จ

ํ•ด๊ฒฐ์ฑ…์œผ๋กœ๋Š” Context์จ์„œ ์–ด๋””์„œ๋“  ๋ฐ”๋กœ ๊บผ๋‚ด์“ฐ๊ธฐ.

 

 

 

๊ทธ๋ž˜์„œ Spring์—์„  ๋นˆ์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ฃผ๊ณ  ์ž๋™์œผ๋กœ ์ฃผ์ž…ํ•˜๋Š” ๊ตฌ์กฐ๋‹ค.

@Service
public class ProfileService {
    private final UserRepository userRepository;

    // ์ƒ์„ฑ์ž์— @Autowired → ์Šคํ”„๋ง์ด ์•Œ์•„์„œ ๋นˆ์„ ์—ฐ๊ฒฐํ•ด์คŒ
    public ProfileService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

๊ฒฐ๊ณผ๋กœ๋Š” ์ง์ ‘ new UserRepository() ์•ˆํ•ด๋„ ๋จ.

์Šคํ”„๋ง์ด ๋Œ€์‹  ๋งŒ๋“ค์–ด์„œ ๋„ฃ์–ด์คŒ

 

 

2.ํ•œ ๋ฒˆ๋งŒ ๋งŒ๋“ค์–ด์„œ ์ „์ฒด ๊ณต์œ (์‹ฑ๊ธ€ํ†ค)

React์˜ Context์— ๋„ฃ๋Š” ๊ฐ์ฒด๋Š” ์ „์ฒด๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด์™€ ๋น„์Šทํ•จ

<DataContext.Provider value={myApiClient}>
  <App />
</DataContext.Provider>

 

Spring ๊ธฐ๋ณธ์ ์œผ๋กœ ๋นˆ์€ ์‹ฑ๊ธ€ํ†ค, ํ•œ ๋ฒˆ๋งŒ ๋งŒ๋“ค์–ด์ ธ์„œ ์–ด๋””์„œ๋“  ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ํŠน์ง•์ด ์žˆ๋‹ค.

@Configuration
public class AppConfig {
    @Bean
    public ApiClient apiClient() {
        return new ApiClient("https://api.example.com");
    }
}

apiClient()๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์ค‘ ๋‹จ 1๋ฒˆ๋งŒ ํ˜ธ์ถœ

 

 

3. ํ…Œ์ŠคํŠธํ•  ๋•Œ๋„ ํŽธํ•จ

@TestConfiguration
public class TestConfig {
    @Bean
    public ApiClient fakeApiClient() {
        return new FakeApiClient(); // ํ…Œ์ŠคํŠธ์šฉ ๊ฐ์ฒด!
    }
}

์‹ค์ œ ๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„ ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ ๊ต์ฒด๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค

์ด๊ฒŒ ๋‹ค ๋นˆ๋“ฑ๋ก์„ ํ†ตํ•ด ์˜์กด์„ฑ ์—ฐ๊ฒฐ์„ ์Šคํ”„๋ง์ด ๋งก๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅ

 

 


์–ด๋–ป๊ฒŒ ๋“ฑ๋กํ•˜๊ณ  ๊บผ๋‚ด์“ฐ๋Š”๋ฐ?

 

ComponentScan = ์ž๋™ ๋“ฑ๋กํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ
@Bean = ์ง์ ‘ ๋“ฑ๋กํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ

 

@ComponentScan: "์ž๋™ ๋“ฑ๋ก๊ธฐ"

 

๋ฌด์Šจ๋ง์ด๋ƒ๋ฉด,

์˜ˆ๋ฅผ๋“ค๋ฉด, React๋กœ ์น˜๋ฉด, ๋‚ด๊ฐ€ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ App.js์—์„œ ์ผ์ผ์ด import ์•ˆํ•ด๋„ src/ components /ํด๋”์— ์ „์ฒด๋ฅผ ์ž๋™์œผ๋กœ ์Šค์บ”ํ•ด์„œ ๋“ฑ๋กํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ

 

Spring์—์„  ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™๋‹ค.

@Component
public class MyService {
    public void doSomething() {
        System.out.println("Spring Bean!");
    }
}

 

์ด ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ์œ„์น˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์Šคํ”„๋ง์ด ์ž๋™์œผ๋กœ ์Šค์บ”ํ•œ๋‹ค.

@SpringBootApllication์ด ์žˆ๋Š” ํด๋ž˜์Šค ๊ธฐ์ค€์œผ๋กœ ํ•˜์œ„ ํŒจํ‚ค์ง€๋ฅผ ๋’ค์ ธ์„œ ์ด๋Ÿฐ @Component, @Service, @Controller, @Repository๊ฐ€ ๋ถ™์€ ๊ฑธ ์ „๋ถ€ Bean์œผ๋กœ ๋“ฑ๋กํ•ด์ค€๋‹ค.

 

์ฆ‰, ์ผ์ผ์ด ๋“ฑ๋กํ•˜์ง€ ์•Š์•„๋„ ๊ทธ๋ƒฅ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•ด์ค˜์„œ ํŽธํ•˜๋‹ค.

 

๋น„์œ ๋ฅผ ํ•ด๋ณด์ž๋ฉด, 

React์—์„œ components/ํด๋”์— ์žˆ๋Š” ๋ชจ๋“  ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ importํ•ด์ฃผ๋Š” ๋А๋‚Œ

(์‹ค์ œ๋กœ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์ง€๋งŒ, ๊ทธ๋Ÿฐ ์ž๋™ํƒ์ƒ‰๊ธฐ ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ์ดํ•ดํ•˜๋ฉด ๋”ฑ ์ข‹์Œ)

 

 

@SpringBootApplication์ด ์™œ ์ค‘์š”ํ•จ?
@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

 

์ด @SpringBootApllication์•ˆ์— ์ด๋ฏธ @ComponentScan์ด ํฌํ•จ๋ผ ์žˆ์Œ

์ฆ‰, ์ด ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์•„๋ž˜์— ์žˆ๋Š” ๋ชจ๋“  @Components๋“ค์„ ๋“ฑ๋กํ•ด์ค˜๋ผ๋Š” ์˜๋ฏธ๋‹ค.

 

๊ทธ๋ž˜์„œ MainApplication์˜ ์œ„์น˜๊ฐ€ ์—„์ฒญ ์ค‘์š”ํ•จ.

๋„ˆ๋ฌด ํ•˜์œ„์— ์žˆ์œผ๋ฉด ์œ„์— ์žˆ๋Š” ๊ฒƒ๋“ค์„ ์Šค์บ” ๋ชปํ•จ

 

 

์ž๋™ ๋“ฑ๋ก์ด ์‹ซ๊ณ  ์ง์ ‘ ๋“ฑ๋กํ•˜๊ณ  ์‹ถ์„ ๋•? (@Bean)

 

React์—์„œ Context.Provider์•ˆ์— ๊ฐ’์„ ๋ช…์‹œ์ ์œผ๋กœ ๋„ฃ์–ด์ฃผ๋Š” ๋А๋‚Œ์ด๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค.

 

@Bean์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฐ์ฒด๋‚˜ ๋‚ด๊ฐ€ ์ปจํŠธ๋กค ๋ชปํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.

Spring์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค

@Configuration // "์ด ํด๋ž˜์Šค๋Š” Bean ๋“ฑ๋ก์šฉ ํด๋ž˜์Šค์•ผ"
public class AppConfig {

    @Bean  // "์ด ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ Spring Bean์œผ๋กœ ๋“ฑ๋กํ•ด์ค˜!"
    public TestService testService() {
        return new TestServiceImpl();
    }
}

์ด์ œ๋ถ€ํ„ฐ๋Š” testService()๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” TestServiceImpl๊ฐ์ฒด๊ฐ€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์•ˆ์— ๋“ค์–ด๊ฐ„๋‹ค.

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
TestService service = context.getBean(TestService.class);

 

React๋กœ ์น˜๋ฉด, Context.Provider์•ˆ์— value={myService} ๋„ฃ์–ด์ค€ ๋А๋‚Œ.

 

 

 

Bean ์ถฉ๋Œ์ด ๋‚ฌ์„ ๋•?

 

๋‘ ๊ฐœ์˜ ๊ฐ™์€ ์ด๋ฆ„์„ ๊ฐ€์ง„ Bean์ด ์žˆ์œผ๋ฉด?

 

@Component("service") // ์ž๋™ ๋“ฑ๋ก
public class ConflictServiceV1 implements ConflictService {...}

@Component("service") // ์ž๋™ ๋“ฑ๋ก
public class ConflictServiceV2 implements ConflictService {...}

์ด๊ฑด ๋งˆ์น˜ Context.Provider ์•ˆ์— ๋‘ ๊ฐœ์˜ value๋ฅผ ๋™์‹œ์— ๋„ฃ์œผ๋ ค๋Š” ๊ฑฐ์ž„

์Šคํ”„๋ง์€ ConflictingBeanDefinitionException ์—๋Ÿฌ๋ฅผ ๋ฑ‰์Œ(๋ˆ„๊ตด ์“ธ์ง€ ๋ชจ๋ฅด๋‹ˆ๊น!)

๊ทธ๋Ÿด ๋•?

 

  • ์ˆ˜๋™ ๋“ฑ๋ก์ด ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ง„๋‹ค.
    • ์ฆ‰, ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋กํ•œ @Bean์ด ์ž๋™ ๋“ฑ๋ก๋œ @Component๋ณด๋‹ค ๋จผ์ € ๋จนํžˆ๊ฒŒ ๋œ๋‹ค.
  • ์‹ค์ˆ˜๋กœ ์ด๋ฆ„ ๊ฒน์น˜๋ฉด ์ง„์งœ ๋ฒ„๊ทธ๋‚จ.
  • ๊ทธ๋ž˜์„œ Spring Boot์—์„œ๋Š” ์ถฉ๋Œํ•˜๋ฉด ์• ์ดˆ์— ์‹คํ–‰ ์˜คํœด ๋‚ด๋ฒ„๋ฆฌ๋Š” ์ •์ฑ…์„ ์”€. ์ด๊ฒŒ ๋” ์•ˆ์ „ํ•˜๋‹ค.

 


 

์˜ˆ์‹œ์ฝ”๋“œ๋กœ ๋ณด๋Š” Bean

 

com.example
โ”œโ”€โ”€ MyApplication.java  // ์—ฌ๊ธฐ @SpringBootApplication ๋ถ™์Œ
โ”œโ”€โ”€ controller/
โ”‚   โ””โ”€โ”€ HelloController.java (@RestController)
โ”œโ”€โ”€ service/
โ”‚   โ””โ”€โ”€ GreetingServiceImpl.java (@Service)

 

// 1. ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ: ์—ญํ•  ์ •์˜
public interface GreetingService {
    String greet(String name);
}

 

 

 

// 2. ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด ๋งŒ๋“ค๊ธฐ
@Service // ComponentScan์— ์˜ํ•ด ์ž๋™์œผ๋กœ ๋นˆ ๋“ฑ๋ก๋จ
// ComponentScan๋ฅผ ์„ ์–ธ ์•ˆ ํ–ˆ๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ์ž๋™ ๋“ฑ๋ก์ด ๋˜๋Š”๊ฐ€?
// @SpringBootApplication์•ˆ์— @ComponentScan์ด ๋“ค์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ.

public class GreetingServiceImpl implements GreetingService {

    @Override
    public String greet(String name) {
        return "์•ˆ๋…•ํ•˜์„ธ์š”, " + name + "๋‹˜!";
    }
}

์œ„ ์ฝ”๋“œ์—์„œ @ComponentScan ์„ ์–ธ ์•ˆ ํ–ˆ๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ์ž๋™๋“ฑ๋ก์ด ๋˜๋Š”์ง€ ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ณ  ๋„˜์–ด๊ฐ€๊ฒ ๋‹ค.

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

์ด๋ ‡๊ฒŒ ์Šคํ”„๋ง๋ถ€ํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด, @SpringBootApllication์ด ์ž๋™์œผ๋กœ @ComponentScan์„ ํฌํ•จํ•˜๊ณ  ์žˆ์–ด์„œ

๋ณ„๋„๋กœ @ComponentScan์„ ์„ ์–ธํ•˜์ง€ ์•Š์•„๋„ ๋จ.

// ์‹ค์ œ๋กœ @SpringBootApplication์—๋Š” ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ์žˆ์Œ
@SpringBootApplication
= @Configuration
+ @EnableAutoConfiguration
+ @ComponentScan   ์š”๊ฒŒ ํฌํ•จ๋˜์–ด ์žˆ์Œ!!!

์ฆ‰, @SpringBootApplication = 3๊ฐœ๋ฅผ ํ•œ ๋ฒˆ์— ๋ถ™์ธ ํšจ๊ณผ

 

 

// 3. ์ด ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ
@RestController
public class HelloController {

    private final GreetingService greetingService;

    // 4. ์ƒ์„ฑ์ž ์ฃผ์ž…: ์Šคํ”„๋ง์ด GreetingServiceImpl์„ ์ž๋™์œผ๋กœ ๋„ฃ์–ด์คŒ!
    public HelloController(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    // 5. ๋ธŒ๋ผ์šฐ์ €์—์„œ /hello?name=ํ•œ์†” → ์ด ๋ฉ”์„œ๋“œ ์‹คํ–‰
    @GetMapping("/hello")
    public String hello(@RequestParam String name) {
        return greetingService.greet(name);  // ์‹ค์ œ ๊ตฌํ˜„์ฒด ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
    }
}

 

 

 

 

'Backend > ๐ŸŒฑ Spring' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Spring] Bean Validation  (5) 2025.07.28
[Spring]์˜์กด๊ด€๊ณ„ ์ฃผ์ž…(DI)  (2) 2025.07.28
[Spring] Layered Architecture  (3) 2025.07.26
[Spring] Mapping  (1) 2025.07.23
[Spring]MVC  (4) 2025.07.23