Back-End/Springboot

[Springboot] 2장 IoC (제어의 역전) 과 DI(의존성 주입)

Tinkies 2025. 2. 27. 00:33

1. IoC (제어의 역전)

Spring boot의 제어의 역전(Inversion of Control, IoC)은 객체의 생성 및 의존성을 관리하는 책임을 프레임워크에 맡기는 디자인 패턴으로 전통적인 프로그래밍에서 객체가 직접 다른 객체를 생성해 의존성을 관리하나, IoC에서는 객체가 필요한 의존성을 외부에서 주입받습니다.

 

  • 장점
    • 유연성: 객체 간의 결합도를 낮춰 시스템을 유연하게 만듬
    • 테스트 용이성: Mock 객체를 사용해 단위 테스트를 쉽게 할 수 있음
    • 재사용성: 동일한 인터페이스를 구현한 여러 객체를 쉽게 교체

2. DI (의존성 주입)

의존성 주입(Dependency Injection, DI)는 IoC의 한 방식으로, 객체가 필요로 하는 의존성을 외부에서 주입해주는 방법입니다.

 

종류

  • 생성자 주입:
@Service
public class Dependercy {

    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

}
  • 세터 주입:
@Service
public class UserService {

    private UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
  • 필드 주입:
@Service
public class FieldService {

    @Autowired
    private UserRepository userRepository;
}

3. DI 출력법

Spring Boot에서 DI를 활용해 서비스를 호출하고 결과를 출력하는 방법을 살펴보겠습니다.

src/main/java/com/example/fileupload/
├── FileUploadApplication.java
├── controller/
│   └── FileController.java
├── service/
│   ├── FileService.java
│   ├── FileServiceImpl.java
│   └── FileServiceWithSetter.java
└── model/
    └── FileResponse.java (선택적으로 사용)
  • FileUploadApplication.java
package com.example.fileupload;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FileUploadApplication {

    public static void main(String[] args) {
        SpringApplication.run(FileUploadApplication.class, args);
    }
}
  • FileService.java
package com.example.fileupload.service;

public interface FileService {

    String createFile(String fileName, String content);
}
  • FileSeervicelmpl.java (의존성 주입)
package com.example.fileupload.service;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.springframework.stereotype.Service;

@Service
public class FileServiceImpl implements FileService {

    @Override
    public String createFile(String fileName, String content) {
        try {
            File file = new File(fileName);
            FileWriter writer = new FileWriter(file);
            writer.write(content);
            writer.close();
            return "File created: " + fileName;
        } catch (IOException e) {
            throw new RuntimeException("Error creating file: " + e.getMessage(), e);
        }
    }
}
  • FileServiceWithSetter.java (세터 주입)
package com.example.fileupload.service;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.springframework.stereotype.Service;

@Service
public class FileServiceWithSetter implements FileService {

    @Override
    public String createFile(String fileName, String content) {
        try {
            File file = new File(fileName);
            FileWriter writer = new FileWriter(file);
            writer.write(content);
            writer.close();
            return "File created with setter: " + fileName;
        } catch (IOException e) {
            throw new RuntimeException("Error creating file: " + e.getMessage(), e);
        }
    }
}
  • FileController.java
package com.example.fileupload.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.example.fileupload.service.FileService;

@RestController
@RequestMapping("/api/files")
public class FileController {

    private final FileService fileService;

    @Autowired
    public FileController(@Qualifier("fileServiceImpl") FileService fileService) {
        this.fileService = fileService;
    }

    @PostMapping("/constructor")
    public String createFileWithConstructor(@RequestParam String fileName, @RequestParam String content) {
        return fileService.createFile(fileName, content);
    }
}

3. API 테스트

이제 각각의 주입 방식에 따른 API 테스트를 해보겠습니다.

  • Postman 사용
    • Postman을 열고 새로윤 요청을 생성
    • 요청 유형을 POST로 설정
  • 생성자 주입 테스트
    • URL: http://localhost:8080/api/files/constructor
  • Body 탭에서 x-www-form-urelencoded 선택
  • key와 Value 내용 쓰고 send 버튼 클릭

 

GitHub - Koras02/springboot-tutorial: https://thinky.tistory.com/category/Back-End/Springboot

https://thinky.tistory.com/category/Back-End/Springboot - Koras02/springboot-tutorial

github.com

 

LIST