• ABOUT
  • POSTS
  • GUESTBOOK

ยฉ 2025 BlueCool12 All rights reserved.

2025.12.09Spring

๐Ÿ’‰ Spring์œผ๋กœ ์•Œ์•„๋ณด๋Š” ์˜์กด์„ฑ ์ฃผ์ž…(DI)

ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์“ฐ๊ฒŒ ๋˜์ง€๋งŒ ๋ง‰์ƒ DI๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋ช…ํ™•ํžˆ ์„ค๋ช…ํ•˜๊ธฐ ์• ๋งคํ•œ ๊ฒฝ์šฐ๋„ ๋งŽ๋‹ค. ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” DI๊ฐ€ ๋ฌด์—‡์ธ์ง€, ์™œ ์“ฐ๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ ์ฝ”๋“œ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€ ์•Œ์•„๋ณด์ž. 

DI(Dependency Injection)๋ž€? 

ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ๋‚ด๊ฐ€ ์ง์ ‘ new ํ•˜์ง€ ์•Š๊ณ  ์™ธ๋ถ€์—์„œ ๋„ฃ์–ด ์ฃผ๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. 

์˜ˆ๋ฅผ ๋“ค์–ด A ํด๋ž˜์Šค์—์„œ B ํด๋ž˜์Šค๋ฅผ ํ•„์š”๋กœ ํ•  ๋•Œ A ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ new ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ์ƒ์„ฑํ•˜๋Š” ๋Œ€์‹  ํ”„๋ ˆ์ž„์›Œํฌ(์Šคํ”„๋ง, NestJS ๋“ฑ)์˜ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ B ํด๋ž˜์Šค๋ฅผ A์— ์ฃผ์ž…ํ•ด ์ฃผ๋Š” ๋ฐฉ์‹์ด๋‹ค. 

์˜์กด์„ฑ(Dependency)์„ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…(Injection) ํ•œ๋‹ค๋Š” ์˜๋ฏธ 
 


*DI๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ  

๊ทธ๋ƒฅ ๊ฐ์ฒด ๋‚ด๋ถ€์—์„œ new ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ ์•„๋‹Œ๊ฐ€?๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค ์ˆ˜๋„ ์žˆ์ง€๋งŒ DI๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ์˜ ์žฅ์ ๋“ค์ด ์žˆ๋‹ค. 
 

1. ํ…Œ์ŠคํŠธ๊ฐ€ ์‰ฌ์›Œ์ง„๋‹ค (Mock ์ฃผ์ž…) 

๋จผ์ € DI๊ฐ€ ์—†๋Š” ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด 

java
// DI๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ง์ ‘ ์ƒ์„ฑ
public class PostService {
  
  private final PostRepository postRepository = new PostRepository();
  
  public Post getPost(Long id) {
    return postRepository.findById(id);
  }
}


์ด๋Ÿฐ ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธํ•  ๋•Œ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์กด์žฌํ•˜๋Š” ๋ฐ ์˜ˆ๋ฅผ ๋“ค์–ด PostRepository๊ฐ€ DB์— ์ง์ ‘ ๋ถ™๋Š” ๊ตฌํ˜„์ฒด๋ผ๋ฉด ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์‹ค์ œ DB๋ฅผ ํ•„์š”๋กœ ํ•˜์—ฌ Mock(๊ฐ€์งœ ๊ฐ์ฒด)๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค. 

๋”ฐ๋ผ์„œ DI๋ฅผ ์ ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค. 

java
// DI ์ ์šฉ
public class PostService {
  
  private final PostRepository postRepository;
  
  public PostService(PostRepository postRepository) {
    this.postRepository = postRepository; // ์™ธ๋ถ€์—์„œ ์ฃผ์ž…
  }
  
  public Post getPost(Long id) {
    return postRepository.findById(id);
  }
}


์ด์ œ ํ…Œ์ŠคํŠธ ์‹œ์—๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด Mock ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค. 

java
PostRepository mockRepo = mock(PostRepository.class);
PostService postService = new PostService(mockRepo);


์‹ค์ œ DB๋ฅผ ๋ถ™์ด์ง€ ์•Š๊ณ ๋„ Mock ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•ด์„œ PostService๋ฅผ ์ˆœ์ˆ˜ํ•˜๊ฒŒ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋‹ค. 
 

2. ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”์–ด ์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ์‰ฌ์›Œ์ง„๋‹ค 

DI์˜ ํ•ต์‹ฌ์€ ์ถ”์ƒ ํƒ€์ž…(์ธํ„ฐํŽ˜์ด์Šค)์— ์˜์กดํ•˜๋ผ๋Š” ์›์น™๊ณผ ์ž˜ ๋งž๋Š”๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ƒˆ ๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฌ๋ฉด ๊ธ€ ์ž‘์„ฑ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๋Š” ๊ธฐ๋Šฅ์„ ๋งŒ๋“ ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์ž. ์ฒ˜์Œ์—๋Š” ์ด๋ฉ”์ผ๋งŒ ๋ณด๋‚ด๋ฉด ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. 

java
// ์•Œ๋ฆผ ์ธํ„ฐํŽ˜์ด์Šค
public interface BlogNotifier {
  void notifyNewComment(Long postId, String commentAuthor, String commentContent);
}

// ์ด๋ฉ”์ผ ์•Œ๋ฆผ ๊ตฌํ˜„์ฒด
public class EmailBlogNotifier implements BlogNotifier {
  
  @Override
  public void notifyNewComment(
    Long postId, String commentAuthor, String, commentContent
  ) {
    // ์ด๋ฉ”์ผ ์ „์†ก ๋กœ์ง
  }
}


๊ทธ๋Ÿฐ๋ฐ ๋ธ”๋กœ๊ทธ๋ฅผ ์šด์˜ํ•˜๋˜ ๋„์ค‘ ์š”๊ตฌ์‚ฌํ•ญ์ด ๋ฐ”๋€Œ์–ด ์Šฌ๋ž™์œผ๋กœ ์•Œ๋ฆผ์„ ๋ณด๋‚ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์Šฌ๋ž™ ์•Œ๋ฆผ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค. 

java
// ์Šฌ๋ž™ ์•Œ๋ฆผ ๊ตฌํ˜„์ฒด
public class SlackBlogNotifier implements BlogNotifier {
  
  @Override
  public void notifyNewComment(
    Long postId, String commentAuthor, String commentContent
  ) {
    // ์Šฌ๋ž™ ์•Œ๋ฆผ ์ „์†ก ๋กœ์ง    
  }
}


์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ํฌ์ธํŠธ๋Š” CommentService ์ฝ”๋“œ๋Š” ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋‹จ์ง€ DI ์„ค์ •์—์„œ ์–ด๋–ค ๊ตฌํ˜„์ฒด๋ฅผ ์ฃผ์ž…ํ• ์ง€๋งŒ ๊ฒฐ์ •ํ•˜๋ฉด ๋œ๋‹ค๋Š” ์ ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์Šคํ”„๋ง์ด๋ผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

java
@Configuration
public class BlogConfig {
  
  @Bean
  public BlogNotifier blogNotifier() {
    // ์ƒํ™ฉ์— ๋งž๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ์„ ํƒ
    // return new EmailBlogNotifier();
    return new SlackBlogNotifier();
    // ํ•„์š”ํ•œ ๊ฒฝ์šฐ Email + Slack์„ ๋ฌถ์€ Composite ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“œ๋Š”๊ฒƒ๋„ ๊ฐ€๋Šฅ
  }
  
  @Bean
  public CommentService commentService(BlogNotifier blogNotifier) {
    return new CommentService(blogNotifier);
  }
}


์ด๋ ‡๊ฒŒ ํ•˜๋ฉด CommentService๋Š” ์˜ค์ง BlogNotifier ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์˜์กดํ•œ๋‹ค. ์‹ค์ œ๋กœ ์ด๋ฉ”์ผ์„ ๋ณด๋‚ผ์ง€ ์Šฌ๋ž™์„ ๋ณด๋‚ผ์ง€๋Š” ์ปจํ…Œ์ด๋„ˆ ์„ค์ •์—์„œ ๊ฒฐ์ •ํ•˜์—ฌ ๋‚˜์ค‘์— WebPush, ์นด์นด์˜คํ†ก ์•Œ๋ฆผ ๋“ฑ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์–ด๋„ ์ƒˆ๋กœ์šด ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  DI ์„ค์ •๋งŒ ๋ฐ”๊พธ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€ ๋ณด์ˆ˜์™€ ํ™•์žฅ์ด ํ›จ์”ฌ ์‰ฌ์›Œ์ง„๋‹ค. 
 


DI์™€ IoC(Inversion of Control) 

DI๊ฐ€ ๋‚˜์˜ค๋ฉด ํ•ญ์ƒ ๋”ฐ๋ผ์˜ค๋Š” ๋‹จ์–ด๊ฐ€ ํ•˜๋‚˜ ๋” ์žˆ๋‹ค. ๋ฐ”๋กœ IoC(Inversion of Control) ์ œ์–ด์˜ ์—ญ์ „์ด๋‹ค. ๊ธฐ์กด ์ „ํ†ต์ ์ธ ๋ฐฉ์‹์—์„œ๋Š” ๋ˆ„๊ฐ€ ์–ด๋–ค ๊ฐ์ฒด๋ฅผ new ํ• ์ง€, ๋ˆ„๊ฐ€ ๋ˆ„๊ตฌ๋ฅผ ํ˜ธ์ถœํ• ์ง€ ์ „๋ถ€ ๋‚ด ์ฝ”๋“œ๊ฐ€ ์ง์ ‘ ์ œ์–ดํ•œ๋‹ค. 

java
public class Main {
  public static void main(String[] args) {
    PostRepository repo = new PostRepository();
    PostService service = new PostService(repo);
    
    Post post = service.getPost(1L);
  }
}


์œ„ ์ฝ”๋“œ์—์„œ๋Š” ์ง์ ‘ ๊ฐ์ฒด ์ƒ์„ฑ ์ˆœ์„œ์™€ ์˜์กด์„ฑ์„ ๋ชจ๋‘ ์ œ์–ดํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์Šคํ”„๋ง, NestJS ๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด๋ฅผ ์–ธ์ œ ๋งŒ๋“ค์ง€, ์–ด๋–ค ์ˆœ์„œ๋กœ ๋งŒ๋“ค์ง€, ์–ด๋–ค ๊ฐ์ฒด์— ์–ด๋–ค ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ• ์ง€ ๊ฐ™์€ ์ด๋Ÿฐ ์ œ์–ด๊ถŒ์„ ํ”„๋ ˆ์ž„์›Œํฌ์˜ IoC ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ฐ€์ ธ๊ฐ„๋‹ค. 

์šฐ๋ฆฌ๋Š” ๊ทธ์ € ์ด ํด๋ž˜์Šค๊ฐ€ ์„œ๋น„์Šค์ธ์ง€ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์ธ์ง€ ํ˜น์€ ์ฃผ์ž…๋ฐ›์•„ ์‚ฌ์šฉํ• ์ง€ ๋“ฑ์˜ ์—ฌ๋ถ€๋งŒ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ํ‘œ์‹œํ•ด ์ฃผ๋ฉด ๋œ๋‹ค. 
 

java
@Repository
public class PostRepository {
  // ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ฝ”๋“œ
}

@Service
public class PostService {
  
  private final PostRepository postRepository;
  
  @Autowired
  public PostService(PostRepository postRepository) {
    this.postRepository = postRepository;
  }
}


์ง์ ‘ new ํ•˜์ง€ ์•Š๊ณ  ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์ฃผ์ž…ํ•œ๋‹ค. ์ฆ‰ ์ œ์–ด(Control)๊ฐ€ ์šฐ๋ฆฌ ์ฝ”๋“œ์—์„œ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์—ญ์ „(Inversion) ๋˜์—ˆ๋‹ค. ์ด๊ฒƒ์„ IoC๋ผ๊ณ  ํ•˜๋ฉฐ ๊ทธ ๊ตฌ์ฒด์ ์ธ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๊ฐ€ DI์ด๋‹ค. 
 


DI์˜ ์ฃผ์ž… ๋ฐฉ๋ฒ• 

DI์—๋Š” ๋ณดํ†ต ์„ธ ๊ฐ€์ง€ ๋ฐฉ์‹์ด ์žˆ๋‹ค. 

  • ์ƒ์„ฑ์ž ์ฃผ์ž…(Constructor Injection)
  • ํ•„๋“œ ์ฃผ์ž…(Field Injection)
  • ์„ธํ„ฐ ์ฃผ์ž…(Setter Injection) 

์š”์ฆ˜์€ ์ƒ์„ฑ์ž ์ฃผ์ž…์ด ๊ฐ€์žฅ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ์‹์ด๋‹ค. 

*์ƒ์„ฑ์ž ์ฃผ์ž… 

java
@Service
public class PostService {
  
  private final PostRepository postRepository;
  
  public PostService(PostRepository postRepository) {
    this.postRepository = postRepository;
  }
}

final ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ์ƒ์„ฑ์ž๋งŒ ํ˜ธ์ถœํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ŠคํŠธ๋„ ์šฉ์ดํ•˜๋‹ค. (Lombok ์‚ฌ์šฉ ์‹œ @RequiredArgsConstructor๋กœ๋„ ๊ฐ€๋Šฅ)

*ํ•„๋“œ ์ฃผ์ž… 

java
@Service
public class PostService {
  
  @Autowired
  private PostRepository postRepository;
}

์ฝ”๋“œ๊ฐ€ ๊ต‰์žฅํžˆ ๊ฐ„๋‹จํ•ด์ง€์ง€๋งŒ ํ•„๋“œ๊ฐ€ final์ด ๋  ์ˆ˜ ์—†๊ณ  ํ…Œ์ŠคํŠธ ์‹œ Mock ์ฃผ์ž…์ด ๋ถˆํŽธํ•˜์—ฌ ์š”์ฆ˜์€ ์ง€์–‘ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ทจ๊ธ‰๋œ๋‹ค. (DI ์ปจํ…Œ์ด๋„ˆ ์—†์ด ์ˆœ์ˆ˜ ์ž๋ฐ” ์ฝ”๋“œ๋กœ ์ƒ์„ฑํ•˜๊ธฐ๋„ ์–ด๋ ต๋‹ค)

*์„ธํ„ฐ ์ฃผ์ž… 

java
@Service
public class PostService {
  
  private PostRepository postRepository;
  
  @Autowired
  public void setPostRepository(PostRepository postRepository) {
    this.postRepository = postRepository;
  }
}

์„ ํƒ์ ์ธ ์˜์กด์„ฑ์ด๋‚˜ ๋Ÿฐํƒ€์ž„์— ๊ตฌํ˜„์ฒด๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉ๋˜๊ธฐ๋„ ํ•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ์„œ๋น„์Šค/๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ตฌ์กฐ์—์„œ๋Š” ์ƒ์„ฑ์ž ์ฃผ์ž…์ด ๋” ๊น”๋”ํ•˜๋‹ค. 
 

์ด์ „ ๊ธ€
๐Ÿ”ค Java์˜ String์ด ํŠน๋ณ„ํ•œ ์ด์œ  - String์˜ ํ•ต์‹ฌ ํŠน์ง• 3๊ฐ€์ง€
๋‹ค์Œ ๊ธ€
๐Ÿง‘โ€๐Ÿ”ง Lombok์˜ ์ƒ์„ฑ์ž ์–ด๋…ธํ…Œ์ด์…˜
์žฅ์‹์šฉ ๋กœ๊ณ