[LG CNS AM INSPRIRE CAMP 1기] Springboot 들어가기전 알아야할 핵심 개념 3가지 IoC, DI, AOP

2025. 1. 22. 16:31·LG CNS AM CAMP 1기
🔑kudos to do your job!

💡 제어의 역전 (IoC, Inversion of Control)


📃 제어의 역전(IoC)은 프로그램의 흐름 제어나 객체 생성을 개발자가 아닌 프레임워크가 담당하는 설계 패턴입니다. 개발자는 객체 생성과 관리에 집중하지 않아도 되고, 애플리케이션의 비즈니스 로직에만 신경 쓰면 됩니다.
쉽게 말하면, "내가 객체를 만들고 관리하는 게 아니라, 프레임워크가 알아서 해주는 방식"입니다 그래서 Inversion은 "기존 전통적인 흐름과 반대로 작용한다"라고 할 수 있습니다

 

  • 전통적인 방식: 개발자가 필요한 객체를 생성하고 관리.
  • IoC 방식: 프레임워크(Spring 등)가 객체 생성과 관리를 담당.

 

💻CODE

// 옛날 방식: 필요한 객체를 직접 생성
MyService myService = new MyService();
myService.doSomething();

// IoC 방식
// Spring Framework가 객체를 생성하고 관리
@Component
public class MyService {
    public void doSomething() {
        System.out.println("작업 수행 중...");
    }
}

@Autowired
private MyService myService; // Spring이 알아서 주입

⬆️ 프레임워크가 객체를 관리하고 애플리케이션에 적절히 주입합니다

 

💡 의존성 주입 (DI, Dependency Injection)


📃 의존성 주입은 객체가 필요로 하는 다른 객체(의존성)을 직접 생성하지 않고 외부에서 주입받는 설계 방식입니다. 이 방식은 코드간의 결합도를 낮추고 테스트와 유지보스를 더 쉽게 만듭니다

💻옛날 방식

public class MyService {
    private MyRepository repository;

    public MyService() {
        this.repository = new MyRepository(); // 직접 생성
    }
}

💻DI 방식

@Component
public class MyService {
    private final MyRepository repository;

    @Autowired
    public MyService(MyRepository repository) { // 외부에서 주입
        this.repository = repository;
    }
}

⬆️ 두개의 방식을 예로 설명을 들었지만, 그냥 DI 방식은 자바 객체 생성자의 느낌이 아닌가?라는 생각이 들어서, 또 다른 예를 찾아봤습니다

💻 차량 색깔 예시

// 일반 생성자
Color red = new Color("RED");
Car car1 = new Car(red);  // 매번 이렇게 해야함

// 스프링 DI
@Component
public class Car {
    private final Color color;
    
    @Autowired
    public Car(Color color) { // 스프링이 설정에 따라 알아서 주입
        this.color = color;
    }
}

⬆️ 위와 같은 차량의 색을 변경하는 예시로 보았을때, 우리는 일반적으로 Car객체에서 new 생성자를 통해 새로운 car를 정의해줬었죠? 하지만 DI 방식은 @Autowired라는 방식으로 스프링이 설정에 따라서 주입하도록 설정을 해준다는 것입니다

💻AppConfig

@Configuration
public class AppConfig {
    @Bean
    public Color color() {
        return new Color("RED");  // 여기만 BLUE로 바꾸면 모든 Car가 파란색으로!
    }
}

⬆️ 그래서 위와 같은 Config 클래스에서 @Bean 어노테이션의 수정만을 통해서 유연하게 관리를 할 수 있다는 점을 기억하면 될 것 같습니다

📃 그래서 실제 업무환경에서 아래와 같이 설정을 관리하며 진행할 수 있다고 하네요

💻실무 환경에서

// 개발 환경용 설정
@Configuration
@Profile("dev")
public class DevConfig {
    @Bean
    public PaymentGateway paymentGateway() {
        return new TestPaymentGateway();  // 실제 결제 없이 테스트
    }
    
    @Bean
    public Repository repository() {
        return new InMemoryRepository();  // 실제 DB 대신 메모리 사용
    }
}

// 실제 운영 환경용 설정
@Configuration
@Profile("prod")
public class ProdConfig {
    @Bean
    public PaymentGateway paymentGateway() {
        return new KakaoPayGateway();  // 실제 카카오페이 결제
    }
    
    @Bean
    public Repository repository() {
        return new MySQLRepository();  // 실제 MySQL DB 사용
    }
}

⬆️ 이렇게 환경별로 다른 구현체를 사용할 수 있고, 애플리케이션 코드는 전혀 건드리지 않아도 됩니다. 이는 설정 파일만으로 시스템의 동작을 완전히 다르게 가져갈 수 있다는 큰 장점이 있습니다

💡 관점 지향 프로그래밍 (AOP, Aspect-Oriented Programming)


📃 관점 지향 프로그래밍(AOP)은 여러 객체나 메서드에서 공통적으로 수행되어야 하는 기능(로깅, 보안, 트랜잭션 관리 등)을 별도로 분리해 관리하는 프로그래밍 기법입니다.
쉽게 말하면, "공통된 작업(예: 로그 남기기)은 한 곳에서 관리하고, 필요한 곳에 자동으로 적용하는 방식"입니다

AOP의 장점:

  • 중복 코드 감소
  • 코드 간결화
  • 공통 기능 관리의 일관성 향상

💻 옛날 방식

public class MyService {
    public void doWork() {
        System.out.println("작업 시작"); // 로깅 코드
        // 작업 실행 코드...
        System.out.println("작업 끝"); // 로깅 코드
    }
}

💻 AOP 방식

@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logStart(JoinPoint joinPoint) {
        System.out.println("작업 시작: " + joinPoint.getSignature().getName());
    }

    @After("execution(* com.example.service.*.*(..))")
    public void logEnd(JoinPoint joinPoint) {
        System.out.println("작업 끝: " + joinPoint.getSignature().getName());
    }
}

⬆️ 사실 이렇게 보면 AOP 방식이 더 번거로워 보일 수도 있습니다. 하지만 우리가 실제로 개발하는 회사의 코드는 보통 방대한 양을 가집니다. 옛날 방식처럼 작업 실행 코드마다 실행 시작과 종료를 정의해주는 방식은 관리와 유지보수 측면에서 비효율적입니다. 반면, Aspect로 공통 기능을 분리하고 필요한 메서드에 자동으로 적용되도록 설정하는 방식은 코드의 중복을 줄이고 유지보수를 쉽게 만들어주는 혁신적인 접근법이라고 할 수 있습니다

📝 SUMMARY


이 글을 보는 모든 분들이 느끼겠지만, 뭐가 편하다는 건지 와닿지 않을 수도 있습니다. 그건 우리가 과거의 방식으로 프로그램을 구현해보지 않았기때문이 아닌가 싶네요. 그래서 이해가 되지 않는다면, 그냥 일단 받아드리는 것도 좋을 것 같네요

📌 IoC: 객체 생성과 관리의 책임을 개발자에서 프레임워크로 넘김

📌 DI: 객체를 직접 생성하지 않고, 외부에서 주입받음으로써 결합도 감소

📌 AOP: 공통된 기능을 분리하여 재사용성을 높이고, 코드를 간결하게 관리

저작자표시 비영리 변경금지 (새창열림)
'LG CNS AM CAMP 1기' 카테고리의 다른 글
  • [LG CNS AM INSPIRE CAMP 1기] 세션 기반 인증 vs. 토큰 기반 인증
  • [LG CNS AM INSPIRE CAMP 1기] JPA와 MyBatis 어떤 선택을 해야할까요?
  • [LG CNS AM INSPIRE CAMP 1기] 어노테이션과 Maven 빌드 관리 도구 빠르게 이해하기
  • [LG CNS AM INSPIRE CAMP 1기] 제네릭 Generic 완벽하게 이해하기
Jelong
Jelong
커스텀 웹: https://jaehong-park.com Github: https://github.com/qkrwoghd04
  • Jelong
    24/7 Developer's Note
    Jelong
  • 전체
    오늘
    어제
    • 분류 전체보기
      • Software Engineering
      • Ubuntu
      • Network
      • JavaScript
      • Web
      • Interaction Design
      • React Native
      • React
      • Algorithm
      • Java
      • Database design
      • IT Trend
      • TroubleShooting
      • AWS
      • Interview
      • LG CNS AM CAMP 1기
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    BST
    화이트 박스 테스트
    오블완
    java
    GPT-4
    AWS
    ChatGPT
    이진트리
    mininet
    heap
    소프트웨어 공학
    expo
    티스토리챌린지
    자바스크립트
    블랙 박스 테스트
    알고리즘 분석
    typescript
    prototyping
    javascript
    frontend
    알고리즘
    JS
    미니넷
    html
    React
    자바
    generic
    데이터 구조
    css
    Queues
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
Jelong
[LG CNS AM INSPRIRE CAMP 1기] Springboot 들어가기전 알아야할 핵심 개념 3가지 IoC, DI, AOP
상단으로

티스토리툴바