๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
SpringBoot

[SpringBoot] DI(Dependency injection)

by ๊ฐœ๋ฐœLOG 2025. 1. 12.
๋ฐ˜์‘ํ˜•

DI(Dependency injection)๋Š” ํด๋ž˜์Šค๊ฐ€ ์ž์‹ ์ด ํ•„์š”ํ•œ ์˜์กด ๊ฐ์ฒด(์ฆ‰, ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค)๋ฅผ ์Šค์Šค๋กœ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ์™ธ๋ถ€์—์„œ ์ œ๊ณต๋ฐ›๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์˜์กด์„ฑ(๋‹ค๋ฅธ ๊ฐ์ฒด)์„ ์ฃผ์ž…ํ•ด์คŒ์œผ๋กœ์จ ๊ฐ์ฒด ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ , ๊ฐ์ฒด์˜ ์ƒ์„ฑ๊ณผ ๊ด€๋ฆฌ์˜ ์ฑ…์ž„์„ ์™ธ๋ถ€์— ์œ„์ž„ํ•ฉ๋‹ˆ๋‹ค.

1. ์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ DI ์„ค์ • ๊ธฐ๋ณธ ๊ตฌ์กฐ

์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ DI๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ณผ์ •์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ๋‹จ๊ณ„๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ์ปดํฌ๋„ŒํŠธ ์Šค์บ”: @Component ๋ฐ ๊ทธ ํ•˜์œ„ ์–ด๋…ธํ…Œ์ด์…˜(@Service, @Repository, @Controller ๋“ฑ)์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก.
  2. ์ž๋™ ์˜์กด์„ฑ ์ฃผ์ž…: @Autowired๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜์กด์„ฑ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…๋ฐ›๊ธฐ.

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ ์„ค์ •์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ž๋™ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํŠน๋ณ„ํ•œ ์„ค์ • ์—†์ด๋„ ๋นˆ ๋“ฑ๋ก ๋ฐ ์˜์กด์„ฑ ์ฃผ์ž…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

2. ์˜์กด์„ฑ ์ฃผ์ž…(DI) ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•

(1) ์ƒ์„ฑ์ž ์ฃผ์ž… (Constructor Injection)

์ƒ์„ฑ์ž ์ฃผ์ž…์€ ์˜์กดํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ์ž ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ๋ณด์žฅํ•˜๊ณ , ์˜์กด์„ฑ์ด ์—†์œผ๋ฉด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ ํƒ€์ž„์— ์˜์กด์„ฑ์„ ๊ฐ•์ œ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Component
public class MyService {
    private final MyRepository myRepository;

    // ์ƒ์„ฑ์ž ์ฃผ์ž…
    @Autowired
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }

    public void performService() {
        myRepository.doSomething();
    }
}

@Component
public class MyRepository {
    public void doSomething() {
        System.out.println("Doing something!");
    }
}
  • @Autowired: ์ƒ์„ฑ์ž์— @Autowired ์• ๋„ˆํ…Œ์ด์…˜์„ ๋ถ™์—ฌ ์Šคํ”„๋ง์ด ์ž๋™์œผ๋กœ ์˜์กด์„ฑ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ์ž๊ฐ€ ํ•˜๋‚˜์ผ ๊ฒฝ์šฐ @Autowired๋Š” ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(2) ์„ธํ„ฐ ์ฃผ์ž… (Setter Injection)

์„ธํ„ฐ ์ฃผ์ž…์€ ๊ฐ์ฒด์˜ ์„ธํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ ํ›„ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆ๋ณ€์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

@Component
public class MyService {
    private MyRepository myRepository;

    // ์„ธํ„ฐ ์ฃผ์ž…
    @Autowired
    public void setMyRepository(MyRepository myRepository) {
        this.myRepository = myRepository;
    }

    public void performService() {
        myRepository.doSomething();
    }
}

 

3. ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ๊ถŒ์žฅํ•˜๋Š” ์ด์œ 

์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๋ณ€์„ฑ์„ ๋ณด์žฅํ•˜๊ณ  ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ๋†’์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.

 

4. Lombok์—์„œ ์ œ๊ณตํ•˜๋Š” ์ƒ์„ฑ์ž ๊ด€๋ จ ์–ด๋…ธํ…Œ์ด์…˜

@AllArgsConstructor , @RequiredArgsConstructor ์ฐจ์ด

 

(1)  @AllArgsConstructor

@AllArgsConstructor๋Š” ํด๋ž˜์Šค์— ์ •์˜๋œ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ฐ–๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” Lombok ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

  • ๋ชจ๋“  ํ•„๋“œ๊ฐ€ ์ฃผ์ž… ๊ฐ€๋Šฅํ•œ ์ƒ์„ฑ์ž๊ฐ€ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค.
  • **final**์ด ๋ถ™์€ ํ•„๋“œ๋„ ํฌํ•จ๋˜๋ฉฐ, ํ•„๋“œ์˜ ํƒ€์ž…์— ๊ด€๊ณ„์—†์ด ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ƒ์„ฑ์ž ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
import lombok.AllArgsConstructor;

@AllArgsConstructor
public class MyService {
    private final MyRepository myRepository;
    private MyOtherRepository myOtherRepository;

    public void performService() {
        myRepository.doSomething();
        myOtherRepository.doSomethingElse();
    }
}

final์ด ๋ถ™๋˜ ์•ˆ๋ถ™๋˜ ์ƒ๊ด€ ์—†์Œ.  @AllArgsConstructor๋Š” ๋ชจ๋“  ํ•„๋“œ ์ƒ์„ฑ์ž ์ฃผ์ž…

myRepository์™€ myOtherRepository ์ƒ์„ฑ์ž ์ฃผ์ž… ๋จ

 

(2) @RequiredArgsConstructor

@RequiredArgsConstructor๋Š” final ํ•„๋“œ์™€ @NonNull ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํ•„๋“œ์— ๋Œ€ํ•ด์„œ๋งŒ ์ƒ์„ฑ์ž๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” Lombok ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค.

  • final ํ•„๋“œ ๋˜๋Š” **@NonNull**์ด ๋ถ™์€ ํ•„๋“œ๋“ค๋งŒ ์ƒ์„ฑ์ž ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
  • ์ฆ‰, ์ฃผ์ž…์ด ํ•„์š”ํ•œ ํ•„๋“œ๋“ค๋งŒ ์ƒ์„ฑ์ž์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํฌํ•จ๋˜๋ฉฐ, final ํ•„๋“œ๊ฐ€ ์•„๋‹Œ @NonNull ํ•„๋“œ๋Š” NULL์ด ์•„๋‹ˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ œ์•ฝ์„ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
import lombok.RequiredArgsConstructor;
import lombok.NonNull;

@RequiredArgsConstructor
public class MyService {
    private final MyRepository myRepository;  // final ํ•„๋“œ
    private @NonNull MyOtherRepository myOtherRepository;  // @NonNull ํ•„๋“œ
    private SubRepository subRepository;

    public void performService() {
        myRepository.doSomething();
    }
}

myRepository์™€ myOtherRepository ๋งŒ ์ƒ์„ฑ์ž ์ฃผ์ž…๋˜๊ณ , subRepository๋Š” ์ƒ์„ฑ์ž์— ํฌํ•จ๋˜์ง€ ์•Š์œผ๋ฉฐ ์ฃผ์ž…๋„ ์•ˆ๋จ.

 

์ฐจ์ด์  ์ •๋ฆฌ

ํŠน์ง•   @AllArgsConstructor @RequiredArgsConstructor
์ƒ์„ฑ์ž์— ํฌํ•จ๋˜๋Š” ํ•„๋“œ   ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ•„๋“œ (๋‹จ, final ํ•„๋“œ๋Š” ๋ฐ˜๋“œ์‹œ ์ฃผ์ž…) final ํ•„๋“œ์™€ **@NonNull**์ด ๋ถ™์€ ํ•„๋“œ๋“ค๋งŒ ํฌํ•จ
ํ•„๋“œ ์ œ์•ฝ   ํ•„๋“œ๊ฐ€ final์ธ์ง€ ์—ฌ๋ถ€์™€ ๊ด€๊ณ„์—†์ด ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ƒ์„ฑ์ž์— ํฌํ•จ final์ด๊ฑฐ๋‚˜ @NonNull ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํ•„๋“œ๋งŒ ํฌํ•จ
์‚ฌ์šฉ ์˜ˆ   ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ƒ์„ฑ ์ฃผ์ž…์ด ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ƒ์„ฑ

๊ฒฐ๋ก 

  • @AllArgsConstructor๋Š” ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ฐ–๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ, ์ฃผ๋กœ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ฃผ์ž…ํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • @RequiredArgsConstructor๋Š” final ํ•„๋“œ ๋˜๋Š” **@NonNull**์ด ๋ถ™์€ ํ•„๋“œ์— ๋Œ€ํ•ด์„œ๋งŒ ์ƒ์„ฑ์ž๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ, ์ฃผ๋กœ ์ฃผ์ž…์ด ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ์ฃผ์ž…ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
๋ฐ˜์‘ํ˜•