Spring Framework의 주축이 되는 3가지 개념을 뜻한다.

IoC는 객체의 생성부터 생명주기 관리까지 모든 객체에 대한 제어권을 개발자가 아닌
스프링 컨테이너가 대신 관리하는 것을 말한다.
컴포넌트 의존 관계 설정, 설정, 생명주기를 해결하기 위한 디자인 패턴이다.
➡️객체를 개발자가new로 직접 만들지 않고 스프링이 알아서 만들어주고 주입해준다.
스프링 컨테이너(IoC 컨테이너)는 객체(Bean)를 생성하고 의존성을 주입하며 생명주기를 관리해주는 핵심 컴포넌트이다.

new를 사용해서 객체를 생성하는 것이다.UserService userService = new UserService(new UserRepository());
public class UserService {
private final UserRepository userRepository;
@Autowired //객체를 알아서 주입해주는 애노테이션 즉, UserService를 주입받고있다.
public UserService(UserRepository userRepository) {
this.userRepository = userRepository; //의존성 주입
}
}
1. 빈 객체 생성
@Component, @Service, @Repository, @Controller 등을 스캔해서 객체를 생성2. 의존성 주입(DI)
@Autowired, @Inject ,생성자 주입 등)3. 라이프 사이클 관리
4. AOP 적용
| 컨테이너 이름 | 설명 |
|---|---|
BeanFactory | 단순한컨테이너에서 객체를 생성하고 DI를 처리하는 기능만 한다. BeanFactory에 여러가지 기능을 추가한 것이 ApplicationContext |
ApplicationContext | 가장 많이 사용하는 스프링 컨테이너. 다양한 기능 제공 |
AnnotationConfigApplicationContext | 자바 기반 설정(@Configuration)에서 사용하는 컨테이너 |
WebApplicationContext | 웹 어플리케이션용 컨테이너. DispatcherServlet이 사용함 |
의존성 주입이란 객체 스스로가 의존 객체를 생성하지 않고, 외부(스프링 컨테이너)가 대신 만들어 넣어주는 방식을 뜻한다.DI 작동 방식
- 스프링이
@Service,@Repository,@Component등으로 빈 등록@Autowired로 의존성을 요구한 클래스 발견- 스프링이 해당 빈을 찾아서 생성자/필드/세터를 통해 주입
@Component와 @Bean을 사용한다.@Contoller, @Service, @Repository 모두 @Component를 포함하고 있다. 즉, 위 애너테이션을 사용한 클래스들은 모두 자동으로 Bean으로 등록된다.@Component
public class UserService {
@Autowired
private UserRepository userRepository;
}
@Configuration
public class AppConfig {
@Bean
public MyComponent myComponent() {
return new MyComponent();
}
}
생성자 주입, 필드 주입, 세터 주입 세가지가 있다.@Service
public class UserService {
private final UserRepository userRepository;
@Autowired // 생성자가 하나면 생략 가능
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
📌특징
- final로 선언 가능 → 불변성 유지
- 테스트 시 주입 쉬움
- 의존성이 누락되면 컴파일 또는 런타임 오류 발생 → 안전
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
📌특징
코드가 간결해 보임
하지만 private이라 테스트에서 mock 주입이 불가능
의존 관계를 명확히 알기 어려움 (생성자에 없음)
❌ 테스트 어려움 + 유지보수 불편 → 지양하는 방식
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
📌특징
선택적인 의존성 주입에 적합 (nullable 가능)
런타임 중에도 변경 가능 → 불변성 유지 안 됨
테스트는 가능하지만, 강제성 없음
AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)는 공통적으로 반복되는 기능(관심사, Concern)을 핵심 로직과 분리해서 모듈화 할 수 있도록 해주는 프로그래밍 패러다임이다.
AOP를 사용하면 이 코드를 한 곳에 모아서 관리할 수 있고, 핵심 비즈니스 로직과 분리되어 유지보수성이 높아진다.
| 용어 | 설명 |
|---|---|
| Aspect | 공통 기능을 모듈화한 클래스 (ex: 트랜잭션 관리, 로그 등) Adivce와 Pointcut을 함께 가지고 있다. |
| Advice | Aspect가 실제로 실행되는 공통 기능의 코드 (ex: 메서드 실행 전 로그 출력) |
| Join Point | Advice가 적용될 수 있는 지점 (ex: 메서드 호출 시점) |
| Pointcut | Advice를 적용할 Join Point를 선별하는 기능을 정의한 모듈 |
| Weaving | Advice를 핵심 로직에 적용하는 과정 (컴파일 시 / 로드 시 / 런타임 시) |
| Target | Advice가 적용될 실제 객체 또는 클래스 |
| Proxy | Target을 감싸서 Target에 대한 요청을 대신 받아주는 Wrapping Object |
| Introduction | 타겟 클래스에 코드 변경 없이 신규 메소드나 멤버 변수를 추가하는 기능 |
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("메서드 실행 전: " + joinPoint.getSignature().getName());
}
}
@Aspect : 이 클래스가 Aspect임을 명시@Before : 대상 메서드 실행 전에 Advice 실행execution(* com.example.service.*.*(..)): Pointcut 표현식PSA란 환경의 변화와 관계없이 일관된 방식의 기술로의 접근 환경을 제공하는 추상화 구조를 말한다.공통 API(인터페이스)만 사용해서 코드의 이식성과 유지보수성을 높일 수 있도록 하는 개념이다.원래 Servlet을 사용하려면 HttpServlet을 상속받고 doGet(), doPost()등 오버라이딩하여 사용해야 한다.
@Contorller를 생각해보자. @Controller 어노테이션을 사용하면 요청을 매핑할 수 있는 컨트롤러 역할을 수행하는 클래스가 된다. 그 클래스에서는 @GetMapping과 @PostMapping 어느테이션을 사용해서 요청을 매핑할 수 있다.
이것이 "잘 만든 인터페이스"의 예시이며, 이러한 편의성 제공이 서비스 추상화의 목적이다.
@GetMapping같은 기능들의 뒷단의 복잡한 코드에 대해서 깊게 고려하지 않아도 되고 이런 기술들을 기반으로 하여 기존 코드를 거의 변경하지 않아도 된다.
또한, 실행 서버를 Tomcat이 아닌 netty로 변경하고 싶다면 프로젝트 설정에 spring-boot-starter-web 의존성 대신 spring-boot-starter-webflux 의존성을 받도록 하면 된다.
이렇게 Spring Web MVC는 사용자가 기존 코드를 거의 변경하지 않고, 웹 기술 스택을 간편하게 바꿀 수 있도록 해준다.
Low level로 트랜잭션을 처리 하려면 명시적으로 setAutoCommit()과 commit(), rollback()등을 호출해야한다.
하지만 Spring이 제공하는 @Transactional 어노테이션을 사용하면 단순하게 메소드에 어노테이션을 붙여줌으로써 트랜잭션 처리가 간단하게 이루어진다.
또한, PSA로써 다양한 기술 스택으로 구현체를 바꿀 수있다.
즉, 기존 코드는 변경하지 않은 채로 트랜잭션을 실제로 처리하는 구현체를 사용 기술에 따라 바꿀 수 있는 것이다.