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 ์ด๋ ธํ ์ด์ ์์ฑ


- @ComponentScan ์ด๋
ธํ
์ด์
์กด์ฌ → @ComponentScan์ Component๋ฅผ ์ฐพ์์ฃผ๋ ์ญํ
1. @ComponentScan์ด ์ค์ ๋์ด ์๋ ํจํค์ง ์์น์ ๊ทธ ํ์ ํจํค์ง๋ค์ ์ ๋ถ ํ์ธ
2. @Component๊ฐ ์ค์ ๋์ด ์๋ class๋ค์ ์ ๋ถ ์ฐพ์์ Bean์ผ๋ก ๋ฑ๋ก

- ํด๋์ค ์ด๋ฆ์ ๋๋ฌธ์ ๋นผ๊ณ ex) memoService ์ด๋ฆ์ผ๋ก Bean ๋ฑ๋กํด์ค

์์กด์ฑ ์ฃผ์ 1 โถ๏ธ @Autowired
์์ฑ์์์ ์ธ๋ถ์์ ์ฃผ์ ๋ฐ์ ๋๋ @Autowired ์ด๋ ธํ ์ด์ ์ ๋ฌ์์ค์ผํจ
๏นกSpring 4.3 ๋ฒ์ ์ดํ๋ถํฐ๋ @Autowired ์๋ต ๊ฐ๋ฅํด์ง. ํ์ง๋ง ์์ฑ์ ์ ์ธ์ด ํ ๊ฐ์ผ ๋๋ง ์๋ต ๊ฐ๋ฅ

- ์ฌ๋ฌ ๋ฐฉ๋ฒ์ ์์กด์ฑ ์ฃผ์ ์ด ์กด์ฌํ์ง๋ง, ์์ฑ์ ์ฃผ์ ์ด ๊ฐ์ฒด์ ๋ถ๋ณ์ฑ์ ์ง์ผ์ค ์ ์๊ธฐ ๋๋ฌธ์ ์์ฑ์๋ก DIํ๋ ๊ฒ์ด ์ข์
- ํ์ง๋ง, ๋์ ๋ฐ๋ผ์ ์ด๋ฏธ ๋ง๋ค์ด์ ธ ์๋๋ผ๋ ์ฃผ์ ํ๋ ๊ตฌํ์ฒด ๋ณ๊ฒฝ์ด ํ์ํ ๊ฒฝ์ฐ์๋ method๋ก ์ฃผ์ ์ ํ๋ ์ํฉ์ด ๋ฐ์ํ ์ ์์
- ํ๋ ์ฃผ์ ์ ๊ฒฝ์ฐ ์ ๊ทผ ์ ์ด์๊ฐ private์ด์ด์ ์ธ๋ถ์์ ์ ๊ทผํ ์ ์์ด๋ @Autowired ์ด๋ ธํ ์ด์ ์ ๋ฌ๋ฉด ์ ๊ทผ ๊ฐ๋ฅํจ(์ถ์ฒ X)
- โผ๏ธ Autowired๋ฅผ ์ ์ฉํ๋ ค๋ฉด IoC Container์ ์ํด์ ๊ด๋ฆฌ๋๋ Bean class์์๋ง ๊ฐ๋ฅํจ
์์กด์ฑ ์ฃผ์ 2 โถ๏ธ Lombok์ @RequiredArgsConstructor ์ฌ์ฉ
@RequiredArgsConstructor ์ด๋ ธํ ์ด์ ์ final์ ์์ฑ์๋ก ์ฌ์ฉํจ

์์กด์ฑ ์ฃผ์ 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์ ์ญํ ์ ๋ช ํํ๊ฒ ํํํ๊ธฐ ์ํด ์ฌ์ฉ


- ์์@Component ์ด๋ ธํ ์ด์ ์กด์ฌํจ

- Controller๋ ๋ด๋ถ์์ DispatcherServlet์ด Handler Mapping์ ํตํด์ ์ด๋ค Controller์ธ์ง ์ฐพ์ ํ method ํธ์ถํ ๋ ์ฌ์ฉํจ → ์ฆ, ๋ด๋ถ์์ ์ฌ์ฉํ๊ณ ์์