본문 바로가기

WINK-(Web & App)/Spring Boot 스터디

[2025 1학기 스프링부트 스터디] 남윤찬 #1주차

반응형

이전에 봤던 강의들이 잇어서 첫날은 핵심 개념들만 빠르게 요약하고 복습 한 번 하겠습니다..

 

1 - 다형성과 객체 지향 설계의 5원칙

다형성

    프로그램을 유연하고 변경이 용이하게 만들어준다.

    쉽게 비유하자면 역할(인터페이스)과 구현(인터페이스를 구현한 클래스, 구현 객체)으로 구분해진다.

객체 지향 설계의 5원칙(SOLID)

SRP(Single Responsibility Principle): 단일 책임 원칙

    - 한 클래스는 하나의 책임만 가진다. 변경이 있을 때 파급이 적을 수록 좋음

OCP(Open/Closed Principle): 개방/폐쇄 원칙

    - 확장에는 개방, 변경에는 폐쇄. 다형성을 활용해 인터페이스를 구현한 새로운 클래스를 만들어 기능을 구현

LSP(Liskov Substitution Principle): 리스코프 치환 원칙

    - 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다

ISP(Interface Segregation Principle): 인터페이스 분리 원칙

    - 인터페이스는 세세할 수록 좋음. 명확해지고 대체가능성이 높아진다.

DIP(Dependency Inversion Principle): 의존 관계 역전 원칙

    - 개발에 있어서 구현체보다 인터페이스에 의존해야한다.

 

2- 스프링 핵심 원리

SoC(Separation of Concerns): 관심사의 분리

    - 의존 관계를 관리하는 객체, 스프링에서는 AppConfig라는 객체를 생성해 애플리케이션의 동작 환경을 구성한다. 새로운 기능을 추가하고 싶다면 객체에서 직접 변경하는 것이 아니라 AppConfig를 수정해 적용시킬 수 있다.

IoC(Inversion of Control): 제어의 역전

    - 개발자가 직접 흐름을 제어X, 구현 객체가 프로그램의 흐름을 컨트롤한다

DI(Dependency Injection): 의존 관계 주입

    - 클래스 의존 관계 - 정적

        import 코드만 보고 의존 관계 판단. 실행 없이 분석 가능

    - 객체 의존 관계 - 동적

        런타임 외부에서 실제 구현 객체를 생성핟고 전달해서 의존 관계를 연결한다. 클래스 의존 관계를 손대지 않고 객체 인스턴스의 의존 관계를 쉽게 변경 가능

컨테이너: AppConfig처럼 객체를 생성/관리 하며 의존 관계를 연결해주는 것

 

3 - 스프링 컨테이너, 스프링 빈

스프링 컨테이너

AppConfig를 참고하여 DI를 해둔다. 각각의 객체, 인터페이스는 스프링에서 빈이라고 한다. 빈과 관련된 정보는 ApplicationContext를 사용해 다양한 메타 데이터를 불러올 수 있다.

 

4 - 싱글톤 컨테이너

스프링 애플리케이션의 대부분은 웹 애플리케이션이다. 각 요청마다 객체를 생성하면 메모리 낭비가 심하게 되어, 스프링의 jvm 안에서 하나의 객체만을 생성하고 이것을 공유하게 하는 싱글톤 패턴을 사용한다.

싱글톤 패턴: 클래스의 인스턴스가 단 한 개만 생성되는 것을 보장하는 디자인 패턴

 

주의점: 싱글톤은 여러 클라이언트가 하나의 인스턴스를 공유하기 때문에 무상태(stateless)로 설계해야 한다.

    특정 클라이언트에 의존적인 필드가 있으면 안된다.

    특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.

    가급적 읽기만 가능해야 한다.

    필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다.

 

5 - 컴포넌트 스캔

프로젝트가 커질수록 스프링 빈을 직접 등록해줄 수 없기에, 스프링은 @ComponentScan이라는 어노테이션으로 컴포넌트를 빈으로 등록하는 작업을 하게 된다. 스프링을 사용하면서 @Controller, @Service 등의 어노테이션은 @Component를 포함하고 있어, 자동으로 등록된다. 컴포넌트 스캔에서 includeFilters, excludeFilters라는 옵션으로 등록할 컴포넌트를 필터링 할 수 있다.

 

스프링에서 빈을 등록하는 과정에서 같은 이름의 빈이 생성되면 충돌이 일어나는데, 다음과 같은 상황이 있다.

    자동 빈 등록 vs 자동 빈 등록 → 스프링이 ConflictingBeanDefinitionException 발생시킴

    수동 빈 등록 vs 자동 빈 등록 → 수동 빈이 우선권을 가지기 때문에 자동 빈을 오버라이딩 해버린다. 하지만 스프링부트를 실행시키면 오류를 발생시킨다.

 

하지만 아래 것을 명심하여 이런 오류가 생기지 않도록 설계를 하도록 한다.

    명확하지 않은 건 하지 말자.

    애매한 상황(어설픈 추상화, 우선순위)은 만들지 말자.

 

6 - 의존 관계 자동 주입

의존 관계 주입에는 생성자 주입, 수정자 주입 등이 있지만, 보편적으로 사용하는 방식은 생성자 주입이다. 그리고 Spring을 사용할 때는 @Autowired 어노테이션을 붙여서 자동 주입을 할 수 있다. 또한 점점 바뀌어서 @Autowired도 생략하고 Lombok 라이브러리를 사용해 @RequiredArgsConstructor 어노테이션을 붙여 의존 관계를 자동으로 주입한다.(스프링은 생성자가 한 개면 @Autowired를 생략할 수 있고, 그렇게 되면 생성자 주입이 된다.)

 

빈이 두 개 이상 탐지 되면

    @Autowired로 타입 매칭을 하고, 여러 개면 필드명과 파라미터명으로 매칭할 수도 있고

    @Qualifier끼리 매칭할 수도 있고

    @Primary를 붙여줘서 우선순위를 정해줄 수 있다.

빈이 모두 필요하면 List와 Map으로 처리 가능함

의존 관계 주입은 현재는 Spring이 가진 어노테이션으로 처리하기 굉장히 편해 자동 기능을 잘 쓰도록 되는 게 중요하다.

 

7 - 빈 생명주기 콜백

스프링 빈의 라이프 사이클

    객체 생성 → 의존관계 주입

스프링 빈의 이벤트 라이프 사이클

    스프링 컨테이너 생성 → 스프링 빈 생성 → 의존관계 주입 → 초기화 콜백 → 사용 → 소멸 전 콜백 → 스프링 종료

빈 생명주기를 콜백하는 방법은 세 가지가 있다

  1. 인터페이스 InitializingBean, DisposableBean을 사용
  2. 빈 등록 초기화, 소멸 메서드 @Bean 어노테이션에서 옵션으로 initMethod와 destroyMethod로 지정할 수 있다.
  3. 어노테이션 @PostConstruct, @PreDestroy를 사용
반응형