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

[๋‚ด์ผ๋ฐฐ์›€์บ ํ”„_Spring Boot ์ž…๋ฌธ์ฃผ์ฐจ] IoC์™€ DI

by alswlfl 2026. 6. 25.

IoC(์ œ์–ด์˜ ์—ญ์ „), DI(์˜์กด์„ฑ ์ฃผ์ž…) ์ดํ•ดํ•˜๊ธฐ

Spring์˜ IoC์™€ DI

๏นกIoC์™€ DI๋Š” ๊ฐ์ฒด์ง€ํ–ฅ์˜ SOLID ์›์น™ ํ˜น์€ GoF์˜ ๋””์ž์ธ ํŒจํ„ด๊ณผ ๊ฐ™์€ ์„ค๊ณ„ ์›์น™ ๋ฐ ๋””์ž์ธ ํŒจํ„ด์ž„

IoC๋Š” ์„ค๊ณ„ ์›์น™์— ํ•ด๋‹นํ•˜๊ณ , DI๋Š” ๋””์ž์ธ ํŒจํ„ด์— ํ•ด๋‹นํ•จ

 

ex) ์„ค๊ณ„ ์›์น™๊ณผ ๋””์ž์ธ ํŒจํ„ด์„ ์š”๋ฆฌ์— ๋น—๋Œ€์–ด๋ณด๊ธฐ

  • ๊น€์น˜ ๋ณถ์Œ๋ฐฅ ๋ง›์žˆ๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•(์„ค๊ณ„ ์›์น™)
    - ์‹ ์„ ํ•œ ์žฌ๋ฃŒ ์‚ฌ์šฉ
    - ์‹  ๊น€์น˜ ์‚ฌ์šฉ
  • ๊น€์น˜ ๋ณถ์Œ๋ฐฅ ๋ ˆ์‹œํ”ผ(๋””์ž์ธ ํŒจํ„ด)
    1. ์˜ค์ผ์„ ๋‘๋ฅธ ํŒฌ์— ์ฑ„์ฌ ํŒŒ๋ฅผ ๋ณถ์•„ ํŒŒ๊ธฐ๋ฆ„์„ ๋งŒ๋“ ๋‹ค.
    2. ์ค€๋น„ํ•œ ํ–„์„ ๋„ฃ๊ณ  ๋ณถ๋‹ค๊ณ , ๊ฐ„์žฅ ํ•œ์Šคํ‘ผ์„ ๋„ฃ์–ด ํ’๋ฏธ๋ฅผ ๋‚ธ๋‹ค.
    ...

์ข‹์€ ์ฝ”๋“œ๋ฅผ ์œ„ํ•ด์„œ Spring์—์„œ IoC์™€ DI๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Œ

โ“ ์ข‹์€ ์ฝ”๋“œ๋ž€?
- ๋…ผ๋ฆฌ๊ฐ€ ๊ฐ„๋‹จํ•ด์•ผํ•จ
- ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๊ณ  ํ‘œํ˜„์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•จ
- ์ฝ”๋“œ๋ฅผ ์ฒ˜์Œ ๋ณด๋Š” ์‚ฌ๋žŒ๋„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•จ
- ์˜์กด์„ฑ์„ ์ตœ์†Œํ™”ํ•ด์•ผ ํ•จ
- ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ ํ•˜๋”๋ผ๋„ ํฌ๊ฒŒ ๊ตฌ์กฐ์˜ ๋ณ€๊ฒฝ์ด ์—†์–ด์•ผ ํ•จ

 

์ฆ‰, IoC์™€ DI๋Š” ์ข‹์€ ์ฝ”๋“œ ์ž‘์„ฑ์„ ์œ„ํ•œ Spring์˜ ํ•ต์‹ฌ ๊ธฐ์ˆ  ์ค‘ ํ•˜๋‚˜์ž„!

์˜์กด์„ฑ

ex) ๋‹ค๋ฆฌ๋ฅผ ๋‹ค์ณ์„œ ๋ชฉ๋ฐœ์„ ์‚ฌ์šฉํ•ด ๊ฑท๊ฒŒ ๋œ๋‹ค๋ฉด ๊ฑท๊ธฐ ์œ„ํ•ด ๋ชฉ๋ฐœ์— ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž„. ์ฆ‰, ์‚ฌ๋žŒ์ด ๋ชฉ๋ฐœ์— ์˜์กด์„ฑ์„ ๋‘๊ฒŒ ๋˜์—ˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Œ

 

ex) ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜์–ด์žˆ๋Š” Consumer์™€ Chicken

public class Consumer {
    void eat() {
    	Chicken chicken = new Chicken();
        chicken.eat();
    }
    
    public static void main(String[] args) {
    	Consumer consumer = new Consumer();
        consumer.eat();
    }
}

class Chicken {
	public void eat() {
    	System.out.println("์น˜ํ‚จ์„ ๋จน๋Š”๋‹ค.");
    }
}
  • ์‹คํ–‰๋˜๋Š”๋ฐ ๋ฌธ์ œ๋Š” ์—†์ง€๋งŒ, ์ค‘๊ฐ„์— Chicken์ด ์•„๋‹Œ Pizza ํด๋ž˜์Šค๋ฅผ ๋„ฃ๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ˆ˜์ •ํ•ด์•ผํ•จ.
  • ์ฆ‰, ์•„๋ž˜ ์ฝ”๋“œ ๋ถ€๋ถ„์ด ๋‘ ๊ฐ์ฒด ์‚ฌ์ด์— ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜์–ด ์žˆ์Œ → ๋ฐ”๊พธ๋ ค๋ฉด ์ € ๋ถ€๋ถ„์„ ๊ณ„์† ์ˆ˜์ •ํ•ด์•ผํ•จ
public class Consumer {
    // ์ด ๋ถ€๋ถ„
    void eat() {
    	Chicken chicken = new Chicken();
        chicken.eat();
    }
    
	...
}

 

  • ๊ฒฐํ•ฉ ์•ฝํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ โ–ถ๏ธŽ Java์˜ Interface ํ™œ์šฉ
public class Consumer {
    // ๋ฉ”์„œ๋“œ์—์„œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ›์Œ
    void eat(Food food) {
    	food.eat();
    }
    
    public static void main(String[] args) {
    	Consumer consumer = new Consumer();
        // ์™ธ๋ถ€์—์„œ new ํ•˜๋ฉด์„œ ๊ฐ์ฒด ๊ตฌํ˜„์ฒด ๋„ฃ๊ธฐ
        consumer.eat(new Chicken());
        consumer.eat(new Pizza());
    }
}

interface Food {
	void eat();
}

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

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

์ฃผ์ž…

์ฝ”๋“œ์—์„œ ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ํ•„์š”๋กœ ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ํ•ด๋‹น ๊ฐ์ฒด์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ

 

ํ•„๋“œ์— ์ง์ ‘ ์ฃผ์ž…

public class Consumer {
    Food food; // Food ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ Consumer ํด๋ž˜์Šค๊ฐ€ ํ•„๋“œ๋กœ ๊ฐ–๊ธฐ(default ์ ‘๊ทผ์ œ์–ด์ž)

    void eat() {
    	this.food.eat();
    }
    
    public static void main(String[] args) {
    	Consumer consumer = new Consumer();
        consumer.food = new Chicken(); // ์ ‘๊ทผ ๊ฐ€๋Šฅ
        consumer.eat();
        
        consumer.food = new Pizza();
        consumer.eat();
    }
}

interface Food {
	void eat();
}

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

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

 

๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ ์ฃผ์ž…

public class Consumer {
    Food food;
    
    void eat() {
    	this.food.eat();
    }
    
    // ๋ฉ”์„œ๋“œ๋กœ ๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ›์•„์™€ ํ•„๋“œ์— ์ฃผ์ž…
    public void setFood(Food food) {
    	this.food = food;
    }
    
    public static void main(String[] args) {
    	Consumer consumer = new Consumer();
        consumer.setFood(new Chicken());
        consumer.eat();
        
        consumer.setFood(new Pizza());
        consumer.eat();
    }
}

interface Food {
	void eat();
}

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

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

 

์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ์ฃผ์ž…

public class Consumer {
    Food food;
    
    // Consumer ์ƒ์„ฑ์ž ๊ตฌํ˜„
    public Consumer(Food food) {
    	this.food = food;
    }

    void eat(Food food) {
    	this.food.eat();
    }
    
    public static void main(String[] args) {
    	// ์ƒ์„ฑ์ž ํ˜ธ์ถœ ์‹œ, Food์— ๊ตฌํ˜„์ฒด ๋„ฃ์Œ
    	Consumer consumer = new Consumer(new Chicken());
        consumer.eat();
        
        consumer = new Consumer(new Pizza());
        consumer.eat();
    }
}

interface Food {
	void eat();
}

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

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

์ œ์–ด์˜ ์—ญ์ „(IoC)

  • ์œ„์—์„œ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ๋œ Consumer๊ฐ€ ์ง์ ‘ Food๋ฅผ ๋งŒ๋“ค์–ด ๋จน์—ˆ์Œ
    • ์ƒˆ๋กœ์šด ์Œ์‹์„ ๋งŒ๋“ค๋ ค๋ฉด ์ถ”๊ฐ€์ ์ธ ์ฝ”๋“œ ์ˆ˜์ • ํ•„์š”ํ–ˆ์Œ
    • ์ œ์–ด์˜ ํ๋ฆ„: Consumer → Food, ์ฆ‰ Consumer๊ฐ€ Food๋ฅผ ์ง์ ‘ ์ œ์–ด
  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ, ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ์ฃผ์ž…๊ณผ ๊ฐ™์ด ์™ธ๋ถ€์—์„œ ๊ตฌํ˜„์ฒด๋ฅผ ์ฃผ์ž…๋ฐ›์Œ
    • ์ œ์–ด์˜ ํ๋ฆ„: Food → Consumer(main์ธ ์™ธ๋ถ€์—์„œ Consumer๋กœ ์Œ์‹ ์ง‘์–ด๋„ฃ์Œ)๋กœ ์—ญ์ „๋จ

๋ฉ”๋ชจ์žฅ ํ”„๋กœ์ ํŠธ์˜ IoC์™€ DI

๋ฌธ์ œ์  1) ๊ฐ์ฒด ์ƒ์„ฑ ์ค‘๋ณต ์ฝ”๋“œ ์กด์žฌ 

package com.sparta.memo.service;


import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import com.sparta.memo.repository.MemoRepository;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class MemoService {
    private final JdbcTemplate jdbcTemplate; // jdbcTemplate ๋ณ€์ˆ˜ ์„ ์–ธ

    // ์ดˆ๊ธฐํ™”๋ฅผ ์œ„ํ•œ ์ƒ์„ฑ์ž
    // ์™ธ๋ถ€์—์„œ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋Š” JdbcTemplate์„ ์—ฌ๊ธฐ์— ๋„ฃ์–ด์คŒ
    // JdbcTemplate ๊ฐ์ฒด๋Š” Spring์—์„œ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•ด์ฃผ๊ณ  ์žˆ์Œ
    public MemoService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public MemoResponseDto createMemo(MemoRequestDto requestDto) {
        // RequestDto -> Entity
        Memo memo = new Memo(requestDto);

        // DB ์ €์žฅ
        MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
        ...
    }

    public List<MemoResponseDto> getMemos() {
        // DB ์กฐํšŒ
        MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
        ...
    }

    public Long updateMemo(Long id, MemoRequestDto requestDto) {
        MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
        // ํ•ด๋‹น ๋ฉ”๋ชจ๊ฐ€ DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
        ...
    }

    public Long deleteMemo(Long id) {
        MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
        // ํ•ด๋‹น ๋ฉ”๋ชจ๊ฐ€ DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
        ...
    }
}
  • MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
  • ์œ„ ์ฝ”๋“œ๊ฐ€ ๊ณ„์† ์ค‘๋ณต๋˜๊ณ  ์žˆ์Œ

MemoService ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ์ด ๋  ๋•Œ ํ•œ ๋ฒˆ๋งŒ MemoRepository๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ํ›จ์”ฌ ํšจ์œจ์ ์ž„

package com.sparta.memo.service;


import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import com.sparta.memo.repository.MemoRepository;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class MemoService {

    private final MemoRepository memoRepository;

    // MemoService๊ฐ€ ์ƒ์„ฑ์ด ๋  ๋•Œ, ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ JdbcTemplate ๋ฐ›์•„์˜ค๊ณ 
    // ๋”ฑ ํ•œ ๋ฒˆ๋งŒ MemoRepository๋ฅผ ๋งŒ๋“ฆ
    public MemoService(JdbcTemplate jdbcTemplate) {
        this.memoRepository = new MemoRepository(jdbcTemplate);
    }

    public MemoResponseDto createMemo(MemoRequestDto requestDto) {
        // RequestDto -> Entity
        Memo memo = new Memo(requestDto);

        // DB ์ €์žฅ
        Memo saveMemo = memoRepository.save(memo);

        // Entity -> ResponseDto
        MemoResponseDto memoResponseDto = new MemoResponseDto(memo);

        return memoResponseDto;
    }

    public List<MemoResponseDto> getMemos() {
        // DB ์กฐํšŒ
        return memoRepository.findAll();
    }

    public Long updateMemo(Long id, MemoRequestDto requestDto) {
        // ํ•ด๋‹น ๋ฉ”๋ชจ๊ฐ€ DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
        Memo memo = memoRepository.findById(id);
        if(memo != null) {
            // memo ๋‚ด์šฉ ์ˆ˜์ •
            memoRepository.update(id, requestDto);
            return id;
        } else {
            throw new IllegalArgumentException("์„ ํƒํ•œ ๋ฉ”๋ชจ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        }
    }

    public Long deleteMemo(Long id) {
        // ํ•ด๋‹น ๋ฉ”๋ชจ๊ฐ€ DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
        Memo memo = memoRepository.findById(id);
        if(memo != null) {
            // memo ์‚ญ์ œ
            memoRepository.delete(id);
            return id;
        } else {
            throw new IllegalArgumentException("์„ ํƒํ•œ ๋ฉ”๋ชจ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        }
    }
}
package com.sparta.memo.controller;

import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.service.MemoService;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api")
public class MemoController {
    private final MemoService memoService; // jdbcTemplate ๋ณ€์ˆ˜ ์„ ์–ธ
    
    public MemoController(JdbcTemplate jdbcTemplate) {
        this.memoService = new MemoService(jdbcTemplate);
    }

    @PostMapping("/memos")
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
        return memoService.createMemo(requestDto);
    }

    @GetMapping("/memos")
    public List<MemoResponseDto> getMemos() {
        return memoService.getMemos();
    }

    @PutMapping("/memos/{id}")
    public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        return memoService.updateMemo(id, requestDto);
    }

    @DeleteMapping("/memos/{id}")
    public Long deleteMemo(@PathVariable Long id) {
        return memoService.deleteMemo(id);
    }
}

๋ฌธ์ œ์  2) ๊ฐ•ํ•œ ๊ฒฐํ•ฉ ์กด์žฌ

public MemoService(JdbcTemplate jdbcTemplate) {
    this.memoRepository = new MemoRepository(jdbcTemplate);
}
  • MemoService๊ฐ€ MemoRepository๋ฅผ ์ง์ ‘ ๋งŒ๋“ค๊ณ  ์žˆ์Œ. ์ฆ‰, ์ œ์–ด ํ๋ฆ„์ด MemoService → MemoRepository
  • MemoController๋„ MemoService๋ฅผ ์ง์ ‘ ๋งŒ๋“ค๊ณ  ์žˆ์Œ. ์ฆ‰, ์ œ์–ด ํ๋ฆ„์ด MemoController → MemoService

โ€ผ๏ธ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ์˜ ๋ฌธ์ œ์ 

1. Controller1์ด Service1 ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์‚ฌ์šฉ

public class Controller1 {
    private final Service1 service1;
    
    public Controller1() {
    	this.service1 = new Service1();
    }
}

 

2. Service1์ด Repository1 ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์‚ฌ์šฉ

public class Service1 {
    private final Repository1 repository1;
    
    public Service1() {
    	this.repository1 = new Repository1();
    }
}

 

3. Repository1 ๊ฐ์ฒด ์„ ์–ธ

public class Repository1 {...}

 

4. ๋งŒ์•ฝ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด,

a. Repository1 ๊ฐ์ฒด ์ƒ์„ฑ ์‹œ DB ์ ‘์† id, pw๋ฅผ ๋ฐ›์•„์„œ DB ์ ‘์† ์‹œ ์‚ฌ์šฉ(์ƒ์„ฑ์ž์— DB ์ ‘์† id, pw ์ถ”๊ฐ€)

public class Repository1 {
	public Repository1(String id, String pw){
    	// DB ์—ฐ๊ฒฐ
        Connection connection = DriverManager.getConnection("~~", id, pw);
    }
}

 

  • Controller 5๊ฐœ๊ฐ€ ๊ฐ๊ฐ Service1์„ ์ƒ์„ฑํ•ด ์‚ฌ์šฉ ์ค‘์ผ ๊ฒฝ์šฐ, Repository1 ์ƒ์„ฑ์ž ๋ณ€๊ฒฝ์— ์˜ํ•ด ๋ชจ๋“  Controller์™€ ๋ชจ๋“  Service์˜ ์ฝ”๋“œ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•จ

 

๋ฉ”๋ชจ์žฅ ํ”„๋กœ์ ํŠธ์—์„œ๋„ MemoService์—์„œ ์ž์‹ ์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ MemoRepository๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด MemoRepository์˜ ์ƒ์„ฑ์ž์— JdbcTemplate์„ ๋„ฃ์–ด์ฃผ๊ณ  ์žˆ์Œ

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ MemoController์—์„œ๋„ MemoService๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ์ž์— JdbcTemplate์„ ๋„ฃ์–ด์ฃผ๊ณ  ์žˆ์Œ

public MemoController(JdbcTemplate jdbcTemplate) {
	this.memoService = new MemoService(jdbcTemplate);
}
...
public MemoService(JdbcTemplate jdbcTemplate) {
	this.memoRepository = new MemoRepository(jdbcTemplate);
}

 

๊ฐ•ํ•œ ๊ฒฐํ•ฉ ํ•ด๊ฒฐ

  • ๊ฐ ๊ฐ์ฒด์— ๋Œ€ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์€ ๋”ฑ 1๋ฒˆ๋งŒ!
  • ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ๋ชจ๋“  ๊ณณ์—์„œ ์žฌ์‚ฌ์šฉ!
  • ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•ด ํ•„์š”๋กœํ•˜๋Š” ๊ฐ์ฒด์— ํ•ด๋‹น ๊ฐ์ฒด ์ฃผ์ž…

1. Repository1 ํด๋ž˜์Šค ์„ ์–ธ ๋ฐ ๊ฐ์ฒด ์ƒ์„ฑ → repository1

public class Repository1 { ... }

// ๊ฐ์ฒด ์ƒ์„ฑ
Repository1 repository1 = new Repository1();

 

2. Service1 ํด๋ž˜์Šค ์„ ์–ธ ๋ฐ ๊ฐ์ฒด ์ƒ์„ฑ(repository1 ์‚ฌ์šฉ) → service1

Class Service1 {
	private final Repository1 repository1;
    
    // repository1 ๊ฐ์ฒด ์‚ฌ์šฉ
    public Service1(Repository1 repository1) {
    	this.repository1 = repository1;
    }
}

// ๊ฐ์ฒด ์ƒ์„ฑ
Service1 service1 = new Service1(repository1);

 

3. Controller1 ์„ ์–ธ(service1 ์‚ฌ์šฉ)

Class Controller1 {
	private final Service1 service1;
    
    // service1 ๊ฐ์ฒด ์‚ฌ์šฉ
    public Controller1(Service1 service1){
    	this.service1 = service1;
    }
}

 

๊ฐ•ํ•œ ๊ฒฐํ•ฉ → ๋А์Šจํ•œ ๊ฒฐํ•ฉ

 

๋ฉ”๋ชจ์žฅ ํ”„๋กœ์ ํŠธ์— ์ œ์–ด์˜ ์—ญ์ „ ์ ์šฉํ•˜๊ธฐ

package com.sparta.memo.controller;

import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.service.MemoService;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api")
public class MemoController {
    private final MemoService memoService; // jdbcTemplate ๋ณ€์ˆ˜ ์„ ์–ธ

    public MemoController(MemoService memoService) {
        this.memoService = memoService;
    }

    @PostMapping("/memos")
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
        return memoService.createMemo(requestDto);
    }

    @GetMapping("/memos")
    public List<MemoResponseDto> getMemos() {
        return memoService.getMemos();
    }

    @PutMapping("/memos/{id}")
    public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        return memoService.updateMemo(id, requestDto);
    }

    @DeleteMapping("/memos/{id}")
    public Long deleteMemo(@PathVariable Long id) {
        return memoService.deleteMemo(id);
    }
}
package com.sparta.memo.service;


import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import com.sparta.memo.repository.MemoRepository;

import java.util.List;

public class MemoService {

    private final MemoRepository memoRepository;

    // MemoService๊ฐ€ ์ƒ์„ฑ์ด ๋  ๋•Œ, ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ JdbcTemplate ๋ฐ›์•„์˜ค๊ณ 
    // ๋”ฑ ํ•œ ๋ฒˆ๋งŒ MemoRepository๋ฅผ ๋งŒ๋“ฆ
    public MemoService(MemoRepository memoRepository) {
        this.memoRepository = memoRepository;
    }

    public MemoResponseDto createMemo(MemoRequestDto requestDto) {
        // RequestDto -> Entity
        Memo memo = new Memo(requestDto);

        // DB ์ €์žฅ
        Memo saveMemo = memoRepository.save(memo);

        // Entity -> ResponseDto
        MemoResponseDto memoResponseDto = new MemoResponseDto(memo);

        return memoResponseDto;
    }

    public List<MemoResponseDto> getMemos() {
        // DB ์กฐํšŒ
        return memoRepository.findAll();
    }

    public Long updateMemo(Long id, MemoRequestDto requestDto) {
        // ํ•ด๋‹น ๋ฉ”๋ชจ๊ฐ€ DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
        Memo memo = memoRepository.findById(id);
        if(memo != null) {
            // memo ๋‚ด์šฉ ์ˆ˜์ •
            memoRepository.update(id, requestDto);
            return id;
        } else {
            throw new IllegalArgumentException("์„ ํƒํ•œ ๋ฉ”๋ชจ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        }
    }

    public Long deleteMemo(Long id) {
        // ํ•ด๋‹น ๋ฉ”๋ชจ๊ฐ€ DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
        Memo memo = memoRepository.findById(id);
        if(memo != null) {
            // memo ์‚ญ์ œ
            memoRepository.delete(id);
            return id;
        } else {
            throw new IllegalArgumentException("์„ ํƒํ•œ ๋ฉ”๋ชจ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        }
    }
}

 

โ“MemoService์™€ MemoRepository๋Š” ๋ˆ„๊ฐ€ ์–ด๋””์„œ ๋งŒ๋“ค์–ด์„œ ๋„ฃ์–ด์ค€๊ฑธ๊นŒ?


IoC Container์™€ Bean

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

์™ธ๋ถ€์—์„œ ์ฃผ์ž…์„ ๋ฐ›๋Š” ์˜์กด์„ฑ ์ฃผ์ž… DI๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ด ์šฐ์„ ๋˜์–ด์•ผ ํ•จ

→ ํ˜„์žฌ Controller ์ž…์žฅ์—์„œ ๋งŒ๋“ค์–ด์ง„ Service ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ ํ•„๋“œ์— ๋„ฃ์–ด์ฃผ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, Service์˜ ๊ฐ์ฒด ์ƒ์„ฑ์ด ์šฐ์„ ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๋œป

 

๏นกSpringํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ๋Œ€์‹ ํ•ด์ฃผ๊ณ  ์žˆ์Œ

 

๋นˆ(Bean): Spring์ด ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด

Spring IoC ์ปจํ…Œ์ด๋„ˆ: 'Bean'์„ ๋ชจ์•„๋‘” ์ปจํ…Œ์ด๋„ˆ

 

๋”ฐ๋ผ์„œ, ์ƒ์„ฑ์ž์—์„œ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…๋ฐ›์„ ๋•Œ๋Š” Bean ๊ฐ์ฒด๋งŒ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์Œ.

Spring Bean ๋“ฑ๋ก๊ณผ ์˜์กด์„ฑ ์ฃผ์ž…

Bean ๋“ฑ๋ก โ–ถ๏ธŽ @Component

Bean์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ ์ž ํ•˜๋Š” Class ์œ„์— @Component ์–ด๋…ธํ…Œ์ด์…˜ ์ž‘์„ฑ

Bean ๋“ฑ๋ก

  • @ComponentScan ์–ด๋…ธํ…Œ์ด์…˜ ์กด์žฌ → @ComponentScan์€ Component๋ฅผ ์ฐพ์•„์ฃผ๋Š” ์—ญํ• 
    1. @ComponentScan์ด ์„ค์ •๋˜์–ด ์žˆ๋Š” ํŒจํ‚ค์ง€ ์œ„์น˜์™€ ๊ทธ ํ•˜์œ„ ํŒจํ‚ค์ง€๋“ค์„ ์ „๋ถ€ ํ™•์ธ
    2. @Component๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ๋Š” class๋“ค์„ ์ „๋ถ€ ์ฐพ์•„์„œ Bean์œผ๋กœ ๋“ฑ๋ก

@ComponentScan

  • ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋Œ€๋ฌธ์ž ๋นผ๊ณ  ex) memoService ์ด๋ฆ„์œผ๋กœ Bean ๋“ฑ๋กํ•ด์คŒ

Bean ๋“ฑ๋ก ์˜ˆ์‹œ

 

์˜์กด์„ฑ ์ฃผ์ž… 1 โ–ถ๏ธŽ @Autowired

์ƒ์„ฑ์ž์—์„œ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…๋ฐ›์„ ๋•Œ๋Š” @Autowired ์–ด๋…ธํ…Œ์ด์…˜์„ ๋‹ฌ์•„์ค˜์•ผํ•จ

๏นกSpring 4.3 ๋ฒ„์ „ ์ดํ›„๋ถ€ํ„ฐ๋Š” @Autowired ์ƒ๋žต ๊ฐ€๋Šฅํ•ด์ง. ํ•˜์ง€๋งŒ ์ƒ์„ฑ์ž ์„ ์–ธ์ด ํ•œ ๊ฐœ์ผ ๋•Œ๋งŒ ์ƒ๋žต ๊ฐ€๋Šฅ

์˜์กด์„ฑ ์ฃผ์ž… @Autowired

  • ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์˜ ์˜์กด์„ฑ ์ฃผ์ž…์ด ์กด์žฌํ•˜์ง€๋งŒ, ์ƒ์„ฑ์ž ์ฃผ์ž…์ด ๊ฐ์ฒด์˜ ๋ถˆ๋ณ€์„ฑ์„ ์ง€์ผœ์ค„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ์ž๋กœ DIํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ
  • ํ•˜์ง€๋งŒ, ๋•Œ์— ๋”ฐ๋ผ์„œ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋”๋ผ๋„ ์ฃผ์ž…ํ•˜๋Š” ๊ตฌํ˜„์ฒด ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” method๋กœ ์ฃผ์ž…์„ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ
  • ํ•„๋“œ ์ฃผ์ž…์˜ ๊ฒฝ์šฐ ์ ‘๊ทผ ์ œ์–ด์ž๊ฐ€ private์ด์–ด์„œ ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†์–ด๋„ @Autowired ์–ด๋…ธํ…Œ์ด์…˜์„ ๋‹ฌ๋ฉด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•จ(์ถ”์ฒœ X)
  • โ€ผ๏ธ Autowired๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด IoC Container์— ์˜ํ•ด์„œ ๊ด€๋ฆฌ๋˜๋Š” Bean class์—์„œ๋งŒ ๊ฐ€๋Šฅํ•จ

์˜์กด์„ฑ ์ฃผ์ž… 2 โ–ถ๏ธŽ Lombok์˜ @RequiredArgsConstructor ์‚ฌ์šฉ

@RequiredArgsConstructor ์–ด๋…ธํ…Œ์ด์…˜์€ final์„ ์ƒ์„ฑ์ž๋กœ ์‚ฌ์šฉํ•จ

@RequiredArgsConstructor ์‚ฌ์šฉ

 

์˜์กด์„ฑ ์ฃผ์ž… 2 โ–ถ๏ธŽ ์ˆ˜๋™์œผ๋กœ ์ฃผ์ž…(ApplicationContext)

ApplicationContext๋Š” BeanFactory ๋“ฑ๋“ฑ์˜ class๋“ค์„ ์ƒ์†๋ฐ›์•„์„œ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•œ Container

BeanFactory๋Š” Bean์˜ ์ƒ์„ฑ, ๊ด€๊ณ„ ์„ค์ • ๋“ฑ์˜ ์ œ์–ด๋ฅผ ๋‹ด๋‹นํ•˜๋Š” IoC ๊ฐ์ฒด

public MemoService(ApplicationContext context) {
    // ๋ฐฉ๋ฒ• 1. Bean์˜ ์ด๋ฆ„์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ
    MemoRepository memoRepository = (MemoRepository) context.getBean("memoRepository");
    this.memoRepository = memoRepository;

    // ๋ฐฉ๋ฒ• 2. Bean ํด๋ž˜์Šค ํ˜•์‹์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ
    MemoRepository memoRepository = context.getBean(MemoRepository.class);
    this.memoRepository = memoRepository;
}
โ€ผ๏ธ Bean ๋“ฑ๋ก ์ˆœ์„œ
1. Spring์ด Run ๋  ๋•Œ, @ComponentScan์ด @Component ์ฐพ์•„์„œ Bean ๋“ฑ๋ก
2. ๋“ฑ๋กํ•œ ํ›„ @Autowired๊ฐ€ ๋‹ฌ๋ ค์žˆ๋Š” ์˜์กด์„ฑ ์ฃผ์ž…(DI)๊ฐ€ ํ•„์š”ํ•œ ๊ณณ๋“ค์— Bean์„ ์ฃผ์ž…ํ•ด ๊ฐ์ฒด ์ƒ์„ฑ๋จ

3 Layer Annotation

3 Layer Annotation์€ @Controller, @Service, @Repository, @RestController๋ผ๋Š” Annotaion์ด ์กด์žฌํ•จ

  • Controller, Service, Repository ์—ญํ• ๋กœ ๊ตฌ๋ถ„์ด ๋˜๋Š” class๋“ค์„ Bean์œผ๋กœ ๋“ฑ๋ก์„ ํ•  ๋•Œ, ๊ทธ ํ•ด๋‹น Bean class์˜ ์—ญํ• ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

3 Layer Annotation

  • ์œ„์—@Component ์–ด๋…ธํ…Œ์ด์…˜ ์กด์žฌํ•จ

  • Controller๋Š” ๋‚ด๋ถ€์—์„œ DispatcherServlet์ด Handler Mapping์„ ํ†ตํ•ด์„œ ์–ด๋–ค Controller์ธ์ง€ ์ฐพ์€ ํ›„ method ํ˜ธ์ถœํ•  ๋•Œ ์‚ฌ์šฉํ•จ → ์ฆ‰, ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Œ