[스프링] 스프링이란 무엇일까?

2025. 6. 26. 17:16·스프링

많은 개발자들이 스프링(Spring)에 대해 이렇게 말하곤 한다.

  • "웹 애플리케이션을 쉽게 만들 수 있는 프레임워크이다."
  • "DB 접근을 편하게 해준다."
  • "전자정부 프레임워크 기반이다."
  • "톰캣 같은 웹 서버를 자동으로 띄워준다."
  • "마이크로서비스나 클라우드 개발에 쓰인다."

이 말들은 틀리지 않다. 그러나 핵심은 아니다.
스프링의 본질은 단순한 웹 개발 도구도, DB 연결 도우미도 아니다.
스프링은 '좋은 객체 지향 설계'를 실현하게 도와주는 자바 기반 프레임워크이다.

 

 

좋은 객체 지향이란 무엇일까?

스프링을 이해하려면 먼저 ‘좋은 객체 지향 설계’가 무엇인지부터 짚고 넘어가야 한다.

좋은 객체 지향이란 다음과 같은 특징을 가진다.

  • 클라이언트는 객체가 수행하는 역할(인터페이스)만 알면 된다.
  • 객체의 내부 구현은 몰라도 된다.
  • 내부 구현이 바뀌어도 외부에 영향을 주지 않는다.
  • 심지어 전체 구현체를 교체하더라도 클라이언트 코드는 그대로 유지된다.

이런 설계를 가능하게 하는 키워드는 바로 "역할과 구현의 분리"이다.
자바는 이를 가능케 하는 기능, 즉 다형성(polymorphism)을 제공한다.

  • 역할 = 인터페이스
  • 구현 = 인터페이스를 구현한 클래스
  • 객체 설계 시 역할(인터페이스)을 먼저 만들고, 그 역할을 수행할 구현 클래스를 나중에 만든다.

이렇게 하면 실제 시스템은 훨씬 유연해진다.
부품을 갈아 끼우듯이 코드를 변경할 수 있고, 확장이 쉬우며, 변화에 강한 구조를 갖게 된다.

 

그럼에도 불구하고, 다형성만으로는 부족하다

하지만 여기서 문제가 하나 생긴다.
다형성만으로는 좋은 객체 지향을 완전히 구현할 수 없다.

왜냐하면 객체를 만들 때 클라이언트가 여전히 구체 클래스에 의존하게 되기 때문이다.
예를 하나 들어보자

public class OrderService {
    private final MemoryRepository repository;

    public OrderService() {
        this.repository = new MemoryRepository(); //의존
    }

    public void createOrder(String item) {
        repository.save(item);
    }
}

 

OrderService가 구체 클래스(MemoryRepository)에 직접 의존하는 형태를 볼 수 있다.

 

이때 저장 형태를 DB로 바꾸라는 요구사항이 들어오면 어떨까? 우리는 DbRepository로 바꾸기 위해 MemoryRepository -> DbRepository로 변경할 것이다.

당장은 그냥 하면 되지 않나? 라고 생각할 수 있다. 하지만 이런 문제가 10~100가지 모이다 보면 불편함이 클 것이다.


즉 이는 OCP(개방-폐쇄 원칙)나 DIP(의존 역전 원칙) 같은 객체 지향 원칙을 지킬 수 없게 된다.

 

당장은 이해되지 않을 수 있다. 추후에 완성된 코드에서 변경된 요구사항을 적용시켜보면 

극단적으로 하나의 변경에 10가지의 코드 수정이 발생하는 불편함을 자연스럽게 느낄 것이다.

 

 

스프링이 등장하는 이유: DI와 컨테이너

이 문제를 해결하기 위해 등장한 것이 바로 스프링의 DI(Dependency Injection)이다.

  • DI(의존성 주입)은 객체가 필요한 의존 객체를 스스로 생성하지 않고, 외부에서 주입받도록 하는 방식이다.
  • 스프링은 이를 자동화한 DI 컨테이너를 제공한다.
  • 개발자는 인터페이스만 설계하고, 실제 구현체는 설정을 통해 주입받는다.
  • 이렇게 하면 클라이언트 코드는 절대 구현체에 의존하지 않는다.
  • 변경이 필요하면 설정만 바꾸면 된다. 코드 변경은 필요 없다.

이러한 구조 덕분에 스프링은 다음과 같은 유연함을 제공한다.

  • 구현체 변경 시 클라이언트 코드 변경 없음
  • 테스트 시 가짜(Mock) 객체 쉽게 주입
  • 기능 확장이 간단
  • 객체 간 결합도 감소

 

스프링이 지향하는 설계 철학: SOLID 원칙

스프링은 단순히 기술을 제공하는 것이 아니라,
좋은 객체 지향 설계를 자연스럽게 유도하도록 설계되어 있다.

특히 아래의 SOLID 원칙을 실천하기 쉽게 만든다.

  • SRP (단일 책임 원칙): 하나의 클래스는 하나의 책임만 가져야 한다.
  • OCP (개방-폐쇄 원칙): 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
  • LSP (리스코프 치환 원칙): 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 한다.
  • ISP (인터페이스 분리 원칙): 인터페이스는 꼭 필요한 기능만 가져야 한다.
  • DIP (의존 역전 원칙): 추상화에 의존해야지, 구체화에 의존하면 안 된다.

스프링은 DI를 통해 DIP와 OCP를 지킬 수 있게 해주고,
빈 설정과 컴포넌트 스캔, AOP 같은 기능을 통해 SRP와 ISP도 실현 가능하게 만든다.

(이는 추후에 다룰 예정)

 

 

결론: 스프링은 ‘좋은 객체 지향’을 실현하는 도구이다

정리하자면, 스프링은 단지 서버를 띄우거나 DB에 연결하는 프레임워크가 아니다.
자바라는 객체 지향 언어의 장점을 최대한 끌어내어,
유연하고 확장 가능하며 변경에 강한 애플리케이션을 만들도록 돕는 도구
이다.

스프링을 제대로 이해하려면
웹 기술보다 먼저 객체 지향과 설계 원칙, 그리고 DI 개념을 정확히 아는 것이 중요하다.

스프링을 이해한다 = 좋은 객체 지향을 이해한다.
이 한 문장을 기억하면 스프링의 본질을 놓치지 않게 된다.

'스프링' 카테고리의 다른 글

[스프링] 빈 스코프  (1) 2025.07.24
[스프링] 빈 생명주기 콜백  (3) 2025.07.24
[스프링] 의존관계 자동 주입에 대하여  (0) 2025.06.26
[스프링] 싱글톤과 스프링 컨테이너에 대하여  (3) 2025.06.26
[스프링] 스프링 컨테이너와 빈(Bean)은 왜 필요한가?  (0) 2025.06.26
'스프링' 카테고리의 다른 글
  • [스프링] 빈 생명주기 콜백
  • [스프링] 의존관계 자동 주입에 대하여
  • [스프링] 싱글톤과 스프링 컨테이너에 대하여
  • [스프링] 스프링 컨테이너와 빈(Bean)은 왜 필요한가?
0kingki_
0kingki_
자바 + 스프링 웹 개발
  • 0kingki_
    0kingki_
    0kingki_
  • 전체
    오늘
    어제
    • 분류 전체보기 (134)
      • 코딩 테스트 (54)
      • 자바 (21)
      • 스프링 (27)
      • 타임리프 (16)
      • 스프링 데이터 JPA (8)
      • 최적화 (2)
      • QueryDSL (4)
      • AWS (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    스프링 컨테이너
    thymeleaf
    불변객체
    스프링 데이터 JPA
    자바
    백준
    SOLID
    JPA
    쿼리dsl
    코딩테스트
    타임리프
    예외처리
    BFS
    Java
    재귀
    SpringDataJpa
    다형성
    fetch join
    mvc
    예외 처리
    spring
    객체지향
    최적화
    코딩 테스트
    스프링
    dfs
    QueryDSL
    LocalDateTime
    컬렉션
    쿼리
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
0kingki_
[스프링] 스프링이란 무엇일까?
상단으로

티스토리툴바