TIL 27 [ Spring ( SOLID 객체지향, Container와 Bean, 싱글톤 ) + 스탠다드반 (DI / IOC) ]

2025. 3. 27. 22:32·[내일배움캠프-Sparta]/Spring 6기
반응형

※ 수준별반 학습이랑 숙련강의 주차에 나왔던 내용이 겹치기 때문에 DI / IOC는 스탠다드반 기준으로 작성.

Spring 숙련 

✅ 객체 지향 설계

1️⃣ SOLID 원칙 

객체 지향 설계의 5가지 기본 원칙, S/W 설계 에서 유지보수성, 확장성, 유연성을 높이기 위한 지침을 제공함.

  1.  단일 책임의 원칙 SRP
    • 하나의 클래스는 하나의 책임만 가져야 한다.
    • 클래스는 1가지 기능에 집중 해야함. 그 외 기능 담당 ❌
  2. 개방 폐쇄 원칙 OCP
    • S/W 요소는 확장에는 열리고, 수정에는 닫혀야 있어야 한다.
      • 새로운 기능을 추가 할때 기존 코드를 수정하지 않고, 확장하도록 설계
    • 다형성을 활용하여 해결
    • 문제점
      • 객체의 생성, 사용 등을 자동으로 설정해주는 무엇인가 필요함.
        • Spring 컨테이너 역할
  3. 리스코프 치환 원칙 LSP
    • 자식 클래스는 언제나 부모 클래스를 대체 할수 있어야 한다.
      • 부모 클래스를 사용하는 곳에 자식 클래스를 사용해도 프로그램 동작에 문제가 없어야 함.
  4. 인터페이스 분리 원칙 ISP
    • 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
      • 하나의 큰 인터페이스 보다 여러 개의 작은 인터페이스로 분리해야 한다.
  5. 의존관계 역전 원칙 DIP
    • 구체적인 클래스에 의존 ❌, 인터페이스나 추상 클래스에 의존 하도록 설계

▶ Spring이 다형성 만으로 해결하지 못한 문제점을 OCP, DIP 원칙을 DI / IOC로 해결해줌.

✅ Spring Container와 Bean

1️⃣ Spring Container

보통 Java에서 new 키워드를 이용하여 객체 생성하였다. 

하지만 이제부터 Spring Container 에서 객체를 생성 및 관리하고 의존성을 주입하는 역할을 담당 한다.

Spring 컨테이너

객체를 직접 생성 하는 경우, 객체간의 의존성 및 결합도가 높아진다 ▶ OCP, DIP 위반

Spring 컨테이너를 사용하면 인터페이스에만 의존하는 설계가 가능해진다 ▶ OCP, DIP 준수

 

Container 종류

일반적으로 Application Context를 사용

2️⃣ Spring Bean

앞서 Spring 컨테이너가 관리하는 객체를 의미, Spring이 이 객체를 관리한 순간부터 Bean이 되며, Spring이 Bean을 생성, 초기화, 의존성 주입을 통해 관리함.

Spring 컨테이너 내 Bean 객체

  • Bean은 new 키워드 대신 사용하는 것이다.
  • Spring Container가 제어한다.
  • Spring Bean의 특징
    1. Spring 컨테이너에 의해 생성되고 관리된다.
    2. 기본적으로 Singleton으로 설정된다.
    3. 의존성 주입(DI)을 통해 다른 객체들과 의존 관계를 맺을 수 있다.
    4. 생성, 초기화, 사용, 소멸의 생명주기를 가진다.

✅ Singleton(싱글톤) 패턴 

클래스의 인스턴스가 오직 하나만 생성되도록 보장하는 디자인 패턴이다.

등장 배경

싱글톤 패치 적용하기 전

  • 요청을 할 때 마다 객체를 새로 생성되고 처리가 완료되면 소멸된다.
  • 메모리 낭비가 아주 심하다.

싱글톤 패턴 적용 후

  • 객체가 한번만 생성되어 리소스를 절약할 수 있다.

✔ Spring이 Bean을 등록하는 방법은 기본적으로 싱글톤 이다. 하지만, 요청할 때 마다 새로운 객체를 생성해서 반환하는 기능도 제공한다.

 

⚠  싱글톤 패턴 주의점

객체의 인스턴스를 하나만 생성하여 공유하는 싱글톤 패턴의 객체는 상태를 유지(stateful)하면 안된다.

  • 상태 유지(stateful)의 문제점
    • 데이터의 불일치나 동시성 문제가 발생할 수 있다.
public class StatefulSingleton {
    private static StatefulSingleton instance;
    
    // 상태를 나타내는 필드
    private int value;

    // private 생성자
    private StatefulSingleton() {}

    // 싱글톤 인스턴스를 반환하는 메서드
    public static StatefulSingleton getInstance() {
        if (instance == null) {
            instance = new StatefulSingleton();
        }
        return instance;
    }

    // 상태 변경 메서드
    public void setValue(int value) {
        this.value = value;
    }

    // 상태를 반환하는 메서드
    public int getValue() {
        return this.value;
    }
}
// ====================================================================================================================================
public class MainApp {
    public static void main(String[] args) {
        // 클라이언트 1: 싱글톤 인스턴스를 가져와서 상태를 설정
        StatefulSingleton client1 = StatefulSingleton.getInstance();
        client1.setValue(42);
        System.out.println("클라이언트 1이 설정한 값: " + client1.getValue());

        // 클라이언트 2: 동일한 싱글톤 인스턴스를 사용해 상태를 변경
        StatefulSingleton client2 = StatefulSingleton.getInstance();
        client2.setValue(100);
        System.out.println("클라이언트 2가 설정한 값: " + client2.getValue());

        // 클라이언트 1이 다시 값을 확인
        System.out.println("클라이언트 1이 다시 확인한 값: " + client1.getValue());
    }
}
클라이언트 1이 설정한 값: 42
클라이언트 2가 설정한 값: 100
클라이언트 1이 다시 확인한 값: 100
  • value 필드는 공유되는 필드인데, 특정 클라이언트가 값을 변경한다.
  • ⭐Spring Bean은 항상 무상태(stateless)로 설계를 해야한다. 아주 중요! ⭐
    • 특정 클라이언트에 의존적인 필드가 있거나 변경할 수 있으면 안된다.

 

스탠다드반 ⭐ DI / IOC ⭐

1️⃣ IOC (제어의 역전, Inversion of Control)

제어의 역전. 객체의 생성과 관리 권한을 개발자가 아닌 Spring 컨테이너가 담당.

  • 기존 : 개발자가 new 키워드를 사용해 객체 생성 및 연결
  • IoC: Spring 컨테이너가 자동으로 객체 생성 및 연결

스프링부트의 주요 특징중 하나이며, 현 개발자 들이 개발하는데에 있어서 편리함을 제공한다. 

스프링 프레임워크가 지향하는 핵심적인 아키텍처 중 하나는 느슨한 결합도 이다. 

▶ 컴포넌트가 강하게 연결 되어 있으면, 변경이 어렵고 테스트 하기 힘들다. 그러므로 느슨한 결합은 유연하고 확장 가흔한 애플리케이션을 가능하게 할 수 있다.  → 인터페이스 를 활용

제어의 역전

2️⃣ DI ( Dependency Injection )

객체 간의 의존 관계를 외부에서 주입해주는 방식 DI는 IOC의 일부분

서로다른 객체 생성 방법

  • 종류:
    • 생성자 주입 (Constructor Injection) ⭐
    • 세터 주입 (Setter Injection)
    • 필드 주입 (Field Injection)
  • 장점:
    • 코드 간 결합도 감소
    • 테스트 용이성 향상
    • 유지보수 용이

주로 개발자들은 생성자 주입을 일반적으로 쓰는 편이다. 

📌 Spring에서의 DI 구현

  • @Component : 빈 등록
  • @Autowired : 의존성 주입 (DI)  ( 생성자 주입시, 생성자가 하나인경우 생략 가능 ! ! )
  • Spring이 Engine 객체를 생성해서 Car에 주입

✅ 생성자 주입 (Constructor Injection)

@Component
public class Car {
    private final Engine engine;

    @Autowired
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        engine.start();
    }
}

장점:

  • 객체 생성 시점에 의존성 주입이 보장되어, 불변 객체 구성에 유리함
  • 테스트 코드 작성 시 명시적인 생성자를 통해 의존성 주입이 가능함
  • 필수 의존성을 강제할 수 있어 컴파일 타임 오류를 방지함
  • 스프링 프레임워크 팀과 대부분의 커뮤니티에서 가장 권장하는 방식

단점:

  • 의존성이 많아질 경우 생성자 파라미터가 길어짐
  • 순환 참조 발생 시 복잡도 증가

✅ 필드 주입 (Field Injection) - 비추천 😒

@Component
public class Engine {
    public String start() {
        return "Engine started!";
    }
}

@Component
public class Car {

    private final Engine engine;

    @Autowired
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        System.out.println(engine.start() + " Driving...");
    }
}

장점:

  • 코드가 가장 간결하고 직관적임

단점:

  • 테스트 시 Mock 주입이 어려움 (리플렉션 필요)
  • 순수 자바 환경에서 사용하기 어려움 (스프링 프레임워크에 강한 의존성)
  • 의존 관계가 외부에서 보이지 않아 명확성이 떨어짐

📌 ApplicationContext와 Bean

  • ApplicationContext: Spring 컨테이너, 객체를 생성하고 관리함
  • Bean: Spring이 관리하는 객체
  • 빈 등록 방법:
    • @Component, @Service, @Repository, @Controller ( 자동 )
    • @Configuration + @Bean 메서드  ( 수동적인 방법 )
반응형

'[내일배움캠프-Sparta] > Spring 6기' 카테고리의 다른 글

Spring ( Session, Token, JWT )  (0) 2025.03.30
TIL 28 [ Spring ( Bean Validation, Cookie ) ]  (0) 2025.03.28
TIL 26 [ Spring 일정관리 앱 과제 해설 + 학습법 & 동기부여 세션 ]  (0) 2025.03.26
TIL 25 [ Spring 일정 관리 앱 과제 ( 필수 . . . JDBC..??) + 미니세션 ( API, ERD ) ]  (0) 2025.03.24
TIL 24 [ Spring ( 3 Layer 아키텍처, DB, SQL, JDBC, SQL Mapper ) ]  (0) 2025.03.21
'[내일배움캠프-Sparta]/Spring 6기' 카테고리의 다른 글
  • Spring ( Session, Token, JWT )
  • TIL 28 [ Spring ( Bean Validation, Cookie ) ]
  • TIL 26 [ Spring 일정관리 앱 과제 해설 + 학습법 & 동기부여 세션 ]
  • TIL 25 [ Spring 일정 관리 앱 과제 ( 필수 . . . JDBC..??) + 미니세션 ( API, ERD ) ]
dimenshun
dimenshun
한 소년의 개발 일기
    반응형
  • dimenshun
    Dev Life Notes
    dimenshun
  • 전체
    오늘
    어제
    • 분류 전체보기 (268)
      • CS (23)
        • 자료구조 (0)
        • 알고리즘 (0)
        • 컴퓨터 구조 (8)
        • 네트워크 (6)
        • 운영체제 (3)
        • DB ( + SQLD ) (5)
        • SW공학 (1)
      • 프로그래밍 (3)
        • Java (0)
        • Spring (0)
        • HTML,CSS (3)
        • JavaScript (0)
      • 개발 툴 (7)
        • Git(버전관리) (1)
        • Docker (3)
        • AWS (2)
        • JSP (1)
      • 코딩테스트(Algorithm) (125)
        • 백준 (6)
        • 프로그래머스 (119)
      • [내일배움캠프-Sparta] (110)
        • Spring 6기 (106)
        • KPT 회고 (3)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    메모리
    CPU
    SQL
    배포
    KPT
    운영체제
    컴퓨터구조
    Python
    웹
    web
    docker
    network
    Til
    db
    네트워크
    OS
    cs
    It
    내일배움캠프
    Java
    세션
    트랜잭션
    알고리즘
    AWS
    Testcode
    코딩테스트
    SQLD
    백엔드
    spring
    개발자
  • hELLO· Designed By정상우.v4.10.3
dimenshun
TIL 27 [ Spring ( SOLID 객체지향, Container와 Bean, 싱글톤 ) + 스탠다드반 (DI / IOC) ]
상단으로

티스토리툴바