1.1 스프링 프레임워크 개요 — 탄생 배경과 철학
대한민국 공공기관 웹 서비스 표준 프레임워크(전자정부프레임워크)의 뼈대이자, 전 세계 엔터프라이즈 자바 개발의 절대 지배자인 Spring Framework 의 세계에 오신 것을 환영합니다.
🌱 1. 스프링 프레임워크의 탄생 배경
2000년대 초반, 자바로 거대한 기업용 애플리케이션(Enterprise Application)을 만들기 위해 쓰던 기술은 EJB (Enterprise JavaBeans) 였습니다.
문제는 EJB가 너무나 무겁고 지나치게 복잡하여, 간단한 기능 하나를 만들려 해도 인터페이스를 3~4개씩 상속받고 무거운 컨테이너 서버 환경을 반드시 띄워야 했습니다. 개발자들 사이에서 원성이 자자하던 중, 2002년 로드 존슨(Rod Johnson)이 출간한 얇은 책("J2EE Development without EJB")에서 EJB의 지옥을 정면으로 비판하며 가볍고 실용적인 프레임워크 코드를 제시했는데, 무수한 박수갈채를 받아 이 오픈소스가 바로 스프링(Spring) 의 시초가 되었습니다. (전통적인 무거운 J2EE 겨울을 깨고 새 봄이 찾아왔다는 의미의 스프링입니다.)
핵심 사상: 기술을 위한 복잡한 기술 종속성을 버리고, 가장 자바 본연의 모습에 가까운 POJO(Plain Old Java Object - 순수한 옛날 자바 객체) 프로그래밍 방식으로 돌아가 순수하게 비즈니스 로직에만 100% 집중하게 해주겠다!
// EJB 시절의 지옥 같은 코드 구조 (특정 기술에 심하게 종속됨)
public class OrderManagerBean implements SessionBean {
public void ejbCreate() throws CreateException { ... }
public void setSessionContext(SessionContext ctx) { ... }
// 비즈니스 로직보다 프레임워크 요구사항 코드가 더 길다!
}
// 스프링 프레임워크가 추구하는 완벽한 POJO (가장 순수한 자바 형태)
public class OrderService {
public void createOrder(Order order) {
// 복잡한 상속이나 특정 클래스 구현 없이 오직 순수 비즈니스 로직만 존재!
}
}
🛠️ 2. 스프링을 지배하는 3대 핵심 프로그래밍 모델 (특징)
스프링 프레임워크는 단순히 기능들의 모음집이 아닙니다. 자바로 설계 가능한 최고의 객체지향 아키텍처를 강제하며, 개발자가 숨 쉬듯이 다음 3가지 핵심 사상을 사용하도록 이끕니다.
① IoC/DI (제어의 역전과 의존성 주입)
자바 코드 내부에서 객체를 개발자가 직접 깎아서(new) 연동하지 않습니다. "저는 B 부품이 필요합니다" 라고 명시하기만 하면, 스프링(거대한 레고 상자 조립기)이 알아서 외부에서 부품(Bean)을 콕콕 찔러 넣어줍니다(Injection). 애플리케이션의 유연성과 부품 탈부착(스위치)이 혁명적으로 자유로워집니다.
// [과거 전통적 방식] 개발자가 스스로 제어
public class MemberService {
// MySQLRepository 쓰다가 OracleRepository로 바꾸려면 코드를 직접 뜯어 고쳐야 함
private MemberRepository repository = new MySQLMemberRepository();
}
// [스프링 IoC/DI 방식] 제어권이 스프링으로 넘어감
@Service
public class MemberService {
private final MemberRepository repository;
// 생성자 파라미터만 열어두면, 스프링 컨테이너가 런타임에 가장 적합한 DB 저장소 부품을 채워줌
public MemberService(MemberRepository repository) {
this.repository = repository;
}
}
② AOP (Aspect-Oriented Programming, 관점 지향 프로그래밍)
로깅, 트랜잭션, 권한 체크 등 모든 클래스마다 위아래로 3~4줄씩 똑같이 반복되는 부가 공통 로직들(Cross-Cutting Concerns)을 개별 클래스에서 완전히 잘라냅니다. 이를 별도의 전담 파일(Aspect)로 만들어 대상 로직 앞뒤에 부착합니다.
// [AOP 적용 전] 핵심 비즈니스(파란색)보다 방어막 코드(빨간색)가 더 김
public void transferMoney(Long fromId, Long toId, int amount) {
long startTime = System.currentTimeMillis(); // 공통 로직
Transaction tx = db.beginTransaction(); // 공통 로직
try {
// -------- 핵심 로직 ---------
accountDao.deduct(fromId, amount);
accountDao.add(toId, amount);
// --------------------------
tx.commit(); // 공통 로직
} catch (Exception e) {
tx.rollback(); // 공통 로직
} finally {
System.out.println("걸린 시간: " + (System.currentTimeMillis() - startTime)); // 공통 로직
}
}
// [AOP 적용 후] 스프링의 @Transactional 어노테이션 한방으로 모든 공통 관심사 분리
@Transactional
@LogExecutionTime
public void transferMoney(Long fromId, Long toId, int amount) {
// 오직 순수한 비즈니스에만 집중
accountDao.deduct(fromId, amount);
accountDao.add(toId, amount);
}
③ PSA (Portable Service Abstraction, 일관된 서비스 추상화)
스프링은 철저하게 '어댑터' 콘셉트를 지향합니다. 개발자가 서블릿이나 특정 데이터베이스 규격에 따라 코드를 뜯어고칠 필요가 없습니다. 스프링이 제시하는 일관된 인터페이스 뼈대만 사용하면, 하단 구현체를 MyBatis에서 JPA로 넘기거나 외부 라이브러리를 통째로 갈아치워도 비즈니스 로직 코드를 안전하게 유지할 수 있습니다.
🎯 3. 현대 실무 고수 팁 (Pro Tips)
💡 라이브러리 vs 프레임워크의 근원적 차이 이해하기
- 라이브러리(Library): 개발자가 필요할 때마다(원하는 시점에) 능동적으로 호출해서 사용하는 유틸리티 칼입니다. 전체 제어권(Control)은 개발자 본인에게 있습니다. (예:
Jackson,Apache Commons)- 프레임워크(Framework): 내가 만든 자바 파일(부품)들을 통째로 거대한 공장 컨베이어 벨트에 집어던지는 형태입니다. 흐름의 통제권 규칙을 프레임워크가 강제하며, 내 코드를 호출하는 시점과 생성/소멸시키는 주체도 프레임워크입니다. 스프링이 내 클래스를 IoC 컨테이너 에 흡수시켜 라이프사이클 통제권을 자신이 거머쥔다는 사실을 잊으면 안 됩니다.