스프링 (6)

 

 

 

 

 

 

❑ 타입별 Advice

 

 

➤ Advice 순서

 

어드바이스는 기본적으로 순서를 보장하지 않는다.

순서를 지정하라면 @Aspect 적용 단위로 org.springframework.core.annotation.@Order 애너테이션을 적용하면 됨

  • 어드바이스 단위가 아닌 클래스 단위로 적용할 수 있다.
  • 하나의 aspect에 여러 어드바이스가 존재하면 순서를 보장받을 수 없다.

aspect를 별도의 클래스로 분리해야 한다.

 

 

 

➤ Advice 종류

 

 

▶️ Before

  • join point 실행 이전에 실행한다.
  • Before Advice 구현한 메서드는 일반적으로 리턴 타입이 void 이다.
  • 메서드에서 예외를 발생시킬 경우 대상 객체의 메서드가 호출되지 않는다.
  • 작업 흐름을 변경할 수 없다.

 

 

▶️ After returning

  • join point가 정상 완료된 후 실행한다.
  • returning 속성에 사용된 이름은 advice 메서드의 매개변수 이름과 일치해야 함

 

 

▶️ After throwing

  • 메서드가 예외를 던지는 경우에 실행한다.
  • 메서드 실행이 예외를 던져서 종료될 때 실행한다.
  • throwing 속성에 사용된 이름은 advice 메서드의 매개변수 이름과 일치해야 함

 

 

▶️ After (finally)

  • join point의 동작(정상 또는 예외)과는 상관없이 실행한다.
  • 메서드 실행 후 공통 기능을 실행한다.
  • try~finally의 finally를 생각하면 된다.
  • 일반적으로 리소스를 해제하는데 사용한다.

 

 

▶️ Around ⭐️

  • 메서드 호출 전후에 수행하며 가장 강력한 advice이다.
  • 메서드 실행 전후, 예외 발생 시점에 공통 기능을 실행한다.
    • 조인 포인트 실행 여부 선택 - joinPoint.proceed()
    • 전달 값 변환 - joinPoint.proceed(args[])
    • 반환 값 변환
    • 예외 변환
  • try~catch~finally 가 들어가는 구문 처리가 가능하다.
  • 어드바이스의 첫 번째 매개변수는 ProceedingJoinPoint를 사용해야 한다.
  • proceed()를 통해 대상을 여러번 실행할 수 있다.

 

 

@Around만 있어도 모든 기능 수행이 가능하다!

하지만 target등 고려해야할 사항이 있을 때 정상적으로 작동되지 않는 경우도 있다.

@Before, @After 어드바이스는 기능은 적지만 원하는대로 작동되고 코드도 단순하다.

 

좋은 설계는 @Around만 사용해서 모두 해결하는 것보다는 제약을 가지더라도 실수를 미연에 방지하는 것이다.

제약을 두면 문제 자체가 발생하지 않고 역할이 명확해진다.

 

 

 

 

 

❑ Pointcut 표현식

 

 

➤ 포인트컷과 표현식&지시자

 

▶️ 포인트컷

관심 조인 포인트를 결정

어드바이스가 실행되는 시기를 제어

AspectJ는 포인트컷을 편리하게 표현하기 위한 표현식을 제공

ex) @Pointcut(“execution(* hello.aop.order..*(..))”)

 

 

▶️ 포인트컷 지시자(Pointcut Designator, PCD)

 

포인트컷 지시자 종류

종류 설명
excution 메서드 실행 조인트 포인트를 매칭한다. 스프링 AOP에서 가장 많이 사용하며, 기능도 복잡하다
within 특정 타입 내의 조인포인트를 매칭한다
args 인자가 주어진 타입의 인스턴스인 조인 포인트
this 스프링 객체(스프링 AOP proxy) 대상으로 하는 조인 포인트
target Target 객체(스프링 AOP proxy 가르키는 실제 대상) 대상으로 하는 조인 포인트
@target 실행 객체의 클래스에 주어진 타입의 애너테이션이 있는 조인 포인트
@within 주어진 애너테이션이 있는 타입 조인 포인트
@annotation 메서드가 주어진 애너테이션을 가지고 있는 조인 포인트를 매칭
@args 전달된 실제 인수의 런타임 타입이 주어진 타입의 애너테이션을 갖는 조인 포인트
bean 스프링 전용 포인트컷 지시자, 빈의 이름으로 포인트컷을 지정한다.

 

 

 

➤ Pointcut 표현식 결합

 

&&, ||, ! 를 사용하여 결합할 수 있다.

이름으로 포인트컷 표현식을 참조할 수도 있다.

 

 

▶️ 일반적인 pointcut 표현식들

 

// 모든 공개 매서드 실행
execution(public * *(..))

// set 다음 이름으로 시작하는 모든 메서드 실행
execution(* set*(..))

// AccountService 인터페이스에 의해 정의된 모든 메서드의 실행
execution(* com.xyz.service.AccountService.*(..))

// service 패키지에 정의된 메서드 실행
execution(* com.xyz.servic.*.*(..))

// service 패키지 또는 해당 하위 패키지 중 하나에 정의된 메서드 실행
execution(* com.xyz.service..*.*(..))



// Spring AOP에서만 메서드 실행하는 표현식들

// service 패키지 내의 모든 조인 포인트
within(com.xyz.service.*)

// service 패키지 또는 하위 패키지 중 하나 내의 모든 조인 포인트
within(com.xyz.service..*)

// AcountService 프록시가 인터페이스를 구현하는 모든 조인 포인트
this(com.xyz.service.AccountService)

// AcountService 대상 객체가 인터페이스를 구현하는 모든 조인 포인트
target(com.xyz.service.AccountService)

// 단일 매개변수를 사용하고 런타임에 전달된 인수가 Serializable 과 같은 모든 조인포인트
args(java.io.Serializable)

// 대상 객체가 @Transactional 애너테이션이 있는 조인 포인트
@target(org.springframework.transaction.annotation.Transactional)

// 실행 메서드에 @Transactional 애너테이션이 있는 조인 포인트
@annotation(org.springframework.transaction.annotation.Transactional)

// 단일 매개 변수를 사용하고 전달된 인수의 런타임 유형이 @Classified 애너테이션을 갖는 조인 포인트
@args(com.xyz.security.Classified)

// tradeService 라는 이름을 가진 스프링 빈의 모든 조인 포인트
bean(tradeService)

// 와일드 표현식 *Service 라는 이름을 가진 스프링 빈의 모든 조인 포인트
bean(*Service)

 

 

 

 

 

❑ JoinPoint

 

 

➤ AOP 적용 위치

 

  • AOP는 메서드 실행 위치 뿐만 아니라 다양한 위치에 적용할 수 있다.
  • 적용 가능 지점 : 생성자, 필드 값 접근, static 메서드 접근, 메서드 실행
  • AOP 를 수행하는 메서드는 이 JoinPoint 인스턴스를 인자로 받게 된다.
  • JointPoint 인스턴스에서 조인 포인트의 정보를 얻어내야 한다.

 

 

➤ JoinPoint

 

  • AOP를 적용할 수 있는 지점을 의미하는 추상적 개념
  • 프로그램 실행 중 지점을 나타낸다.
  • AspectJ를 사용해서 컴파일 시점과 클래스 로딩 시점에 적용하는 AOP는 바이트코드를 실제 조작하기 때문에 해당 기능을 모든 지점에 적용할 수 있다.
  • 프록시 방식을 사용하는 Spring AOP메서드 실행 지점에만 AOP를 적용할 수 있다.
  • 프록시는 메서드 오버라이딩 개념으로 동작한다.
  • 생성자나 static 메서드, 필드값 접근에는 프록시 개념이 적용될 수 없다. (프록시는 스프링 AOP에서 사용하기 때문)
  • 프록시를 사용하는 스프링 AOP의 조인 포인트는 메서드 실행으로 제한된다.
  • 프록시 방식을 사용하는 스프링 AOP는 스프링 컨테이너가 관리하는 스프링 빈에만 AOP를 적용할 수 있다.
  • JoinPoint 메서드는 advice의 종류에 따라 사용방법이 다르지만 기본적으로 advice 메서드에 매개변수로 선언만 하면 된다.

 

 

 

➤ JoinPoint Interface의 주요 기능

 

  • JoinPoint.getArgs() : JoinPoint에 전달된 인자를 배열로 반환한다.
  • JoinPoint.getThis() : AOP 프록시 객체를 반환한다.
  • JoinPoint.getTarget() : AOP가 적용된 대상 객체를 반환한다. (클라이언트가 호출한 비즈니스 메서드를 포함하는 비즈니스 객체를 반환)
  • JoinPoint.getSignature() : advice되는 메서드에 대한 설명을 반환한다.
  • JoinPoint.toString() : advice되는 방법에 대한 유용한 설명을 인쇄한다.

 

 

➤ ProceedingJoinPoint Interface의 주요 기능

 

▶️ ProceedingJoinPoint Interface

얜 또 뭐야...

https://www.javadoc.io/doc/org.aspectj/aspectjrt/1.7.2/org/aspectj/lang/ProceedingJoinPoint.html

 

ProceedingJoinPoint - aspectjrt 1.7.2 javadoc

Latest version of org.aspectj:aspectjrt https://javadoc.io/doc/org.aspectj/aspectjrt Current version 1.7.2 https://javadoc.io/doc/org.aspectj/aspectjrt/1.7.2 package-list path (used for javadoc generation -link option) https://javadoc.io/doc/org.aspectj/as

www.javadoc.io

 

JoinPoint 인터페이스를 extends하는 인터페이스 이다
  • proceed() : 다음 어드바이스나 타겟을 호출한다.

 

 

 

 

❑ 애너테이션(Annotation)을 이용한 AOP

 

 

➤ Spring에서의 AOP

 

AOP는 스프링 IoC를 보완하여 매우 강력한 미들웨어 솔루션을 제공한다.

 

▶️ Spring AOP 지원

  • @AspectJ 애너테이션 스타일
  • 스키마 기반 접근

 

 

▶️ @AspectJ 지원

 

  • @AspectJ는 애너테이션이 있는 일반 자바 클래스로 aspect를 선언하는 스타일을 말한다.
  • AspectJ 5 릴리스의 일부로 AspectJ 프로젝트에 의해 도입되었다.
  • 스프링은 pointcut 구문 분석 및 일치를 위해 AspectJ가 제공하는 라이브러리를 사용하여 AspectJ 5와 동일한 애너테이션을 해석한다.
  • AOP 런타임은 여전히 순수한 스프링 AOP이며, AspectJ 컴파일러 위버(weaver)에 의존하지 않는다.

 

 

▶️ @AspectJ 지원 활성화

 

  • Spring 설정에서 @AspectJ 에 기반한 Spring AOP 설정과 이러한 aspect에 의해 advice되는 자동 프록시 빈에 대한 Spring 지원을 활성화 해야한다.
  • @AspectJ 지원은 XML 또는 Java 스타일 설정으로 활성화할 수 있다.
  • Java 설정으로 @AspectJ 지원 활성화 방법
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

}
  • XML 설정으로 @AspectJ 지원 활성화 방법
<aop:aspectj-autoproxy/>

 

 

 

➤ Aspect 선언

 

@AspectJ 지원이 활성화

-> @AspectJ aspect(@Aspect 애너테이션이 있음)이 있는 클래스로 애플리케이션 컨텍스트에 정의된 모든 빈이 Spring에서 자동으로 감지

-> Spring AOP를 구성하는데 사용된다.

 

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectExample {

}

 

 

 

➤ Pointcut 선언

  • pointcut 선언은 이름과 매개변수를 포함하는 Signature와 메서드 실행을 정확히 결정하는 pointcut 표현식의 두 부분으로 구성된다.
  • pointcut 표현식은 @Pointcut 애너테이션 사용

 

 

 

 

읽어주셔서 감사합니다. 좋은하루 되세요 😉

오개념 지적은 환영입니다

 

 

 

 

 

 

➤ 기본 개념

 

  • Spring은 Spring Container를 통해 객체를 관리한다
  • 스프링 컨테이너에서 관리하는 객체를 bean(빈)이라고 한다
  • @Configuration : 클래스 위에 작성하여 해당 클래스가 IoC 컨테이너에 bean definition 소스로 사용될 수 있음을 알려줌
  • @Bean : 메서드 위에 작성하여 해당 메서드가 스프링 컨테이너에 자동 등록되도록 함

 

@Configuration과 @Bean 공식 문서

https://docs.spring.io/spring-framework/docs/3.0.0.M4/reference/html/ch03s11.html

 

3.11 Java-based container configuration

3.11.1 Using the @Configuration annotation The central artifact in Spring's new Java-configuration support is the @Configuration-annotated class. These classes consist principally of @Bean-annotated methods that define instantiation, configuration, and in

docs.spring.io

 

 

 

❑ Bean Definition

 

bean definition = 레시피

bean definition은 configuration metadata 정보를 포함하고 있는 인터페이스이다.

configuration metadata

  • 빈을 어떻게 생성할 것인가
  • 빈의 생명주기에 대한 설명
  • 빈의 종속성

 

 

Bean Definition 참고 자료

https://www.tutorialspoint.com/spring/spring_bean_definition.htm

 

Spring - Bean Definition

Spring - Bean Definition The objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. These b

www.tutorialspoint.com

 

BeanDefinition 필드 및 메서드

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanDefinition.html

 

BeanDefinition (Spring Framework 5.3.21 API)

Return the current bean class name of this bean definition. Note that this does not have to be the actual class name used at runtime, in case of a child definition overriding/inheriting the class name from its parent. Also, this may just be the class that

docs.spring.io

 

 

 

 

 

❑ Bean Scope

 

Spring Framework는 6개의 scope를 지원함

그 중에 4개는 ApplicationContext를 사용하는 경우에만 사용할 수 있음

bean은 여러 scope 중 하나를 설정할 수 있음

사용자 정의 scope를 설정할 수도 있음

 

Scop Description
singleton
(Default) Spring IoC 컨테이너당 단일 인스턴스로 bean definition scpoe를 지정
prototype 스프링 컨테이너가 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프
request 요청이 들어오고 나갈 까지 유지되는 스코프
session 세션이 생성되고 종료될 때까지 유지되는 스코프
application ServletContext 라는 클래스 타입의 객체로 생성되어 서버가 종료될 때까지 유지
websocket 단일 bean definition 범위를 WebSocket 라이프사이클까지 확장함
Spring ApplicationContext 컨텍스트에서만 유효함

 

 

 

➤ 스프링 없는 컨테이너만 사용한 객체 생성방법

 

같은 클래스의 여러 인스턴스를 만들면 서로 다른 주소값을 가진다.

수많은 객체를 생성하게 되면 이 방식은 메모리 낭비가 생기고 효율성이 떨어지게 됨

-> 해결 방법으로 싱글톤 패턴을 사용할 수 있음

 

 

 

 

❑ Singleton Scope

 

싱글톤 패턴 : 클래스의 인스턴스를 단 1개만 생성하도록 하는 디자인 패턴

 

스프링 컨테이너의 시작과 함께 인스턴스가 생성되어 스프링 컨테이너가 종료될 때까지 유지됨

싱글톤 빈의 하나의 공유 인스턴스만 관리

생성자를 private로만 만들어서 외부에서 임의의 new로 인스턴스를 만드는 것을 방지

스프링 컨테이너 종료시 소멸 메서드도 자동으로 실행됨

 

 

 

➤ 싱글톤?

 

싱글톤은 해당 빈의 인스턴스를 오직 하나만 생성해서 사용하는 것을 의미함

단일 인스턴스는 싱글톤 빈의 캐시에 저장됨

이름이 정해진 빈에 대한 모든 요청과 참조는 캐시된 개체를 반환함

싱글톤 스코프의 스프링 빈은 여러번 호출해도 모두 같은 인스턴스의 참조 주소값을 가짐

 

 

▶️ 싱글톤 디자인 패턴은 어떤 때 사용할까?

 

예를 들어 CodeStates라는 회사 클래스와 크루, 수강생 클래스가 있다.

크루와 수강생은 여러 명일 수 있으므로 인스턴스를 여러 개 생성하면 되지만

CodeStates는 어떤 크루나 수강생 객체에서 참조해도 동일한 회사이므로 하나의 인스턴스만 생성해도 된다.

 

싱글톤 예시

 

싱글톤 패턴 적용 코드

public class CodeStates {
	// static 영역에 단일 객체 생성
    private static final CodeStates instance = new CodeStates();
	// getInstance 메서드로만 인스턴스 호출
    public static CodeStates getInstance() {
        return instance;
    }
    // 생성자를 private 으로 선언하여 외부에서 new 키워드로 인스턴스 생성하는 것을 방지
    private  CodeStates() {
    }
    public void getInfo() {
        System.out.println("CodeStates 입니다.");
    }
}

 

 

▶️ 코드 특징

  • static 영역에 객체 인스턴스를 미리 1개 생성함
  • 객체 인스턴스가 필요한 경우 getInstance() 메서드를 통해서만 조회
  • 항상 같은 인스턴스가 호출됨
  • 외부에서 생성자를 new로 새로 만드는 것을 방지하기 위해 private으로 생성자를 생성함

 

스프링 컨테이너의 기본값은 싱글톤이기 때문에 위 코드처럼 직접 static 인스턴스를 만들지 않아도 됨

 

 

 

➤ 싱글톤 패턴의 문제점

 

  • 싱글톤 패턴을 구현하는 코드 자체는 많음
  • 의존 관계상 클라이언트가 구체 클래스에 의존함
  • 지정해서 가져오기 때문에 테스트하기 어려움
  • private 생성자를 사용하여 자식 클래스를 만들기 때문에 유연성이 떨어짐
  • 속성 공유
  • Application 초기 구동 시 인스턴스 생성

 

 

 

➤ 싱글톤 패턴 문제 해결

 

싱글톤 패턴의 문제는 스프링 컨테이너로 해결할 수 있다.

스프링 컨테이너는 싱글톤 컨테이너 역할을 한다.

싱글톤 객체로 생성하고 관리하는 기능을 싱글톤 레지스트리라고 함

스프링 컨테이너의 위 기능 덕분에 싱글톤 패턴의 모든 단점을 해결하고 객체를 싱글톤으로 유지할 수 있음

 

싱글톤 컨테이너로 관리하려는 객체의 클래스에 @Configuration(클래스 위에 작성)와 @Bean(메서드 위에 작성)을 작성해준다.

@Bean을 통해 스프링 컨테이너에 등록됨

 

 

 

➤ 싱글톤 방식 주의점

 

여러 클라이언트가 하나의 객체 인스턴스를 공유하기 때문에 몇가지 조심할 부분이 있다.

상태를 유지하게(stateful) 설계하면 안된다. 무상태(stateless)로 설계해야 한다.

  • 특정 클라이언트가 값을 변경할 수 있으면 안됨
  • 특정 클라이언트에서 의존적인 필드가 존재하면 안됨
  • 클라이언트가 수정할 수 있으면 안됨, 읽기만 가능해야함
  • 스프링 빈의 공유 값을 설정하면 장애가 발생할 수 밖에 없음 -> 공유되지 않는 지역변수, 매개변수 사용

 

 

 

싱글톤 이외의 다른 Scope Reference

https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-scopes

 

5. The IoC container

The BeanFactory provides the underlying basis for Spring's IoC functionality but it is only used directly in integration with other third-party frameworks and is now largely historical in nature for most users of Spring. The BeanFactory and related interfa

docs.spring.io

 

 

 

 

 

읽어주셔서 감사합니다. 좋은하루 되세요.🥰

오개념에 대한 지적은 언제나 환영입니다~

 

 

 

 

 

 

❑ Spring Container

 

 

 

스프링 프레임워크의 핵심 컴포넌트

스프링 컨테이너는 내부에 존재하는 애플리케이션 빈의 생명주기(생성, 관리, 제거 등)를 관리한다.

 

 

▶️ 스프링 컨테이너가 무엇일까?

 

Spring Container

 

ApplicationContext를 스프링 컨테이너라고 한다.

인터페이스로 구현되어있다. (다형성 적용)

 

스프링 컨테이너는 XML, 애너테이션 기반의 자바 설정 클래스로 만들 수 있다.

예전에는 xml을 통해 모두 설정해줬지만 복잡한 설정들을 Spring Boot를 사용하면서 거의 사용하지 않게되었다.

빈의 인스턴스화, 구성, 전체 생명주기, 제거까지 처리한다.

컨테이너는 개발자가 정의한 Bean을 객체로 만들어 관리하고 개발자가 필요할 때 제공한다.

원하는 만큼 많은 객체를 가질 수 있다.

의존성 주입을 통해 애플리케이션의 컴포넌트를 관리한다.

  • 스프링 컨테이너는 서로 다른 빈을 연결해 애플리케이션의 빈을 연결하는 역할을 한다.
  • 개발자는 모듈 간에 의존 및 결합으로 인해 발생하는 문제로부터 자유로울 수 있다.
  • 메서드가 언제, 어디서 호출되어야하는지, 메서드 호출에 필요한 매개변수를 준비해서 전달하지 않는다.

 

 

▶️ 왜 스프링 컨테이너를 사용할까?

 

new 생성자를 사용해서 객체를 생성할 필요가 없다. -> 낮은 결합도

객체간의 참조가 많을수록 의존성이 높아진다.

높은 의존성은 객체지향 프로그래밍의 핵심 중 하나인 낮은 결합도를 지키지 못하게 한다.

그래서 의존성을 낮추기 위해 스프링컨테이너가 필요하다.

 

 

▶️ 기존 방식 vs Spring Container

 

  • 기존의 방식 : 새로운 정책이 생길 때 마다 변경 사항을 일일이 수정해야 했다. 작업 초반부는 하나하나 수정할 수 있지만 코드가 거대해질 경우 의존도가 높아져있고 그에 따른 코드 변경 시간이 많이 들어간다.
  • Spring Container : 구현 클래스에 있는 의존을 제거하여 인터페이스에만 의존하도록 설계한다. 거대한 코드를 수정할 때도 일부분만 수정하면된다.

 

 

▶️ 스프링 컨테이너의 생성 과정은 어떻게 될까?

 

주로 사용하게 되는 설정방식은 Java 기반의 애너테이션 기반 설정이다.

(하지만 XML 방식에 대해서도 이해를 하고 있어야 한다.)

 

참고) XML 이란 무엇인가?

XML(eXtensible Markup Language) W3C에서 개발된, 다른 특수한 목적을 갖는 마크업 언어를 만드는데 사용하도록 권장하는 다목적 마크업 언어

다른 많은 종류의 데이터를 기술하는데 사용할 수 있다.

주로 다른 종류의 시스템, 특히 인터넷에 연결된 시스템끼리 데이터를 쉽게 주고 받을 수 있게하여 HTML의 한계를 극복

텍스트 데이터 형식으로 유니코드를 사용(전 세계 언어 지원)

지금은 임의의 자료구조를 나타내는데 널리 사용됨 (대표적인 예가 웹 서비스)

- 위키백과 -

 

 

Configuration Metadata 사용

※ Configuration Metadata 가 무엇일까?

⬇️ 공식문서

https://docs.spring.io/spring-boot/docs/current/reference/html/configuration-metadata.html

 

Configuration Metadata

Configuration metadata files are located inside jars under META-INF/spring-configuration-metadata.json. They use a JSON format with items categorized under either “groups” or “properties” and additional values hints categorized under "hints", as sh

docs.spring.io

 

스프링 컨테이너는 매개변수로 넘어온 설정 클래스 정보를 사용하여 스프링 빈을 등록한다.

new AnnotationConfigApplicationContext(구성정보.class) 로 스프링에 있는 @Bean의 메서드를 등록

애너테이션 기반의 자바 설정 클래스로 Spring을 만드는 것을 의미한다.

 

XML 기반으로 만드는 ClassPathXmlApplicationContext도 있다.

XML 기반 메타데이터의 기본 구조

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>


    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>


     <!-- more bean definitions go here -->

</beans>

 

<beans id=“...”> : 빈 정의를 식별하는데 사용되는 문자열

<beans class=“...”> : 빈의 유형을 정의하고 클래스 이름을 사용

 

 

 

➤ 스프링 컨테이너의 종류

 

▶️ BeanFactory

스프링 컨테이너의 최상위 인터페이스

빈을 등록하고 생성, 조회하고 돌려주는 등 빈을 관리하는 역할

getBean() 메서드를 통해 빈을 인스턴스화 할 수 있음

@Bean이 붙은 메서드 명을 스프링 빈의 이름으로 사용하여 빈 등록

 

 

▶️ ApplicationContext

BeanFactory의 기능을 상속함

BeanFactory 기능 + 부가기능 제공

참고) 부가기능

  • MessageSource : 메세지 다국화를 위한 인터페이스
  • EnvironmentCapable : 개발, 운영 등 환경변수 등으로 나눠 처리, 애플리케이션 구동 시 필요한 정보들을 관리하는 인터페이스
  • ApplicationEventPublisher : 이벤트 관련 기능을 제공하는 인터페이스
  • ResourceLoader : 파일, 클래스 패스, 외부 등 리소스를 편리하게 조회

 

 

※ 컨테이너 인스턴스화

ApplicationContext 생성자에 제공된 위치 경로는 컨테이너가 로컬 파일 시스템, Java CLASSPATH 등과 같은 다양한 외부 리소스로부터 구성 메타데이터를 로드할 수 있도록 하는 리소스 문자열

 

 

➤ new와 생성자 주입 코드 차이점

 

new를 사용하는 대신 생성자를 통해 의존 객체가 주입되고 느슨한 의존 관계가 이루어짐 -> 객체지향적 프로그래밍 가능

구현 클래스는 Bean 설정에 따라 유연하게 변하게

생성자가 주입된 객체 입장에서는 어떤 구현 객체가 주입될 지 알 수 없고 알 필요도 없음

어떤 객체가 주입될 지는 외부에서 결정

생성자가 주입된 객체는 오로지 실행에만 집중하게 됨

 

 

 

❑ Bean(빈)

 

➤ 빈이란?

 

스프링 컨테이너에 의해 관리되는 재사용 소프트웨어 컴포넌트이다.

 

Spring 컨테이너가 관리하는 자바 객체를 의미하며 하나 이상의 빈을 관리한다.

빈은 인스턴스화된 객체를 의미함

스프링 컨테이너에 등록된 객체를 스프링 빈이라고 함

 

참고) Spring Bean != Java Bean

자바 빈

  • private로 선언된 필드와 Getter/Setter로만 이루어져 있다
  • 생성자가 없는 no-Argument 생성자만 존재한다
  • java.io.Serializable을 구현한다

스프링 빈은 스프링 컨테이너에 등록된 객체를 의미한다.

 

@Bean이 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록함

빈은 클래스의 등록정보, Getter/Setter 메서드를 포함

빈은 컨테이너에 사용되는 설정 메타데이터로 생성됨

설정 메타데이터

  • XML / 자바 애너테이션, 자바코드로 표현함
  • 컨테이너의 명령과 인스턴스화, 설정, 조립할 객체를 정의함

 

 

➤ Bean 접근방법

 

ApplicationContext를 사용하여 bean 정의를 읽고 액세스할 수 있음

  • getBean을 사용하여 bean의 인스턴스를 가져올 수 있음
  • ApplicationContext 인터페이스는 bean을 가져오는 몇 가지 방법들이 있음
  • 응용프로그램 코드에서는 getBean() 메서드로 호출하여 사용하면 안된다. (IoC/DI)

 

 

➤ BeanDefinition

 

스프링은 다양한 설정 형식을 BeanDefinition이라는 추상화 덕분에 지원할 수 있음

빈은 BeanDefinition(빈 설정 메타정보)으로 정의되고 BeanDefinition에 따라서 활용하는 방법이 달라짐

BeanDefinition(빈 설정 메타정보)

  • 속성에 따라 컨테이너가 Bean을 어떻게 생성하고 관리할지 결정함
  • @Bean / <bean> 당 1개씩 메타 정보가 생성됨
  • Spring이 설정 메타정보를 BeanDefinition 인터페이스를 통해 관리하기 때문에 컨테이너 설정을 XML이나 Java코드로 설정할 수 있음(스프링 컨테이너는 설정 형식이 무엇인지 모르고 BeanDefinition만 알면 됨)

 

 

 

 

읽어주셔서 감사합니다. 좋은하루 되세요 🤗

오개념에 대한 지적은 언제나 환영입니다.

 

 

 

프로그램을 짤 때 좋은 코드인지 볼 수 있는 척도 중 하나

느슨한 결합도 높은 응집도

 

오늘은 어제 다 못한 스프링 트라이앵글을 마저 학습했다.

오늘 학습한건 AOP와 PSA이다.

Spring 삼각형

 

 

❑ AOP(Aspect Oriented Programming)

 

 

➤ AOP란?

 

번역하면 관심지향 프로그래밍

객체 지향은 알겠는데 관심지향 프로그래밍에서 관심은 무엇을 의미할까?

 

고양이를 키우는 집사들은 다 다른 방식으로 키운다.

어떤 집사는 고양이에게 좋은 음수대를 사주고 또 어떤 집사는 비싼 캣타워를 사준다.

이렇게 집사들의 고양이 키우는 방식은 다 다르지만 모두 공통적으로 고양이의 행복을 바란다.

집사들이 고양이의 행복이라는 공통 관심사를 가지고 있는 것처럼 AOP에서 'Aspect'는 애플리케이션에 필요한 기능 중에서 공통적으로 적용되는 기능에 대한 관심이다.

 

 

➤ 공통 관심사항과 핵심 관심사항

 

AOP에서 관심사항에는 공통 관심사항핵심 관심사항이 있다.

공통 관심사항 : 애플리케이션 전반에 걸쳐 공통적으로 사용하는 기능들에 대한 관심사

핵심 관심사항 : 비즈니스 로직, 애플리케이션의 주 목적을 달성하기 위한 핵심 로직에 대한 관심사

핵심 관심사항과 반대되는 의미에서 공통 관심사항을 부가 관심사항이라고 부르기도 한다.

 

예를 들어서 음식을 주문하는 애플리케이션을 만든다고 했을 때

핵심 기능에는 음식 선택, 계산, 주문 취소가 들어갈 수 있고

공통적으로 들어가는 기능에는 로깅, 보안, 트랜잭션이 있다.

관심사 예시

 

공통 관심사와 핵심 관심사를 그림으로 그려보면 위와 같이 그려진다.

핵심기능과 부가기능은 떨어져 있고 부가기능들이 핵심기능을 관통한다.

결론적으로 AOP는 애플리케이션을 만들 때 핵심기능 로직에서 공통기능 로직을 분리해서 따로 작성하는 것이다.

 

 

 

➤ 왜 AOP가 필요할까?

 

핵심 로직과 공통 로직을 분리하면 다음과 같은 장점이 있다.

  • 코드가 간결해진다
  • 객체 지향적으로 설계할 수 있다
  • 코드를 재사용하기 쉽다

 

 

※ AOP의 예시로 학습자료에 있던 JDBC 트랜잭션에서 중요한 부분을 정리해보았다.

트랜잭션(Transaction) : 데이터를 처리하는 하나의 작업 단위

같은 트랜잭션 내에 있는 기능 중 하나라도 오류를 발생하면 모든 작업은 취소된다. (All or Nothing)

모든 작업이 정상적으로 수행되어야만 정상적으로 반영한다. (commit)

하나의 작업이라도 실패하면 모든 작업을 롤백(rollback) 시킨다.

 

 

 

 

❑ PSA(Portable Service Abstraction)

 

 

➤ 추상화(Abstraction)의 개념

 

어떤 클래스의 본질적인 특성만을 추출해서 일반화 하는것을 추상화라고 한다.

설계의 관점에서는 추상화보다 일반화가 적절한 용어이다.

자바에서 추상화의 대표적인 방법이 인터페이스(Interface) 이다.

 

클라이언트가 추상화된 상위 클래스를 일관적으로 바라보며 하위 클래스들의 기능을 사용하는 것이 일관된 서비스 추상화(PSA)이다.

여기서 클라이언트의 영역에 대해서 조금 생각해보자.

서버/클라이언트에서 클라이언트는 서버측의 기능을 이용하는 입장이다.

대표적인 클라이언트는 웹 브라우저이다.

하지만 코드 레벨에서 어떤 클래스의 기능을 사용하는 측 역시 클라이언트라고 부른다.

 

 

➤ 서비스에 적용되는 일관된 서비스 추상화(PSA) 기법

 

예시로 java 콘솔 애플리케이션에서 클라이언트가 데이터베이스에 연결하기 위해서는 JdbcConnector라는 기능을 사용하려고 한다.

JdbcConnector는 애플리케이션에서 사용하는 서비스 중 하나라고 생각하면 된다.

데이터베이스에 연결하기 위한 JDBC 인터페이스의 구현체는 OracleJdbcConnector, MariaDBJdbcConnector, SQLiteJdbcConnector가 있다.

이때 클라이언트가 JDBC의 구현체에 바로 연결하는 것이 아닌 JdbcConnector 인터페이스를 통해 간접적으로 연결되어 느슨한 결합으로 연결되어 있다.

어떤 JdbcConnector를 이용해도 JDBC에 작성되어 있는 공통기능을 일관된 방식으로 사용할 수 있다.

기능이 작동하는 방식은 각각의 JDBC를 구현한 객체에 작성되어 있는데로 작동한다.

 

이처럼 애플리케이션에서 서비스의 기능을 접근하는 방식 자체를 일관되게 유지하면서 기술을 유연하게 사용할 수 있도록 하는 것을  PSA(일관된 서비스 추상화)라고 한다.

 

 

➤ PSA가 필요한 이유

 

어떤 서비스를 이용하기 위한 접근 방식을 일관된 방식으로 유지해서

애플리케이션에서 사용하는 기술이 변경되더라도 최소한의 변경만으로 변경된 요구사항을 반영하기 위해서이다.

 

PSA를 통해서 애플리케이션의 요구 사항 변경에 유연하게 대처할 수 있다.

 

Spring에서 PSA가 적용되는 분야로는 트랜잭션 서비스, 메일 서비스,  Spring Data 서비스 등이 있다.

 

 

 

 

 

읽어주셔서 감사합니다. 🥰 좋은하루 되시길 바랍니다.

오개념에 대한 지적은 늘 환영입니다. ^^

 

 

 

Spring 삼각형

 

 

Spring 삼각형

 

위의 Spring 삼각형 그림은 Spring의 핵심 개념들을 모두 표현한 모형이다.

 

POJO는 다른 핵심 개념들에 둘러 싸여져 있다.

POJO는 Ioc/DI, AOP, PSA를 통해서 달성할 수 있다는 것을 의미한다.

 

 

 

❑ POJO(Plain Old Java Object)

 

➤ POJO란?

JO’는 java object라는 뜻이다.

자바는 객체 끼리 관계를 맺을 수 밖에 없는 객체 지향 프로그래밍이다.

그렇다면 ‘PO’는 무엇일까?

P’는 plain 이란 의미다.

플레인은 보통 아무것도 들어가지 않은 순수한 상태를 의미한다. (플레인 요거트를 떠올려보자)

따라서 POJO는 자바로 생성하는 순수한 객체를 의미한다.

 

➤ POJO 프로그래밍이란?

POJO를 이용해서 프로그래밍 코드를 작성하는 것

그러나 단순히 순수한 자바 객체를 사용해서 코드를 작성한다고해서 POJO 프로그래밍이라고 볼 수는 없다.

 

※ 아래의 두가지 규칙을 지켜야 POJO 프로그래밍 이라고 부를 수 있다.

1. Java나 Java의 스펙(사양)에 정의된 것 이외에는 다른 기술이나 규약에 얽매이지 않아야 한다.

특정 기술을 상속해서 코드를 작성하게 되면 나중에 애플리케이션의 요구사항이 변경되어 다른 기술로 변경하려면 클래스를 명시적으로 사용했던 부분을 전부 다 일일이 제거하거나 수정해야한다.

 

2. 특정 환경에 종속적이지 않아야 한다.

 

 

➤ POJO 프로그래밍이 필요한 이유

  • 특정 환경이나 기술에 종속적이지 않으면 재사용 가능하고, 확장 가능한 유연한 코드를 작성할 수 있다.
  • 저수준 레벨의 기술과 환경에 종속적인 코드를 애플리케이션 코드에서 제거함으로써 코드가 깔끔해진다.
  • 코드가 깔끔해지기 때문에 디버깅하기도 상대적으로 쉽다.
  • 특정 기술이나 환경에 종속적이지 않기 때문에 테스트가 단순해진다.
  • 객체지향적인 설계를 제한없이 적용할 수 있다.

 

 

 

➤ POJO와 Spring의 관계

 

Spring은 POJO 프로그래밍을 지향하는 Framework이다.

그리고 최대한 다른 환경이나 기술에 종속적이지 않도록 작성하기 위해 IoC/DI, AOP, PSA의 3가지 기술을 지원하고 있다.

 

애플리케이션 프로그래밍 코드를 작성할 때 항상 내가 작성한 코드가 객체지향스러운가에 대한 고민을 하는 습관을 가져야 한다. 

 

 

 

 

❑ IoC(Inversion Of Control)/DI(Depedency Injection)

 

Library는 애플리케이션 흐름의 주도권이 개발자에게 있고 Framework는 애플리케이션 흐름의 주도권이 Framework에 있다.

여기서 말하는 애플리케이션 흐름의 주도권뒤바뀐 것IoC(Inversion of Control)이라고 한다.

 

 

▶️ Java 콘솔 애플리케이션의 일반적인 제어권

순수 자바 코드만으로 콘솔에 메시지를 출력하는 프로그램을 만들었다고 가정해보자.

일반적으로 자바 콘솔 애플리케이션이 실행되면 main() 메소드가 가장먼저 호출된다.

그리고 순서대로 System 클래스를 통해서 static 멤버 변수인 out의 println()이 호출된다.

이렇게 개발자가 작성한 코드를 순차적으로 실행하는게 일반적인 애플리케이션의 제어 흐름이다.

 

 

▶️ Java 웹 애플리케이션에서 IoC가 적용된다면?

 

서블릿 컨테이너의 서블릿 호출 모형

 

웹에서 동작하는 애플리케이션의 경우 클라이언트가 외부에서 접속해서 사용하는 서비스이기 때문에 main() 메서드가 종료되지 않아야 한다.

그런데 서블릿 컨테이너에는 서블릿 사양에 맞게 작성된 서블릿 클래스만 존재하고 별도의 main()메서드는 존재하지 않는다.

main()메서드처럼 애플리케이션의 시작되는 지점엔트리 포인트(Entry point)라고 부른다.

main()메서드가 없이 어떻게 애플리케이션이 실행되는 것일까?

클라이언트의 요청이 들어올 때마다 서블릿 컨테이너 내의 컨테이너 로직(service() 메서드)이 서블릿을 직접 실행시켜주기 때문에 main()메서드가 필요없는 것이다.

서블릿 컨테이너가 서블릿을 제어하고 있기 때문에 애플리케이션의 주도권은 서블릿 컨테이너에 있다.

여기서 서블릿과 웹 애플리케이션 간에 IoC의 개념이 적용되어 있는 것이다.

 

그렇다면 Spring에는 IoC의 개념이 어떻게 적용되어 있을까?

Spring에서 IoC는 DI(Dependency Injection)을 통해 적용된다.

 

 

 

➤ DI(Dependency Injection)란?

 

IoC 개념을 조금 더 구체화 시킨 것

Depencency는 ‘의존하는, 종속하는’ 이라는 의미이고 injection은 ‘주입’이라는 의미이다.

따라서 DI는 직역하면 '의존성 주입' 이라는 뜻이다.

 

 

 

▶️ 의존성 주입은 무엇일까?

 

객체지향프로그래밍에서 의존성은 대부분 객체 간의 의존성을 의미한다.

예를 들어 A, B의 두개의 클래스가 있다.

A클래스가 B클래스를 호출하는 다이어그램

A클래스는 B클래스 내부의 메서드를 호출하여 사용하도록 작성하였다.

이 때 ‘A클래스는 B클래스에 의존한다’라고 한다.

쉽게 말해 ‘A 클래스의 프로그래밍 로직 완성을 위해 B클래스에 도움을 요청한다’ 고 볼 수 있다.

 

※ 다이어그램

클래스간의 관계를 나타내는 다이어그램은 애플리케이션 설계를 위해 자주 사용된다. (애플리케이션 설계에 있어 중요한 역할!)

도구 : VisualParadigm

 

 

A클래스가 B클래스를 의존하는 관계를 코드로 작성해보았다.

public class EnergyController {
    public static void main(String[] args) {
        MonsterDrink monsterDrink = new MonsterDrink();
        int energy = monsterDrink.getCaffeine();
    }
}
public class MonsterDrink {
    public int getCaffeine() {
        return 10;
    }
}

 

위 코드에서 EnergyController 클래스는 클라이언트로부터 요청을 받는 엔드포인트(Endpoint) 역할을 한다.

그리고 MonsterDrink 클래스는 EnergyController 클래스가 전달받은 클라이언트의 요청을 처리하는 역할을 한다.

클라이언트 측면에서 서버의 엔드포인트란 클라이언트가 서버의 자원(리소스)를 이용하기 위한 끝 지점을 의미한다.

 

EnergyController에서 에너지드링크인 MonsterDrink 객체를 생성한 후 MonsterDrink의 getCaffeine() 메소드를 호출하고 있다.

이처럼 객체를 생성해서 참조하게 되면 의존 관계가 성립하게 된다.

 

 

그러나 두 클래스간의 의존 관계가 성립됐지만 아직 의존성 주입은 이루어지지 않았다.

의존성 주입을 하기 위해 코드를 수정해보자.

 

public class EnergyController {
    public static void main(String[] args) {
        MonsterDrink monsterDrink = new MonsterDrink();
        PresentEnergy presentEnergy = new PresentEnergy(monsterDrink);
        int energy = monsterDrink.getCaffeine();
    }
}
public class MonsterDrink {
    public int getCaffeine() {
        return 10;
    }
}
public class PresentEnergy {
    private MonsterDrink monster;
    public PresentEnergy(MonsterDrink monster) {
        this.monster = monster;
    }
}

 

의존성 주입은 생성자를 통해서 어떤 클래스의 객체를 전달 받는 것이다.

생성자의 매개변수로 객체를 전달하는 것을 외부에서 객체를 주입한다고 표현하는 것이다.

그렇다면 여기서 외부는 어디일까?

객체를 매개변수로 전달하고 있는 클래스가 외부이다.

 

클래스의 생성자로 객체를 전달받는 코드가 있다면 객체를 외부에서 주입받고 있어서 의존성 주입이 이루어지고 있다고 볼 수 있다

 

 

 

▶️ 왜 의존성 주입이 필요한가?

 

자바에서 생성자를 통해 객체를 전달하는 일은 아주 흔한 일이다.

하지만 의존성 주입을 사용할 때 클래스 내부에서 외부 클래스의 객체를 생성하기 위한 new 키워드를 사용을 지양해야 한다.

객체를 생성할 땐 당연히 new 키워드를 쓰지만 *Reflection이라는 기법을 이용해서 Runtime시에 동적으로 생성할 수 있는 방법이 있다.

new 키워드를 사용해서 의존 객체를 생성할 때, 클래스들 간의 강하게 결합(Tight Coupling)되어 있다고 한다.

하지만 자주 변경하려면 클래스들 간의 강한 결합은 피하는 것이 시간을 절약할 수 있다.

따라서 강한 결합보다는 느슨한 결합(Loose Coupling)을 사용하는 것이 좋다.

애플리케이션의 요구사항은 언제나 바뀔 수 있기 때문에 코드를 작성할 때 이부분을 고려하는 것이 좋다.

 

 

▶️ 느슨한 의존성 주입은 어떻게 할까?

 

클래스 간의 관계를 느슨하게 하는 대표적인 방법은 바로 인터페이스(Interface)를 사용하는 것이다.

어떤 클래스가 인터페이스 같이 일반화된 구성 요소에 의존하고 있을 때, 클래스들 간의 느슨하게 결합되어 있다고 한다.

예시로 작성했던 코드는 전달할 객체를 생성할 때 new 연산자를 사용했기 때문에 강하게 결합되어 있다.

그런데 여기서 에너지드링크를 monster가 아닌 hotsix로 바꾼다고 하면 코드를 수정할 부분이 많아진다.

하지만 monster와 hotsix의 일반적인 개념인 EnergyDrink라는 인터페이스를 만들어서 monster를 사용한 부분에 EnergyDrink를 작성한다면 어떨까?

moster와 hotsix 중 전달하고 싶은것을 생성할 때 작성하기만 하고 나머지는 수정하지 않아도 된다.

위의 내용을 코드로 구현하면 아래와 같다.

 

public class EnergyController {
    public static void main(String[] args) {
        EnergyDrink energyDrink = new MonsterDrink();
        PresentEnergy presentEnergy = new PresentEnergy(energyDrink);
        int energy = energyDrink.getCaffeine();
    }
}
public interface EnergyDrink {
    public int getCaffeine();
}
public class MonsterDrink implements EnergyDrink {
    @Override
    public int getCaffeine() {
        return 10;
    }
}
public class Hotsix implements EnergyDrink {
    @Override
    public int getCaffeine() {
        return 7;
    }
}
public class PresentEnergy {
    private EnergyDrink energyDrink;
    public PresentEnergy(EnergyDrink energyDrink) {
        this.energyDrink = energyDrink;
    }
}

 

하지만 여전히 EnergyController 클래스 내에서 객체를 생성할 때 new 연산자를 사용하고 있다.

여기서 이 new 연산자는 어떻게 없앨 수 있을까?

 

 

▶️ Spring 에서 의존성 주입을 누가 해주는가?

 

Spring에서 new 키워드로 객체를 생성하지 않고 Spring이 그 역할을 대신 할 수 있다.

new 키워드를 없애려면 Config라는 클래스를 이용하면 된다.

Config에 대해선 차후에 자세히 학습할 예정이기 때문에 지금은 어떤 역할인지만 기억하고 넘어가자.

Config클래스는 객체 생성을 미리 정의해 둔다.

그래서 Spring의 도움을 받아 new 키워드 마저도 없앨 수 있다!

하지만 Config클래스 객체를 new 키워드로 생성한거면 이것도 문제이지 않을까??

아니다. Config 클래스는 단순한 클래스가 아니라 Spring Framework의 영역에 해당하는 것이고 Config 클래스가 실제 애플리케이션의 핵심 로직에 관여하지 않고 있기 때문에 문제가 되지 않는다.

 

Spring 기반의 애플리케이션에서는 Spring이 의존 객체들을 주입해주기 때문에 애플리케이션 코드를 유연하게 구성할 수 있다.

 

 

 

더 공부가 필요한 내용

  • Java Reflection
  • Config

 

 

 

 

 

 

❑ Spring Framework 들어가기전

 

지금까지 Java의 기본과 핵심을 배웠다.

Java의 기본문법만으로 어떤 소프트웨어를 만들 수 있을까?

지금까지 배운것으로는 콘솔 출력 프로그램 또는

Java GUI API인 AWTSwing을 사용한 데스크탑 애플리케이션을 만들 수 있을 것이다.

 

 

➤ AWT(Abstract Window Toolkit)

AWT (출처: 위키)

자바의 본 플랫폼에 의존하는 윈도, 그래픽스, 사용자 인터페이스 위젯 툴킷

GUI를 제공하는 표준 API인 자바 파운데이션 클래스(JFC)의 일부

AWT는 수많은 자바 ME(Java Platform Micro Edition, 임베디드를 위한 자바 플랫폼)를 위한 GUI툴킷이다.

 

 

➤ 스윙(Swing)

Swing (출처: 위키)

자바에서 GUI를 구현하기 위해 JDK에서 기본적으로 제공하는 개발 툴킷

선마이크로시스템즈의 자바기반클래스의 일부

기존에 발표되었던 AWT가 OS및 윈도 시스템의 자원을 그대로 제공하기 때문에 자바에서 지향하는 “Write Once, Run Everywhere(WORE)”를 구현하기 위해 각종 시스템에서 공통적으로 제공하는 버튼, 대화창 등만을 구현했다.

그래서 여러 환경에서 동일한 화면을 보여줄 수 있지만 대신 해당 시스템의 고유한 모습을 보여줄 수 없다.

 

 

 

 

❑ 스프링 실습 환경 구성

 

먼저 설정해야 하는 것들이 몇 가지 있다.

  1. JDK-11 설치
  2. 환경변수에 JAVA_HOME 설정
  3. IntelliJ Community Edition 설치

 

Spring Initializr 공식 사이트로 이동

https://start.spring.io/

원하는 Spring Boot 실행 환경과 필요한 모듈을 포함하는 템플릿 프로젝트를 생성해 준다.

 

Spring Boot 애플리케이션은 WAS 배포용인 War 파일 형태로 배포할 수 있지만, 일반적으로 Spring Boot 애플리케이션은 WAS를 내장하고 있는 Jar 파일 형태로 배포해서 실행한다.

 

 

스프링 != 스프링 부트

스프링 부트는 스프링을 잘 활용하기 위해 스프링에서 나온 프로젝트

 

Packaging : 개발한 코드를 빌드해서 하나의 결과물로 만들어 낸다

 

ADD DEPENDENCIES 에서 ‘Lombok’ 과 ’Spring Web’을 선택하고 GENERATE를 누른다.

그러면 zip 파일이 다운로드 된다.

다운로드한 zip 파일은 압축해제 한다.

그 다음에 intelliJ에서 Open으로 압축을 푼 프로젝트를 열면 된다.

 

 

 

 

❑ Spring Framework 소개

 

 

➤ Framework란?

 

Frame은 틀, 구조, 뼈대 등의 의미이다.

벽에 거는 액자를 프레임이라고 부르기도 한다.

자동차에서는 뼈대가 되는 강판을 프레임이라고 부른다.

이처럼 Frame은 어떤 대상의 큰 틀이나 외형적인 구조를 의미한다.

지금까지 배웠던 것 중에 Framework는 Collections Framework가 있다.

Collections Framework 안에 있는 Map, Set, List 등은 데이터를 저장하기 위해 자주 사용되는 자료구조를 바탕으로 자바에서 제공하는 클래스이다.

그렇다면 콜렉션에 왜 framework라는 말을 붙일까?

자바에서 framework, 틀 하면 제일 먼저 생각나는 것이 인터페이스(Interface)이다.

자바의 콜렉션은 Map, List, Set같은 인터페이스와 그 인터페이스를 구현한 구현체들의 집합이다.

이렇게 Framework는 프로그래밍을 하기 위한 기본적인 틀이나 구조를 제공한다.

그 외에도 프레임워크는 다양한 기능들을 제공한다.

개발하고자 하는 애플리케이션이 다른 애플리케이션과 통신하고 데이터를 데이터 저장소에 저장하는 등의 기능들도 프레임워크나 라이브러리에서 제공한다.

이를 통해 개발자는 애플리케이션의 핵심 로직을 개발하는 것에만 집중할 수 있도록 해준다.

 

 

➤ Framework 와 Library?

 

프레임워크와 라이브러리는 얼핏 보면 같은 개념이지만 차이점이 있다.

프레임워크와 라이브러리는 여러가지 필요한 기능들을 제공한다는 점에서는 비슷하지만 중요한 차이점이 바로 애플리케이션에 대한 제어권이다.

 

라이브러리는 애플리케이션 흐름의 주도권이 개발자에게 있다.

개발자가 짜 놓은 코드내에서 필요한 기능이 있으면 호출해서 자유롭게 사용이 가능하다.

 

이에 반해 프레임워크는 애플리케이션 흐름의 주도권이 개발자가 아닌 프레임워크에 있다.

프레임워크는 불러오면 코드 상에서 보이지 않는 상당히 많은 일들을 한다.

개발자가 메서드내에 코드를 작성해두면 스프링 프레임워크에서 개발자가 작성한 코드를 사용하여 애플리케이션의 흐름을 만들어낸다.

이것이 Spring Framework의 핵심개념 중 하나인 IoC(Inversion Of Control,  제어의 역전)이다.

 

 

 

 

❑ Spring Framework를 배워야 하는 이유

 

 

➤ Spring Framework란?

 

스프링 프레임워크는 Java 기반의 웹 애플리케이션을 개발하는데 필요한 프레임워크이다.

2004년 버전 1.0이 처음 릴리즈 된 이후로 Java 기반의 웹 애플리케이션을 개발하는데 있어 표준이라 해도 과언이 아닐만큼 대세가 되었다.

 

그런데 자바 기반의 웹 애플리케이션을 개발하기 위한 프레임워크는 스프링만 있는 것은 아니다. Apache Struts2, Apache Wicket, JSF(Java Server Faces), Grails 와 같은 자바 또는 JVM 기반의 웹 프레임워크들이 존재한다.

 

▶️ 그런데 왜 스프링 프레임워크가 각광받는 걸까?

대부분의 기업들이 기업용 Enterprise 시스템용 애플리케이션 개발에 있어 Framework를 선택할 때, 개발 생산성을 높이고 어떻게하면 유지보수를 더 용이하게 할 것인가에 많은 초점을 맞춘다. 스프링 프레임워크는 개발 생산성을 향상시키고 유지보수를 용이하게 해주고 그 이상도 달성할 수 있게 해준다.

*기업용 Enterprise 시스템 : 기업의 업무(조직의 업무, 고객을 위한 서비스 등)를 처리해주는 시스템, 대량의 사용자 요청을 처리해야 하기 때문에 서버의 자원 효율성, 보안성, 시스템의 안전성이나 확장성 등을 충분히 고려해서 시스템을 구축한다.

 

Spring Framework를 사용하는 이유는 이전의 기술들을 알아보면 이해할 수 있다.

 

➤ Spring Framework 이전의 기술들

 

▶️ JSP를 이용한 애플리케이션

JSP(Java server page)

백엔드/프론트엔드의 구분없이 코드에 html/Javascript, Java가 뒤섞여 있는 방식이다.

가독성이 떨어지고 유지보수도 매우 어렵다.

프론트엔드/백엔드를 구분하지 않았던 예전엔 양쪽을 모두 개발하는 개발자들이 많았기 때문에 이런 방법을 이용했다.

 

▶️ 서블릿(Servlet)을 이용한 애플리케이션

JSP 방식과 Spring에서도 내부적으로 Servlet 방식을 사용한다.

서블릿은 클라이언트 웹 요청 처리에 특화된 Java 클래스의 일종이다.

서블릿 방식을 이용한다는 의미는 서블릿을 위한 자바 코드가 클라이언트 측 코드에서

분리되어 별도의 자바 클래스로 관리된다는 것을 의미한다.

하는 일에 비해 코드가 너무 길어보인다는 단점이 있다.

 

▶️ Spring MVC를 이용한 애플리케이션

서블릿 방식의 코드를 Spring MVC 방식의 코드로 바꾸면 코드가 간결해진다.

서블릿 방식은 클라이언트의 요청에 담긴 데이터를 꺼내오는 작업을 개발자가 직접 코드로 작성해야하고, 캐릭터셋도 지정해주어야 한다.

하지만 Spring MVC 방식의 코드에서는 눈에 보이지 않지만 그런 작업들을 Spring에서 알아서 처리해준다.

그런데도 Spring 기반의 애플리케이션의 기본 도구를 잡는 설정 작업이 여전히 불편하다는 단점이 있다.

그래서 이러한 문제를 대부분 개선한 Spring Boot가 나왔다.

 

▶️ Spring Boot을 이용한 애플리케이션

이전 기술에서 구현한 것을 더 짧은 코드로 간결하게 작성할 수 있다.

Spring MVC에서 겪었던 설정의 복잡함을 Spring Boot에서는 찾아볼 수 없다.

Spring의 복잡한 설정 작업도 Spring이 대신 처리해주기 때문에 개발자는

애플리케이션의 핵심 비즈니스 로직에만 집중할 수 있게 되었다.

 

 

※ 심화 학습

 

자바 서블릿이란?

자바 서블릿 자체를 사용하는 기술은 현재 거의 사용하고 있지 않지만 Spring MVC같은 자바 기반의 웹 애플리케이션 내부에서 여전히 사용되고 있다.

 

서블릿 컨테이너란?

서블릿 기반의 웹 애플리케이션을 실행해주는 것부터 시작해서 서블릿의 생명주기를 관리하며, 쓰레드 풀을 생성해서 서블릿과 쓰레드를 매핑시켜 주기도 한다.

아파치 톰캣(Apache Tomcat)은 서블릿 컨테이너의 한 종류로써 Spring MVC 기반의 웹 애플리케이션 역시 기본적으로 아파치 톰캣에서 실행 된다.

 

 

 

 

읽어주셔서 감사합니다. 좋은하루 되세요 🦾

오개념 지적은 환영입니다~

 

1