HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
[New] 타일러팀
[New] 타일러팀
/
🤖
IoC(Inversion of Control) : 제어의 역전
🤖

IoC(Inversion of Control) : 제어의 역전

Category
Spring
Created
Apr 9, 2022 11:11 AM
Person
State
완료

Inversion of Control(IoC) : 제어의 역전


  • 프로그램의 제어 흐름을 직접 제어하는 것이 아니라, 외부에서 관리하는 것
  • 객체의 생성과 소멸, 그리고 객체간의 의존관계를 설정하는 행위
    • 모두 프레임워크가 대신 해준다 : 주도권이 역전됨 → 제어의 역전
    • 프레임워크가 흐름을 주도하면서 개발자가 만든 어플리케이션 코드를 사용한다.
  • 이렇게 IoC가 일어나는 공간을 IoC 컨테이너라고 부른다.
❓
도대체 무슨 말이야? 분명 코드를 작성한건 나인데, 왜 자꾸 주도권이 프레임워크에 있다는 거지? 🤔 → 이를 이해하기 위해, 프레임워크를 사용할때와 사용하지 않을 때를 비교해보자
 

(1) 직접 객체를 생성하고 의존관계를 설정해주는 경우


public class BeanKor { public void sayBean(String name){ System.out.println("한국 콩!"); } } public class BeanEng { public void sayBean(String name){ System.out.println("English Bean!"); } }
public class YummyBean { public static void main(String[] ars){ // BeanKor bean = new BeanKor(); // 한국 콩! BeanEng bean = new BeanEng(); // English Bean! bean.sayBean(); } }
  • main에서 BeanEng를 BeanKor로 바꿔줘야 함 : YummyBean은 BeanEng/Kor에 의존성을 가지고 있다
    • YummyBean의 기능을 바꾸고자 할 때, BeanEng/Kor도 함께 바꿔줘야 하기 때문이다.
  • 이러한 번거로움을 해결해주기 위해서는 객체의 인스턴스를 외부에서 생성받을 필요가 있다. (의존성 주입)
 

(2) 의존관계를 외부로부터 받아오는 경우 (의존성 주입)


public interface Bean { public void sayBean(); } public class BeanKor implements Bean{ public void sayBean(){ System.out.println("한국 콩!"); } } public class BeanEng implements Bean{ public void sayBean(){System.out.println("English Bean!");} }
public class YummyBean { public static void main(String[] ars){ Bean bean = new BeanKor(); // 한국 콩! // Bean bean = new BeanEng(); // English Bean! bean.sayBean(); } }
→ 생성자를 이용한 의존성 주입 (생성자에 따라 전달받는 객체가 달라진다)
  • 하지만 여전히 출력되는 값을 바꾸기 위해선 소스코드의 수정이 필요하다.
  • 더 개선시킬 수 있을까?
 

(3) 프레임워크가 대신 객체를 생성하고 의존관계를 설정해주는 경우 (IoC)


public interface Bean { public void sayBean(); } public class BeanKor implements Bean{ public void sayBean(){ System.out.println("한국 콩!"); } } public class BeanEng implements Bean{ public void sayBean(){ System.out.println("English Bean!"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=".../beans/spring-beans.xsd"> <bean id="Bean" class="BeanKor"/> <!--<bean id="Bean" class="BeanEng"/>--> </beans>
→ Bean에 주입할 객체에 대한 정보가 담겨있는 설정 파일
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.FileSystemResource; public class YummyBean { public static void main(String[] ars){ BeanFactory factory = new XmlBeanFactory (new FileSystemResource("resources/beans.xml")); Bean bean = factory.getBean("bean", Bean.class); bean.sayBean(); // 한국 콩! } }
→ bean이 사용하는 클래스 이름(BeanEng/Kor)을 코드에 직접 기술하지 않는다(의존성이 없다).
  • 소스 코드의 변경 없이 환경설정만으로도 프로그램을 제어할 수 있다.
  • 이것이 가능한 이유는, 객체의 생성과 주입을 모두 스프링 프레임워크가 주도하고 있기 때문 (IoC)
    • 프로그래머는 BeanKor 클래스와 BeanEng클래스를 정의하기만 했다.
    • 기존 코드에서처럼 bean에 BeanKor를 넣어줄지, BeanEng를 넣어줄지 결정하지도 않았고, newBeanKor 따위의 생성자로 객체를 생성하지도 않았다.
    • 스프링이 스스로 설정 파일을 읽고, 거기 써져 있는대로 객체를 생성한 다음 반환해줬다 : 주도권 을 가짐
 

프레임워크가 생산성을 높여주는 이유


  • 프레임워크는 뼈대를 제공하고, 그 위에 개발자가 코드를 올려 동작하게끔 한다.
  • 개발자 입장에선 로직에 더 집중할 수 있고, 객체지향 개발에 있어서 시스템을 일관성있게 관리할 수 있다.
  • 여러 개발자들이 각자의 취향에 따라 설계하고 코딩한다면 관리가 어렵지만, 프레임워크가 제공하는 뼈대와 가이드에 따라 개발하면 시스템의 유지/보수가 용이하다.
  • 예) 기존에 쓰던 객체를 버리고, 새로운 객체를 사용해야 하는 경우
    • [상황] 5000원 할인권만 뿌리고 있었는데, 50% 할인권을 뿌려야 한다고요?
      • (1)의 방법 : 새 클래스 정의하고, 코드 일일이 돌면서, ctrl+f 해가면서, 일일이 수정 작업ㅠ
      • (3)의 방법 : 새 클래스를 정의한 다음, 설정 파일만 수정해주면 끝!
 

참고자료


스프링 핵심 원리 - 기본편 - 인프런 | 강의
초급자를 위해 준비한 [웹 개발, 백엔드] 강의입니다. 스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다. 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보세요! 본 강의는 자바 스프링 완전 정복 시리즈의 두 번째 강의입니다. 우아한형제들 최연소 기술이사 김영한의 스프링 완전 정복 로드맵을 먼저 확인해주세요.
스프링 핵심 원리 - 기본편 - 인프런 | 강의
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard
스프링 핵심 원리 - 기본편 - 인프런 | 강의
mo-world.tistory.com
https://mo-world.tistory.com/entry/IOC%EC%99%80-DI-%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B0%9C%EB%85%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EC%84%A4%EB%AA%85
 

함께 나눈 이야기


  • IoC는 Profile/Property/Resource 등의 외부 설정파일 주입에 주로 사용되고(사용 DB 등) 위 예제에서처럼 객체에서는 IoC가 잘 안일어나는 것 아닐까? 상품권 객체에 IoC를 사용하는 것이 맞을까?
  • 하지만 DI 기능은 IoC 기능의 일부 아닌가?
  • 하지만 그럼 객체의 생명주기와 관계 설정을 담당하는 IoC 컨테이너는 무엇인가?
  • 정확히 언제 IoC의 이득을 볼 수 있는지, 정확히 언제 IoC의 기능을 사용할 수 있는지를 정리해보면 좋을 것 같다!