1. 엔터프라이즈 애플리케이션과 Spring의 탄생 배경
1) 엔터프라이즈 앱과 기존 기술의 한계 (EJB)
- JDK와 EJB: 과거 자바 엔터프라이즈 환경(Java EE)에서는 EJB(Enterprise JavaBeans)라는 기술을 표준으로 사용.
- EJB의 단점: 너무 무겁고 실행 속도가 느렸으며, 고가의 유료 WAS가 필요하게 됨. 자바 객체 하나를 만들더라도 프레임워크가 제공하는 무거운 인터페이스를 강제로 상속(implements, extends)받아야만 했기에 코드가 프레임워크와 강하게 결합되어 테스트도 어렵고 자바 객체 지향의 매력이 사라짐. (코드 지저분함 + SOLID 원칙을 지키기 어려움)
- 이름의 변화: 이후 EJB 중심의 사양은 아파치 재단을 거쳐 현재는 Jakarta EE라는 이름으로 이관되었으며, 스프링도 이 자카르타의 표준 인터페이스를 가져와 내부적으로 활용합니다.
2) 스프링 프레임워크(Spring Framework)의 등장
EJB의 무거움에 반발하여 등장한 오픈소스 경량 프레임워크. (Spring GitHub 공식 저장소)
- POJO(Plain Old Java Object) 지향: 특정 프레임워크나 인터페이스에 종속되지 않는 강제로 상속/구현하지 않은, 순수하고 표준적인 자바 객체(자바빈즈 스타일)를 지향하자는 패러다임
- 100% 무조건 상속/구현을 금지하는 것은 아니며, 비즈니스 도메인을 표현하기 위한 인터페이스 상속 등은 객체지향 설계를 위해 적극 권장
- 핵심 목표: 개발자가 로깅, 트랜잭션 같은 주변 기술 설정보다 실제 비즈니스 로직 구현에만 집중할 수 있도록 돕는 것.
- 스프링 IoC는 개발자가 그냥 순수한 자바 클래스(POJO)를 짜기만 하면, 컨테이너가 알아서 객체를 대신 생성하고 관계를 맺어(DI) 줌. 즉, IoC 덕분에 개발자는 코드를 오염시키지 않고 POJO 패러다임을 유지할 수 있게 된 것.
2. Spring의 3대 핵심 개념
Spring의 핵심 기술으로 IoC/DI(코드의 유연성 + 결합도가 낮아짐), AOP(반복되는 코드 떼어내기), PSA(기술 추상화하여 제공)가 있다. ( 세가지가 삼각형의 각 꼭짓점을 이루며, 삼각형의 바탕에 위치하는 가장 본질적인 개념인 POJO와 함께 "삼각형 + 1"이라고도 부름)
① IoC (Inversion of Control, 제어의 역전) & DI (Dependency Injection, 의존성 주입)
- 의존성(Dependency)이란?: 어떤 클래스(Client)가 내부 필드로 다른 클래스(A)의 참조값을 필요로 하는 상태를 말함.
- 강한 결합의 문제: 개발자가 직접 new 연산자로 의존 객체를 직접 생성하고 주입(setter나 생성자 호출)하면 두 클래스 간의 결합도가 높아져, 하나를 바꿀 때 전체 코드를 수정해야 함. ("Objects don't new their dependencies")
- 제어의 역전(IoC): 객체의 생성과 생명주기 관리, 의존성 연결(Wiring)의 제어권을 개발자가 아닌 Spring IoC 컨테이너에 넘겨주는 것
- 의존성 주입(DI): 컨테이너가 필요로 하는 객체(A → B → C)를 알아서 생성하고 조립하여 주입해 주는 기술.
- 생성자 주입: 가장 권장되는 방식으로, SOLID의 S(단일 책임 원칙)와 O(개방-폐쇄 원칙, OCP)을 지키며 유연하게 확장할 수 있게 한다.
💡 Spring IoC Container와 Bean
- 컨테이너(Container): 물류 컨테이너가 화물을 규격화하여 수송 혁신을 이룬 것처럼(도커의 고래 고안 배경과 유사), 객체들을 규격화하여 관리한다. 실체는 ApplicationContext 인터페이스의 구현체들. (예: GenericApplicationContext)
- 빈(Bean): Spring IoC 컨테이너가 주체적으로 생성, 조립, 관리하는 자바 객체. 주로 @Configuration과 @Bean 또는 스테레오타입 어노테이션(@Service, @Component 등)을 통해 메타데이터로 등록됨. (단, 일반 String 필드 같은 것은 주입 대상이 아님)
② AOP (Aspect-Oriented Programming, 관점 지향 프로로그래밍)
- 횡단 관심사(Cross-cutting Concerns)/공통 관심사 분리: 로그인, 회원가입, 상품 검색 같은 핵심 비즈니스 로직(도메인)과 보안, 로그 출력, 트랜잭션 관리 같은 공통 반복 코드(보일러플레이트)를 분리하여 모듈화하는 기술.
- 구현 원리 (프록시 패턴): 타깃 객체를 직접 호출하는 대신, 껍데기인 프록시(Proxy) 객체를 앞에 세워 공통 로직을 실행한 뒤 타깃을 호출.
- JDK 동적 프록시 (자바 서드파티/기본 제공): 인터페이스가 있을 때 이를 구현하여 프록시 생성 (invoke 메서드 활용).
- CGLIB: 인터페이스가 없는 일반 클래스를 상속받아 바이트코드를 조작하여 프록시 생성.
- 리플렉션 (Reflection): 런타임(프로그램 실행 중)에 클래스의 메타 정보를 분석하고 동적으로 객체를 다루는 기술. 접근 제어자인 private 모디파이어까지 깨버리고 내부 필드나 메서드에 접근할 수 있어 프록시 기술의 근간이 됨.
- 이를 통해 비즈니스 코드의 가독성과 유지보수성을 극대화.
더보기
ℹ️ 도메인 주도 설계(DDD) 기반 패키지 구조
현대 백엔드 개발에서는 기능(Layer) 중심이 아닌 도메인(비즈니스 단위)별로 패키지를 구성하는 DDD 방식을 관례로 많이 사용. 각 도메인 내부에 Controller, Service, Repository(DAO) 등을 모아두어 유지보수성을 높임.
- account: 회원가입, 회원 정보 관리 등 사용자 계정 관련 도메인
- oauth: 구글, 카카오, 네이버 등 소셜 로그인 처리
- post: 게시판, 게시글 CRUD 관련 비즈니스 로직
- security / cors: 로그인/로그아웃 인증 및 인가 시스템, 교차 출처 자원 공유(CORS) 설정
- smtp / s3: 이메일 전송, AWS S3 파일 업로드 같은 인프라성 서비스
- Tip: admin과 같이 너무 포괄적인 이름보다는 세부 도메인별로 명확하게 찢어서 관리하는 것이 좋음.
③ PSA (Portable Service Abstraction, 이식 가능한 서비스 추상화)
- 데이터베이스나 구동 환경 등 내부 기술이 바뀌어도 개발자는 기존 코드를 그대로 유지할 수 있도록, 동일한 방식으로 코드를 작성할 수 있게 해주는 추상화 계층. (JDBC, JPA, 트랜잭션, 메시징 등)
- 비유: 유닉스(UNIX) 이전에는 하드웨어가 바뀌면 OS와 소프트웨어를 새로 다 뜯어고쳐야 했으나, 운영체제가 하드웨어를 추상화하면서 생산성 증가.
3. Spring Boot와의 연관성
- Spring Framework와의 관계: Spring Boot는 Spring Framework와 별개의 프레임워크가 아닌, Spring을 더 쉽고 빠르게 사용할 수 있도록 도와주는 하위 프로젝트(또는 확장 도구).
- 존재 이유: 과거 Spring은 버전 맞추기와 XML 설정이 매우 복잡함. Spring Boot는 개발 진영의 의견을 반영해 spring-boot-starter 시리즈를 제공함으로써 호환되는 라이브러리 버전을 자동으로 맞춰주고 내장 톰캣(Tomcat)을 통해 설정을 극도로 단순화시킴
'Tech Stack > Backend' 카테고리의 다른 글
| 🍃어노테이션 기반 자동 빈 등록(Component Scan & Autowired) (1) | 2026.06.21 |
|---|---|
| 🥾스프링 부트 소개: 설정의 늪에서 생산성의 혁명으로 (0) | 2026.06.19 |
| 🍃빌드 시스템(Maven/Gradle) 이해 및 프로젝트 기본 구조 (0) | 2026.06.19 |
| 🍃어노테이션 기반 수동 빈 등록 (AppConfig) & 스프링 어노테이션(@Autowired) 없이 수동 주입 (0) | 2026.06.18 |
| 🍃스프링 어노테이션(DI/MVC/롬복) 가이드 (참고용) (0) | 2026.06.18 |