Java 백엔드 개발에 있어서 꼭 배워둬야 할 프레임워크로, 스프링의 핵심기술인 스프링 프레임워크와 스프링 부트에 대해 알아보고자 한다. 먼저 프레임워크가 무엇인지 간단히 살펴보자.
Framework란?
개발하면서 반복되는 코드들을 어떤 규칙에 맞게 쓸 수 있도록 미리 환경을 구성해 놓은 것이다. 라이브러리와 차이점은 개발자가 작성한 코드가 프레임워크에 의해 수동적으로 불려진다는 점이 차이점이다.
자동차를 만들 때 미리 만들어진 차체(뼈대)를 가져다 사용한다면 개발이 훨 편할 것이다. 여기서 프레임워크는 그 "차체"에 해당한다고 볼 수 있다. 이 덕분에 개발자는 뼈대 구조와 반복적인 로직에 신경쓰지 않고, 중요한 비즈니스 로직을 구현하는 데에 집중할 수 있다.
그러면 애플리케이션 프레임워크란?
일반적으로 프레임워크는 특정 업무 분야 또는 한 기술에 집중한다. 반면에 애플리케이션 프레임워크는 애플리케이션 개발에 필요한 모든 과정에 집중한다고 볼 수 있다. 즉, 애플리케이션 프레임워크는 애플리케이션을 개발하는 데에 있어 필요한 모든 업무 분야 및 모든 기술과 관련된 코드들의 뼈대를 제공한다.
Spring의 정의
결론부터 말하면 스프링은 Java 언어 기반의 엔터프라이즈급 애플리케이션을 효율적으로 개발하기 위해 제공되는 오픈 소스 애플리케이션 프레임워크이다. 주요 특징은 다음과 같다.
1. POJO 기반 (Plain Old Java Object)
- 스프링의 가장 큰 특징으로, 바로 POJO 프로그래밍을 지향한다.
- 즉, Spring의 빈(Bean)은 순수 자바 객체 형체를 띠어서 특정 인터페이스나 클래스를 상속, 구현할 필요 없이 자유롭게 설계할 수 있다. (특정 기술이나 환경에 종속되지 않는다.)
- 여기서 순수 Java만을 사용한다는 것은 Java 및 Java의 스펙에 정의된 기술만 사용한다는 것이다.
- 따라서 외부 모듈이나 라이브러리를 가져와서 사용한다면 POJO라고 볼 수 없다.
- 이 POJO 프로그래밍을 위해 스프링이 지원하는 기술로 IoC/DI, AOP, PSA가 있다.
2. 제어의 역전(IoC)
- 스프링의 핵심은 IoC(Inversion of Control) 원칙을 적용한 컨테이너다.
- 애플리케이션 내 객체(빈, Bean이라 부름)의 생성, 생명주기, 의존관계를 개발자가 직접 관리하는 것이 아니라 컨테이너가 대신 관리해 줌으로써 컴포넌트 간 결합도를 크게 낮춰준다.
- 쉽게 말하면, '내가 이것저것 직접 챙겨야지' 에서 '필요할 때 누군가(프레임워크)가 알아서 챙겨준다'로 바뀌는 것이라고 보면 된다.
요리할 때 재료를 직접 사오는 대신, 냉장고에 필요한 재료가 미리 채워져 있다고 생각해 보자. 즉, 스프링에서는 빈을 직접 new 하지 않고 "이게 필요하다"만 선언해 두면 IoC 컨테이너가 알아서 해주는 것이다.
3. 의존성 주입(DI)
- DI(Dependency Injection)는 IoC의 구체적인 구현 방식 중 하나로, 필요한 객체를 직/간접적으로 주입해 주는 메커니즘이다.
- 생성자 주입, 세터 주입, 필드 주입 등 다양한 방식을 지원하여 테스트 용이성과 모듈화 수준을 향상시킨다.
- 예시)
- Engine 인터페이스를 구현한 GasEngine이 있다.
- Car 클래스는 Engine 타입의 의존성을 갖고 있다.
- 스프링 컨테이너가 Car에 적절한 Engine 빈을 주입해 준다.
- 1) 인터페이스와 구현체 정의
// Engine.java
public interface Engine {
void start();
}
// GasEngine.java
import org.springframework.stereotype.Component;
@Component // 스캔 대상 빈으로 등록
public class GasEngine implements Engine {
@Override
public void start() {
System.out.println("가솔린 엔진 시동!");
}
}
- 2) 의존성 주입 대상 클래스(Car)
// Car.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component // 이걸 붙여서 빈(Bean)으로 등록함
public class Car {
private Engine engine;
// (1) 생성자 주입 방식
@Autowired
// @Autowired를 이용해 스프링 컨테이너가 Engine 타입 빈(GasEngine)을 Car에 주입(DI)해준다.
public Car(Engine engine) {
this.engine = engine;
}
// (2) 세터 주입 방식
// @Autowired
// public void setEngine(Engine engine) {
// this.engine = engine;
// }
public void drive() {
engine.start();
System.out.println("차가 달립니다!");
}
}
- 3) 스프링 설정 클래스
// AppConfig.java
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig { }
- 4) 애플리케이션 구동
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
Car car = ctx.getBean(Car.class);
car.drive();
}
}
- 위처럼 진행했을 경우 실행 결과는 다음과 같다.
가솔린 엔진 시동!
차가 달립니다!
- 어려운 부분은 넘어가고 결론적으로 스프링 DI가 사용되면:
스프링이 실행 시점에 알아서 빈을 생성·관리·주입해 주기 때문에 코드의 응집도가 높아지고, 결합도를 낮게 작성할 수 있다.- Car는 Engine 인터페이스 타입의 필드만 알고 있을 뿐, 실제로 어떤 구현체(Gas일지, Electric일지)가 주입될지는 전혀 모른다.
- 단지 받은 Engine 인스턴스에 drive()와 같은 메서드가 존재할 것이라는 가정만 할 뿐이다.
- 이 덕분에 Car 코드는 구체 구현에 의존하지 않고, 인터페이스에만 의존하게 되어 결합도가 낮아진다.
- 결과적으로 구현체를 바꾸어도 (가솔린 엔진 -> 전기 엔진) Car 코드를 수정할 필요가 없어진다.
4. 관점 지향 프로그래밍(AOP: Aspect-Oriented Programming)
- 로깅, 트랜잭션 관리, 보안 검사 등 애플리케이션 전반에 걸쳐 공통으로 적용되는 부가기능을 모듈화하여 깔끔하게 분리해준다.
- 즉, 공통 기능을 코드에 흩뿌리지 않고(중복 방지) 한 곳에 모아두어 필요할 때만 꺼내 쓰기 위한 기법이다.
- 이를 통해 비즈니스 로직은 깔끔하게, 공통 관심사는 중앙에서 효율적으로 관리할 수 있다.
5. 일관된 서비스 추상화(PSA: Portable Service Abstraction)
- 백엔드 개발에서 DB는 떼어놓기 어렵고 그 종류는 정말 다양하며 각각의 사용방법이 존재한다.
- 스프링은 DB 인터페이스를 추상화한 인터페이스를 제공하기 때문에, 스프링을 사용하면 동일한 사용방법을 유지한 채로 DB를 변경할 수 있다.
- 그 중에서 Java를 사용하여 DB에 접근하는 방법을 규정한 인터페이스를 JDBC(Java DataBase Connectivity)라고 한다.
- 이처럼 특정 기술과 관련된 서비스를 추상화하여 일관된 방식으로 사용할 수 있도록 한 것을 PSA라 한다.
6. 확장성과 호환성
- 다양한 서드파티 라이브러리(Hibernate, JPA, Quartz 등)와 쉽게 통합되며, Java EE의 EJB 등 무거운 컴포넌트 모델을 대체해 왔다.
- 최근에는 Spring Boot를 통해 설정 편의성과 자동 구성을 강화하여, 더 빠르고 간편하게 애플리케이션을 개발할 수 있게 지원하고 있다.
요약
정리하자면, Spring Framework는 POJO를 지향하는 IoC/DI 기반으로 애플리케이션의 결합도를 낮추고 AOP로 공통 기능을 모듈화하며, 다양한 모듈을 통해 데이터 접근부터 웹 MVC, 테스트까지 통합적으로 지원하는 경량형 Java 프레임워크라고 할 수 있다.
다음 글에서는 스프링 사용을 위해 간단히 스프링 설정을 도와주는 Spring Boot에 대해 알아보겠다.
참고 글:
https://codestates.com/blog/content/스프링-스프링부트
스프링과 스프링부트(Spring Boot)ㅣ정의, 특징, 사용 이유, 생성 방법
스프링은 Java 백엔드 개발에 있어 떼어놓을 수 없는 프레임워크입니다. Java 백엔드의 핵심 기술이 되는 스프링 프레임워크와 스프링 부트가 무엇인지, 나아가 스프링 부트를 활용하여 프로젝트
www.codestates.com
'개발 > Spring' 카테고리의 다른 글
| [Spring] Swagger UI와 OpenAPI 문서화 정리 (0) | 2026.07.31 |
|---|---|
| [Spring] Spring Boot JPA 동작 원리와 CRUD 정리 (0) | 2026.07.31 |
| [Spring] MVC 패턴과 Spring MVC 동작 원리 정리 (0) | 2026.07.28 |
| [Spring] DTO는 무엇일까? (0) | 2025.09.08 |
| [Spring] Spring Boot란? (0) | 2025.07.07 |