๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ์„ค๊ณ„


ํšŒ์›

  • ํšŒ์›์„ ๊ฐ€์ž…ํ•˜๊ณ  ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํšŒ์›์€ ์ผ๋ฐ˜๊ณผ VIP ๋‘ ๊ฐ€์ง€ ๋“ฑ๊ธ‰์ด ์žˆ๋‹ค.
  • ํšŒ์› ๋ฐ์ดํ„ฐ๋Š” ์ž์ฒด DB ๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ณ , ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฃผ๋ฌธ๊ณผ ํ• ์ธ ์ •์ฑ…

  • ํšŒ์›์€ ์ƒํ’ˆ์„ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํšŒ์› ๋“ฑ๊ธ‰์— ๋”ฐ๋ผ ํ• ์ธ ์ •์ฑ…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ• ์ธ ์ •์ฑ…์€ ๋ชจ๋“  VIP ๋Š” 1000์›์„ ํ• ์ธํ•ด์ฃผ๋Š” ๊ณ ์ • ๊ธˆ์•ก ํ• ์ธ์„ ์ ์šฉํ•œ๋‹ค.
  • ํ• ์ธ ์ •์ฑ…์€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค. ํšŒ์‚ฌ์˜ ๊ธฐ๋ณธ ํ• ์ธ ์ •์ฑ…์„ ์•„์ง ์ •ํ•˜์ง€ ๋ชปํ–ˆ๊ณ , ์˜คํ”ˆ ์ง์ „๊นŒ์ง€ ๊ณ ๋ฏผ์„ ๋ฏธ๋ฃจ๊ณ  ์‹ถ๋‹ค. ์ตœ์•…์˜ ๊ฒฝ์šฐ ํ• ์ธ์„ ์ ์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

ํšŒ์› ๋„๋ฉ”์ธ ์„ค๊ณ„


ํšŒ์› ๋„๋ฉ”์ธ ํ˜‘๋ ฅ ๊ด€๊ณ„

ํšŒ์› ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

ํšŒ์› ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ

Web MVC ๊ฐœ๋ฐœ


ํšŒ์› ์›น ๊ธฐ๋Šฅ - ํ™ˆ ํ™”๋ฉด ์ถ”๊ฐ€

package hello.hellospring.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
 
@Controller
public class HomeController {
 
     @GetMapping("/")
     public String home() {
         return "home";
     }
}

/ ๊ฒฝ๋กœ๋กœ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ, ์œ„ GetMapping ์„ ํ†ตํ•ด ์š”์ฒญ์„ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋ฐ›์•„๋“œ๋ ค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ปจํŠธ๋กค๋Ÿฌ๋Š” ์ •์  ํŒŒ์ผ๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๊ธฐ ๋•Œ๋ฌธ์—, ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋จผ์ € ์กฐํšŒํ•˜์—ฌ ํ•ด๋‹น ์š”์ฒญ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. ๋•Œ๋ฌธ์—, ๊ธฐ์กด์— static ์•ˆ์— ์žˆ๋Š” index.html ์ด ๋ฐ˜ํ™˜๋˜์ง€ ์•Š๊ณ , templates ์—์„œ home.html ์„ ๋ Œ๋”๋งํ•˜์—ฌ ์‘๋‹ตํ•œ๋‹ค.

ํšŒ์› ์›น ๊ธฐ๋Šฅ - ๋“ฑ๋ก

@Controller
public class MemberController {
 
    private final MemberService memberService;
 
    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
 
    @GetMapping(value = "/members/new")
    public String createForm() {
        return "members/createMemberForm";
    }
 
    @PostMapping(value = "/members/new")
    public String create(MemberForm form) {
        Member member = new Member();
        member.setName(form.getName());
 
        memberService.join(member);
 
        return "redirect:/";
    }
}

ํšŒ์› ๋“ฑ๋กํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์œ„์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•œ๋‹ค. /members/new ๊ฒฝ๋กœ๋กœ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ, ์œ„ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋˜๊ณ , templates ์•ˆ์— ์žˆ๋Š” members ๋””๋ ‰ํ† ๋ฆฌ์˜ createMemberForm.html ์„ ๋ Œ๋”๋งํ•˜์—ฌ ์‘๋‹ตํ•œ๋‹ค.

package hello.hellospring.controller;
 
public class MemberForm {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

ํšŒ์› ๋“ฑ๋ก ํŽ˜์ด์ง€๊ฐ€ ๋„์›Œ์ง„ ์ƒํƒœ์—์„œ POST ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋œ๋‹ค๋ฉด, PostMapping ์„ ํ†ตํ•ด ์š”์ฒญ์„ ๋ฐ›๊ฒŒ๋œ๋‹ค. Form ์œผ๋กœ ์ „๋‹ฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•˜์—ฌ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋ฐ›๊ฒŒ๋˜๊ณ , ์ด๋ฅผ ๋„๋ฉ”์ธ ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ service ๋ ˆ์ด์–ด์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค. ๋ชจ๋“  ํšŒ์› ๋“ฑ๋ก ๋กœ์ง์ด ์ˆ˜ํ–‰๋œ ์ดํ›„ redirect:/ ๋ฅผ ํ†ตํ•ด ํ™ˆ ํ™”๋ฉด์œผ๋กœ redirect ํ•œ๋‹ค.

ํšŒ์› ์›น ๊ธฐ๋Šฅ - ์กฐํšŒ

@GetMapping(value = "/members")
public String list(Model model) {
 
    List<Member> members = memberService.findMembers();
    model.addAttribute("members", members);
    return "members/memberList";
}

/members ๊ฒฝ๋กœ๋กœ ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๊ฒฝ์šฐ์— ํšŒ์› ๋ชฉ๋ก์„ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์œ„์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. memberService.findMembers(); ๋ฅผ ํ†ตํ•ด ๋ฉค๋ฒ„ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ›์•„์˜จ ํ›„ model ์˜ attribute ์— add ํ•ด์ค€๋‹ค. ์ดํ›„ templates ์•ˆ์— ์žˆ๋Š” members ๋””๋ ‰ํ† ๋ฆฌ์˜ memberList.html ์„ ๋ Œ๋”๋งํ•˜์—ฌ ์‘๋‹ตํ•œ๋‹ค.

์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ์„ค๊ณ„


์ฃผ๋ฌธ ๋„๋ฉ”์ธ ํ˜‘๋ ฅ, ์—ญํ• , ์ฑ…์ž„

์ฃผ๋ฌธ ๋„๋ฉ”์ธ ์ „์ฒด

์ฃผ๋ฌธ ๋„๋ฉ”์ธ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

์ฃผ๋ฌธ ๋„๋ฉ”์ธ ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ

์ €์žฅ์†Œ๋‚˜ ํ• ์ธ ์ •์ฑ…์„ ๋ณ€๊ฒฝํ•ด๋„ ์„œ๋น„์Šค ๊ตฌํ˜„์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ… ๊ฐœ๋ฐœ


RateDiscountPolicy ์ถ”๊ฐ€

์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ… ์ ์šฉ๊ณผ ๋ฌธ์ œ์ 


ํ• ์ธ ์ •์ฑ…์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ์šฉํ•ด๋ณด์ž

ํ• ์ธ ์ •์ฑ…์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ํด๋ผ์ด์–ธํŠธ์ธ OrderServiceImpl ์ฝ”๋“œ๋ฅผ ๊ณ ์ณ์•ผ ํ•œ๋‹ค.

public class OrderServiceImpl implements OrderService {
    // private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
    ...
}

์ฃผ๋ฌธ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ์ธ OrderServiceImpl ๋Š” ์‚ฌ์‹ค ์ธํ„ฐํŽ˜์ด์Šค๋„ ์˜์กดํ•˜๋ฉด์„œ ๊ตฌํ˜„์ฒด์—๋„ ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ์˜์กด๊ด€๊ณ„๋Š” DIP ๋ฅผ ์œ„๋ฐ˜ํ•˜๊ณ  ์žˆ๋‹ค. ๋˜ํ•œ, ํ˜„์žฌ ์ฝ”๋“œ๋Š” ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•ด์„œ ๋ณ€๊ฒฝํ•˜๋ฉด, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์˜ํ–ฅ์„ ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— OCP ๋„ ์œ„๋ฐ˜ํ•œ๋‹ค.

์‹ค์ œ ์˜์กด๊ด€๊ณ„

์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์˜์กดํ•˜๋„๋ก ์„ค๊ณ„ ๋ณ€๊ฒฝ

public class OrderServiceImpl implements OrderService {
    private DiscountPolicy discountPolicy;
    ...
}

์‹ค์ œ ์‹คํ–‰ํ•ด๋ณด๋ฉด NPE ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„  ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํด๋ผ์ด์–ธํŠธ์ธ OrderServiceImpl ์— DiscountPolicy ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ๋Œ€์‹  ์ƒ์„ฑํ•˜๊ณ  ์ฃผ์ž…ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ


AppConfig ๋“ฑ์žฅ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด ๋™์ž‘ ๋ฐฉ์‹์„ ๊ตฌ์„ฑ(config)ํ•˜๊ธฐ ์œ„ํ•ด, ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์—ฐ๊ฒฐํ•˜๋Š” ์ฑ…์ž„์„ ๊ฐ€์ง€๋Š” ๋ณ„๋„์˜ ์„ค์ • ํด๋ž˜์Šค, AppConfig ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. AppConfig ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋™์ž‘์— ํ•„์š”ํ•œ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ƒ์„ฑํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ฃผ์ž…ํ•œ๋‹ค. MemberServiceImpl ์˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ• ์ง€๋Š” ์˜ค์ง ์™ธ๋ถ€์—์„œ ๊ฒฐ์ •๋˜๊ณ , MemberServiceImpl ์€ ์ด์ œ๋ถ€ํ„ฐ ์˜์กด๊ด€๊ณ„์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์€ ์™ธ๋ถ€์— ๋งก๊ธฐ๊ณ  ์‹คํ–‰์—๋งŒ ์ง‘์ค‘ํ•œ๋‹ค.

ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

AppConfig ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ ์—ฐ๊ฒฐ์˜ ์—ญํ• ์„ ์œ„์ž„ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด DIP ๋ฅผ ์ค€์ˆ˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ๋œ๋‹ค.

ํšŒ์› ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

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

์ƒˆ๋กœ์šด ๊ตฌ์กฐ์™€ ํ• ์ธ ์ •์ฑ… ์ ์šฉ


ํ• ์ธ ์ •์ฑ…์˜ ๋ณ€๊ฒฝ

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

์ข‹์€ ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„์˜ 5๊ฐ€์ง€ ์›์น™์˜ ์ ์šฉ


SRP ๋‹จ์ผ ์ฑ…์ž„ ์›์น™

๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ๊ฐ์ฒด๋Š” ์ง์ ‘ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์—ฐ๊ฒฐํ•˜๊ณ , ์‹คํ–‰ํ•˜๋Š” ๋‹ค์–‘ํ•œ ์ฑ…์ž„์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋‹ค. AppConfig ๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋Š” ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ ๊ฐ์ฒด๋Š” ์‹คํ–‰ํ•˜๋Š” ์ฑ…์ž„๋งŒ ๋‹ด๋‹นํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , SRP ๋ฅผ ์ค€์ˆ˜ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

DIP ์˜์กด๊ด€๊ณ„ ์—ญ์ „ ์›์น™

์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ…์„ ๊ฐœ๋ฐœํ•˜๊ณ  ์ ์šฉํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ–ˆ๋‹ค. AppConfig ๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๊ฐ€ ์ถ”์ƒํ™” ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€๊ฒฝํ•˜๊ณ , AppConfig ์—์„œ ๊ตฌํ˜„์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค. ์ด๋ฅผ ํ†ตํ•ด DIP ์—ญ์‹œ ์ค€์ˆ˜ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

OCP ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™

๋‹คํ˜•์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ DIP ๋ฅผ ์ง€์ผฐ๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉ ์˜์—ญ๊ณผ ๊ตฌ์„ฑ ์˜์—ญ์œผ๋กœ ๋‚˜๋ˆด๋‹ค. AppConfig ๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ์šด ๊ตฌํ˜„์ฒด๋ฅผ ์ฃผ์ž…ํ•˜๊ฒŒ ๋˜๋ฉด, ์†Œํ”„ํŠธ์›จ์–ด ์š”์†Œ๋Š” ์ƒˆ๋กญ๊ฒŒ ํ™•์žฅ๋˜์—ˆ์ง€๋งŒ, ์‚ฌ์šฉ ์˜์—ญ์˜ ๋ณ€๊ฒฝ์€ ๋‹ซํ˜€ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ๊ฒฐ๊ตญ OCP ๋ฅผ ์ค€์ˆ˜ํ•˜๋Š” ํ–‰์œ„์ด๋‹ค.

IoC, DI, ์ปจํ…Œ์ด๋„ˆ


์ œ์–ด์˜ ์—ญ์ „ IoC, Inversion of Control

๊ธฐ์กด ํ”„๋กœ๊ทธ๋žจ์€ ํด๋ผ์ด์–ธํŠธ ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ์Šค์Šค๋กœ ํ•„์š”ํ•œ ์„œ๋ฒ„ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์—ฐ๊ฒฐํ•˜๊ณ , ์‹คํ–‰ํ–ˆ๋‹ค. ์ฆ‰, ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์„ ์Šค์Šค๋กœ ์กฐ์ข…ํ–ˆ๋‹ค. ๋ฐ˜๋ฉด, AppConfig ์˜ ๋“ฑ์žฅ ์ดํ›„, ๊ตฌํ˜„ ๊ฐ์ฒด๋Š” ์ž์‹ ์˜ ๋กœ์ง์„ ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ๋งŒ ๋‹ด๋‹นํ•˜๊ณ  ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์€ AppConfig ๊ฐ€ ๊ฐ€์ ธ๊ฐ„๋‹ค. ์ด๋ ‡๋“ฏ, ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์„ ์ง์ ‘ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์™ธ๋ถ€์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ์ œ์–ด์˜ ์—ญ์ „์ด๋ผ๊ณ  ํ•œ๋‹ค.

ํ”„๋ ˆ์ž„ ์›Œํฌ vs ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ์ œ์–ดํ•˜๊ณ  ๋Œ€์‹  ์‹คํ–‰ํ•˜๋ฉด ๊ทธ๊ฒƒ์€ ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค. ๋ฐ˜๋ฉด, ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ ์ง์ ‘ ์ œ์–ด์˜ ํ๋ฆ„์„ ๋‹ด๋‹นํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ ๊ฒƒ์ด๋‹ค.

์˜์กด๊ด€๊ณ„ ์ฃผ์ž… DI, Dependency Injection

์˜์กด๊ด€๊ณ„๋Š” ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„์™€, ์‹คํ–‰ ์‹œ์ ์— ๊ฒฐ์ •๋˜๋Š” ๋™์ ์ธ ์˜์กด๊ด€๊ณ„๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค. ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„๋Š” ํด๋ž˜์Šค๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” import ์ฝ”๋“œ๋งŒ ๋ณด๊ณ ๋„ ์˜์กด๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜์ง€ ์•Š์•„๋„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ๋™์ ์ธ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ์˜์กด๊ด€๊ณ„๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ์ ์— ์‹ค์ œ ์ƒ์„ฑ๋œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์˜์กด๊ด€๊ณ„๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ์ ์— ์™ธ๋ถ€์—์„œ ์‹ค์ œ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•˜์—ฌ ์˜์กด๊ด€๊ณ„๊ฐ€ ์—ฐ๊ฒฐ๋˜๋Š” ๊ฒƒ์„ ์˜์กด์„ฑ ์ฃผ์ž…์ด๋ผ๊ณ  ํ•œ๋‹ค. ์˜์กด์„ฑ ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ , ๋™์ ์ธ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ์˜์กด๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

IoC ์ปจํ…Œ์ด๋„ˆ์™€ DI ์ปจํ…Œ์ด๋„ˆ

AppConfig ์ฒ˜๋Ÿผ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ด€๋ฆฌํ•˜๊ณ , ์˜์กด๊ด€๊ณ„๋ฅผ ์—ฐ๊ฒฐํ•ด ์ฃผ๋Š” ๊ฒƒ์„ IoC ์ปจํ…Œ์ด๋„ˆ ํ˜น์€ DI ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•œ๋‹ค. ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์— ์ดˆ์ ์„ ๋งž์ถ”์–ด ์ตœ๊ทผ์—๋Š” ์ฃผ๋กœ DI ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•œ๋‹ค.

์Šคํ”„๋ง์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ


์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ

ApplicationContext ๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•œ๋‹ค. ๊ธฐ์กด์—๋Š” AppConfig ๋ฅผ ์‚ฌ์šฉํ•ด ์ง์ ‘ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  DI ํ–ˆ์ง€๋งŒ, ์ด์ œ๋ถ€ํ„ฐ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }
    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }
}

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” @Configuration ์ด ๋ถ™์€ AppConfig ๋ฅผ ์„ค์ •(๊ตฌ์„ฑ) ์ •๋ณด๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ @Bean ์ด๋ผ ์ ํžŒ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ํ˜ธ์ถœํ•ด์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•œ๋‹ค. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์ด๋ผ๊ณ  ํ•˜๋ฉฐ, ๋ฉ”์„œ๋“œ๋ช…์„ ์Šคํ”„๋ง ๋นˆ์˜ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

public class OrderApp {
    public static void main(String[] args) {
//        AppConfig appConfig = new AppConfig();
//        MemberService memberService = appConfig.memberService();
//        OrderService orderService = appConfig.orderService();
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
        OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
        Long memberId = 1L;
        Member member = new Member(memberId, "memberA", Grade.VIP);
        memberService.join(member);
        Order order = orderService.createOrder(memberId, "itemA", 10000);
        System.out.println("order = " + order);
    }
}

๊ธฐ์กด AppConfig ๋งŒ์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ AppConfig ๋ฅผ ์‚ฌ์šฉํ•ด ์ง์ ‘ ์กฐํšŒํ–ˆ์ง€๋งŒ, ์ด์ œ๋ถ€ํ„ฐ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ†ตํ•ด์„œ ํ•„์š”ํ•œ ์Šคํ”„๋ง ๋นˆ์„ ์ฐพ์•„์•ผ ํ•œ๋‹ค. ์Šคํ”„๋ง ๋นˆ์€ ์œ„์™€ ๊ฐ™์ด applicationContext.getBean() ์„ ํ†ตํ•ด ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋กœ์จ, ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•˜๊ณ  ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ์Šคํ”„๋ง ๋นˆ์„ ์ฐพ์•„์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ๋” ๋ณต์žกํ•ด์ง„ ๊ฒƒ ๊ฐ™์€๋ฐ, ๊ตณ์ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ• ๊นŒ? ๋ฌด์Šจ ์žฅ์ ์ด ์žˆ์„๊นŒ?