SpringCore-1일차

박상원·2024년 2월 13일

spring

목록 보기
1/15

Framework vs Library

Framework는 원하는 기능을 구현하기 위해 일정한 형태(골격)를 제공한다.
e.g. WebApplication, redis, 영속 프레임워크 등
우리들이 직접 코드를 호출하는 것을 라이브러리, 프레임워크는 라이브러리들로 구성되어 있고 우리의 코드를 호출한다.

공통점

  • 특정 문제를 일반적인 방법으로 해결하기 위한 코드를 제공한다.
  • 재활용할 수 있다.

차이점

  • Framework는 원하는 기능을 구현하기 위해 일정한 형태를 제공한다.
  • 기능(함수)의 집합
    e.g. redis 클라이언트 라이브러리
  • redis 영속 프레임워크 vs redis 클라이언트 라이브러리

프레임워크를 사용하는 이유

  • 기능적 요구사항과 비 기능적 요구사항
    • 기능적 요구사항 : 애플리케이션이 실제 갖춰야 할 기능, 반복되지 않는다.
    • 비 기능적 요구사항 : 애플리케이션이 갖춰야 할 스펙 기능을 수행하는 시간 등, 반복될 수 있다.
  • 생산성
  • 속도
  • 결과
    • 반복되는 기능
    • 비즈니스 로직에 집중
    • 빠른 개발

프레임워크가 비 기능적 요구사항을 제공해준다.
e.g. transaction management 등

어떤 프레임워크를 써야 할까?

  • 표준 (standard == defecto)
  • 신뢰성
  • 생태계 (eco-system)

스프링이 표준은 아닌데 사실상 표준이라고 하는 defecto이다.
신뢰성과 생태계가 잘 구성된 프레임워크를 사용해야 한다.

Spring Framework

자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크
스프링 프레임워크는 경량급이다. 이 말은 옛날 EJB보다 가볍다는 뜻이지 그렇게 가볍지는 않다.
스프링은 모듈러 방식이다. 나머지 부분을 가져올 필요 없이 필요한 부분만 사용할 수 있다.
스프링은 비침해적으로 설계되었다. 즉, 도메인 로직 코드는 일반적으로 프레임워크 자체에 종속성이 없다.
스프링 프레임워크는 Java 애플리케이션 개발을 위한 포괄적인 인프라 지원을 제공하는 Java 플렛폼이다.
스프링은 인프라를 처리하므로 애플리케이션에 집중할 수 있다.
infrastructure이다. 데이터를 받아서 저장하고 꺼내올 때 필요한 기능을 제공해준다.
스프링을 사용하면 POJO에서 애플리케이션을 구축하고 POJO에 엔터프라이즈 서비스를 비침투적으로 적용할 수 있다.

Spring Framework 특징

경량 컨테이너로서, Spring Bean을 직접 관리한다.

  • Spring Bean 객체의 라이프 사이클을 관리한다.
    • Spring Bean : Spring Container가 관리하는 중요 객체
  • Container : Spring Bean 객체의 생성, 보관, 제거에 관한 모든 일을 처리한다.

POJO(Plain Old Java Object) 기반의 프레임워크.

  • 일반적인 J2EE 프레임워크와 비교하여, 특정한 인터페이스를 구현하거나 상속을 받을 필요가 없다.
  • 기존에 존재하는 라이브러리를 사용하기 편리하다.

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

  • 컨트롤의 제어권이 사용자(개발자)가 아니라 프레임워크에 있어서, 필요에 따라 Spring에서 사용자의 코드를 호출한다.
  • 의존성 주입(DI : Dependency Injection)
  • DDD, TDD와 같은 프로그래밍 개발론에도 적합한 프레임워크이다.

관점 지향 프로그래밍(AOP : Aspect-Oriented Programming)을 지원

  • 복잡한 비즈니스 영역의 문제와 공통된 지원 영역의 문제를 분리할 수 있다.
  • 문제 해결을 위한 집중
  • e.g. Transaction, Logging, Security and etc.

영속성과 관련된 다양한 서비스 지원

  • e.g. MyBatis, Hibernate, JdbcTemplate 등

높은 확장성 및 범용성 그리고 Eco System

Spring Framework Modules

Core Container

  • spring-core : Spring의 핵심 유틸리티가 포함된 모듈
  • spring-context : Spring의 ApplicationContext 클래스들, 스케줄링 클래스들, AOP 관련 클래스들, Cache 관련 클래스들을 제공.
  • spring-context-support : Third-part 라이브러리를 통합하여, Spring ApplicationContext에서 사용하기 위한 클래스들을 제공한다. Quartz, Guava, Ehcache 등과 관련된 클래스들
  • spring-beans : Spring Bean과 관련된 클래스와 어노테이션들을 제공한다.
  • spring-expression : Spring Expression Language(SpEL) 관련 기능을 제공한다.

AOP

  • spring-aop : Proxy-based AOP support
  • spring-aspects : AspectJ based aspects

인증 : 아이디 패스워드를 입력하여 들어가는 것
인가 : admin과 일반 유저마다 다른 기능을 제공하는 것

Data Access/Integration, Web, Test

  • spring-jdbc : DataSource 설정 및 JDBC 액세스 지원을 포함한 JDBC 지원 패키지
  • spring-jms : JMS 메시지를 보내고 받기 위한 도우미 클래스를 포함한 JMS 지원 패키지
  • spring-messaging : 메시징 아키텍처 및 프로토콜 지원
  • spring-orm : JPA 및 Hibernate 지원을 포함한 객체/관계형 매핑
  • spring-oxm : 객체와 xml 매핑
  • spring-test : 단위 테스트 및 통합 테스트 Spring 구성요소 지원
  • spring-tx : DAO 지원 및 JCA(Java EE Connector Architecture) 통합을 포함한 트렌잭션 인프라
  • spring-web : 클라이언트 및 웹 원격을 포함한 웹 지원 패키지
  • spring-webmvc : 웹 애플리케이션을 위한 REST 웹 서비스 및 model-view-controller 구현
  • spring-websocket : STOMP 지원을 포함한 WebSocket 및 SockJS 구현

Spring Boot vs Spring Core

  • Spring Boot 프레임워크를 사용한 프로젝트
    • Out-Of-Box : 꺼내서 바로 사용할 수 있는 것
    • Cloud - Executable JAR, Packaging
    • MSA - 수많은 컴포넌트
  • 하지만 기본은 Spring Core

The Spring Triangle

  • DI(Dependecy Injection)
  • AOP(Aspect-Oriented Programmin)
  • PSA(Portable Service Abstraction)
  • 중심은 POJO(Plain Old Java Object)

다형성

하나의 객체가 여러가지 형태로 구현이 될 수 있는 것

java의 다형성(polymorphism)

  • Java에서 변수는 부모 클래스 타입이나 인터페이스 타입에 할당될 수 있음
  • 참조 변수의 메소드를 호출하면 실제 구현 객체의 메소드가 실행된다.
  • 동일한 메시지를 전송하지만 실제로 어떤 메서드가 실행될 것인지는 메시지를 수신하는 객체의 클래스가 무엇인가에 따라 결정 되는 것이다.
  • 한국어, 영어 인사를 수행하는 시스템을 다형성을 이용해서 개발한다고 가정하면 다음과 같이 설계할 수 있다.

pakage를 나누는 이유 : 사용과 목적의 경계를 나누기 위해

final은 변수, 인자, 메서드에 붙일 수 있는데 변수는 값을 바꿀 수 없게 되고, 메서드는 재정의가 불가능하고, 클래스는 상속을 할 수 없게 된다.

static 메서드와 필드는 metaspace 영역에 생긴다.
JVM에는 young generation과 old generation, metaspace가 있다.
최초로 새로운 객체가 생성이 되었을 때, young generation에 생성이 된다.
young generation에는 Edan과 survivor1, survivor2로 나뉘어 진다.

  • Edan : 자바 객체가 생성되자마자 할당되는 메모리 영역이다. 즉 new 연산자로 생성된 객체가 위치한다.
  • Survivor1, Survivor2
    • 각 영역이 채워지게 되면, 살아남은 객체는 비워진 Survivor로 이동한다.
    • 이때 참조가 없는 객체들은 Minor GC로 수집된다.
      old generation에는 Young Generation에서 가비지 컬렉션으로 마지막까지 살아남은 객체가 Old Generation으로 오게 된다. 즉, 오래된 데이터가 저장되는 영역이다.
      Major GC가 이루어지며, Minor GC보다 횟수는 적다.

Metaspace

  • Metaspace는 Java의 Classloader가 현재까지 로드한 Class들의 Metadata가 저장되는 공간이다.
  • 중요한 건 Heap 영역이 아니라 Native 메모리 영역에 위치한다.
  • Default로 제한된 크기를 가지고 있지 않다. 그래서 필요한 만큼 계속 늘어난다.

의존성

  • 코드에서 두 모듈간의 연결을 의존성이라고 한다.
  • 객체지향언어에서 두 클래스 간의 관계를 말하기도 한다.

의존성의 종류

Dependency(의존관계)

  • A클래스가 B클래스를 일시적으로 참조하는 형태이다.
    • 인자로 받은 객체의 메서드 참조
public class B {
    private int numB;
    
    public int getNumB() {
      return this.numB;
    }
}

public class A {
    private int numA;
    
    // add 메소드가 반환한 이후에는 B 클래스의 b 객체는 제거된다. 
    public int add(B b) {
      return numA + b.getNumB();
    }
}

Association(연관관계)

  • 클래스 필드로 다른 클래스의 객체를 가지고 있는 관계
public class B {
    private int numB;
    
    public int getNumB() {
      return this.numB;
    }
}

public class A {
    private int numA;
    private B b;
    
    // add 메소드가 반환한 이후에도 B 클래스의 b 객체는 여전히 남아 있다.
    public int add() {
      return numA + this.b.getNumB();
    }
}

Aggregation(집합관계)

  • Association(연관관계)의 특수한 형태
  • 클래스 A와 클래스 B의 생명주기는 반드시 일치 하지 않는다.
public class B {
    private int numB;
    
    public int getNumB() {
      return this.numB;
    }
}

public class A {
    private int numA;
    private B b;
    
    public A(B externalB) {
        this.b = externalB;
    }
}

Composition(합성관계)

  • Association(연관관계)의 특수한 형태
  • Aggregation(집합관계)보다 강결합
  • 클래스 A와 클래스 B의 생명주기가 일치한다.
public class B {
}

public class A {
    private B b;
    
    public A(B externalB) {
        this.b = new B();
    }
}

집합관계는 라이프사이클이 다르고 합성관계는 라이프사이클이 같다.

IoC(제어의 역전)

  • 제어권을 프레임워크가 갖는 것 == 개발자는 제어권이 없다. == 제어(Control)가 역전(Inversion) 되었다.
    • IoC : Inversion of Control
    • 제어
      • 프로그램의 흐름
      • 객체의 생성
  • IoC 관점에서 각자의 역할
    • 개발자는 코드의 흐름이나 객체 생성에 관련된 코드를 직접 작성하지 않는다.
    • 개발자는 프레임워크가 제공하는 설정방법을 사용하여 코드를 설정만 한다.
    • 프레임워크는 이 설정을 보고 객체를 생성하고 코드가 동작하는 순서를 결정하여 실행한다.

우리가 하는 일은 비즈니스 코드를 짜고 그 코드는 프레임워크가 제공하는 설정방법을 사용해서 설정한다. 그 것을 프레임워크가 보고 객체를 생성하고 코드가 동작하는 순서를 결정하여 실행함

IoC의 예 - 흐름의 제어역전(template method pattern)

  • template(형판, 틀) + 메서드 + 패턴
  • 추상 클래스에 템플릿에 해당하는 메서드에서 실행의 흐름이 이미 결정되어 있음
  • 단, 각 메서드가 구체적으로 어떤일을 할 것인지는 개발자의 구현에 따라 결정됨

IoC의 예 - 객체 생성의 제어역전

  • 객체를 원래 메서드에서 생성하여 반환했는데 그 객체를 생성자에서 주입받는 예시
public class ComplexGreetingService {

    // ComplexGreetingService 내부에서 생성한 객체를 사용한다.
    public boolean greet() {
        return new KoreanGreeter().sayHello();
    }
}
public class GreetingService {
    private final Greeter greeter;

    public GreetingService(Greeter greeter) {
        this.greeter = greeter;
    }

    public void doGreet() {
        greeter.sayHello();
    }
}

원래는 GreetingService에서 생성하던 객체를 외부에서 생성을 하여 주입하여 객체 생성의 제어의 역전을 볼 수 있다.

ApplicationContext

Spring IoC container

  • org.springframework.context.ApplicationContext인터페이스는 Spring IoC Container를 나타낸다.
  • 구성 메타데이터를 읽어서 Bean의 인스턴스화, 구성 및 조립을 담당한다.

spring container가 조립하고 설정하고 초기화하는 bean들이 spring bean이다.

Spring Bean

spring bean은 spring IoC container에 의해 인스턴스화되고, 어셈블링되고, 관리되는 객체
spring bean은 name, type, object로 구성되어 있다.
spring bean은 spring framework에서 중요하게 관리하는 객체이다.

JavaBeans

  • public default (no argument) constructor가 있어야 한다.
  • getter/setter가 있어야 한다.
  • implement java.io.Serializable이 구현되어야 한다.

Spring Bean은 Java Bean이 될 수도 있고 안될 수도 있다.
Java Bean도 Spring Bean이 될 수도 있고 안될 수도 있다.

  • 국제화(internationalization) : 언어가 접속하는 클라이언트 언어에 맞추어서 제공되는 것

Bean Factory vs ApplicationContext

  • Spring IoC container는 Bean Factory 또는 ApplicationContext이다.

Bean Factory

  • BeanFactory API는 Spring의 IoC 기능에 대한 기본 기반을 제공한다.

ApplicationContext

  • Bean Factory functionality + α
FeatureBeanFactoryApplicationContext
Bean instantiation/wiringOO
Integrated lifecycle managementXO
Automatic BeanPostProcessor registrationXO
Automatic BeanFactoryPostProcessor registrationXO
Convenient MessageSource access(for Internationalization)XO
Built-in ApplicationEvent publication mechanismXO

ApplicationContext

정의

  • 애플리케이션에 구성 정보를 제공하기 위한 Spring 애플레케이션 내의 중앙 인터페이스

기능

  • 애플리케이션 구성요소에 엑세스하기 위한 Bean factory method이다.
  • 일반적인 방식으로 파일 리소스를 로드하는 기능
  • 등록된 청취자에게 이벤트를 게시하는 기능
  • 국제화를 지원하기 위해 메시지를 해결하는 기능
  • 상위 컨텍스트로부터의 상속

ApplicationContext 종류

  • ~Xml~ApplicationContext : Xml
  • ~AnnotationConfig~ApplicationContext : Java
  • ~Groovy~ApplicationContext : Groovy
  • ~Web~ApplicationContext : Web

try with resources 안에는 자원을 해제해줘야 하는 것이 들어가고 AutoClosable이 있어야 안에 들어갈 수 있다.

singleton을 만드는 방법

  • Eager Initialization : 싱글톤 클래스의 인스턴스를 클래스 로딩 단계에서 생성하는 방법이다. 그러나 애플리케이션에서 해당 인스턴스를 사용하지 않더라도 인스턴스를 생성하기 때문에 자칫 낭비가 발생할 수 있다.
  • Static Block Initialization : Eager Initialization과 유사하지만 static block을 통해서 Exception Handling에 대한 옵션을 제공한다.
  • Lazy Initailization : 앞선 두 방식과는 달리 나중에 초기화하는 방법이다. 이는 global access한 getInstance() 메서드를 호출할 때에 인스턴스가 없다면 생성한다.
  • Thread Safe Singleton : Lazy Initialization의 문제를 해결하기 위한 방법으로, getInstance() 메서드에 synchronized를 걸어두는 방식이다. synchronized는 임계 영역(Critical Section)을 형성해 해당 영역에 오직 하나의 쓰레드만 접근 가능하게 해준다.
  • Bill Pugh Singleton Implementation : 이는 Bill Pugh가 고안한 방식으로, inner static helper class를 사용하는 방식이다. 앞선 방식이 안고 있는 문제점들을 대부분 해결한 방식으로, 현재 가장 널리 쓰이는 싱글톤 구현 방법이다. Singleton Helper 클래스는 Singleton 클래스가 Load 될 때에도 Load 되지 않다가 getInstance()가 호출됐을 때 비로소 JVM 메모리에 로드되고, 인스턴스를 생성하게 된다. synchronized를 사용하지 않기 때문에 성능 저하 또한 해결된다.
  • Enum Singleton : 앞서 살펴본 싱글톤 방식은 사실 완전할 수 없다. 왜냐하면 Java의 Reflection을 통해서 싱글톤을 파괴할 수 있기 때문이다. 이에 Joshua Bloch는 Enum으로 싱글톤을 구현하는 방법을 제안했다. 그러나 이 방법 또한 instance가 사용되지 않을 경우 메모리 문제를 해결하지 못한 것과 유연성이 떨어진다는 면에서의 한계를 가지고 있다.

ApplicationContext 역할

  • Spring Bean 생성
  • Spring Bean 파기
  • Spring Bean 주입

Bean Scope

  • singleton - default
  • prototype
  • 웹어웨어러블한 Spring Application의 컨텍스트에서만 유효한 범위
    • request - single HTTP request의 생명주기
    • session - HTTP Session의 생명주기
    • application - ServletContext의 생명주기
    • websocket - WebSocket의 생명주기

jar로 애플리케이션을 실행시키면 heap 메모리 공간에 ApplicationContext가 띄워지는데 그 안에서 singleton이다. ApplicationContext가 여러개 띄워질 수 있는데 그럼 heap에서 볼 때는 singleton이 아닐 수도 있다.

jvm에서 객체를 비교할 때는 hashcode로 비교를 한다.

DbConnectionPool에 connection을 미리 만들어 놓는 이유는 만드는 과정에 비용이 많이 들어가기 때문이다. 비용이 많이 들어간다는 말은 자원과 시간이 많이 소모된다는 말이다. 그래서 미리 만들어 놓으면 이미 비용을 지불했기 때문에 따로 시간이 들지 않는다.

Atomic 클래스 : Atomic class는 CAS(Compare-And-Swap)를 이용하여 동시성을 하므로 여러 스레드에서 데이터를 write해도 문제가 없다. synchronized 보다 적은 비용으로 동시성을 보장할 수 있다.

  • CAS 알고리즘이란 현재 스레드가 존재하는 CPU의 CacheMemory와 MainMemory에 저장된 값을 비교하여, 일치하는 경우 새로운 값으로 교체하고, 일치하지 않는 경우 기존 교체가 실패되고, 이에 대해 계속 재시도하는 방식이다.
  • CPU가 MainMemory의 자원을 CPU Cache Memory로 가져와 연산을 수행하는 동안 다른 스레드에서 연산이 수행되어 MainMemory의 자원값이 바뀌었을 경우 기존 연산을 실패처리하고, 새로 바뀐 MainMemory 값으로 재수행하는 방식이다.

객체의 생명주기 - BeanPostProcessor

  • Spring IoC의 생명주기 처리를 변경할 수 있는 확장 포인트
  • BeanPostProcessor가 설정되면 Bean 생명주기 이벤트를 가로채서 처리할 수 있다.

구현 메소드

  • postProcessBeforeInitialization : init-method에 지정된 메서드가 호출되기 전에 호출된다.
  • postProcessAfterInitialization : init-method에 지정된 메서드가 호출된 후에 호출된다.
  • init-method가 지정되어 있지 않더라도 자동으로 호출된다.

의존성 주입(Dependency Injection)

  • IoC의 패턴 중에 하나
  • Object간의 의존성을 낮춘다.
  • 외부에서 객체를 생성하고 전달한다.

우리들의 코드에서 new라는 키워드가 많아지면 의존성이 높아지는 것을 뜻함

0개의 댓글