[CS] Spring 뭐시기
Spring Framework란?
- 엔터프라이즈급 어플리케이션을 구축할 수 있는 가벼운 솔루션이자, 원스-스탑-숍(One-Stop-Shop) 원하는 부분만 가져다 사용할 수 있도록 모듈화가 잘 되어 있습니다. IoC 컨테이너입니다.
- 선언적으로 트랜잭션을 관리할 수 있습니다. 완전한 기능을 갖춘 MVC Framework를 제공합니다. AOP 지원합니다.
- 스프링은 도메인 논리 코드와 쉽게 분리될 수 있는 구조로 되어 있습니다.

프레임 워크 모듈
스프링 프레임워크는 약 20개의 모듈로 구성되어 있습니다. 필요한 모듈만 가져다 사용할 수 있습니다.
AOP 와 인스트루멘테이션 (Instrumentation)
spring-AOP : AOP 얼라이언스(Alliance)와 호환되는 방법으로 AOP를 지원합니다. spring-aspects : AspectJ와의 통합을 제공합니다. spring-instrument : 인스트루멘테이션을 지원하는 클래스와 특정 WAS에서 사용하는 클래스로 더 구현체를 제공합니다. 참고로 BCI(Byte Code Instrumentations)은 런타임이나 로드(Load) 때 클래스의 바이트 코드에 변경을 가하는 방법을 말합니다.
메시징(Messaging)
spring-messaging : 스프링 프레임워크 4는 메시지 기반 어플리케이션을 작성할 수 있는 Message, MessageChannel, MessageHandler 등을 제공합니다. 또한, 해당 모듈에는 메소드에 메시지를 맵핑하기 위한 어노테이션도 포함되어 있으며, Spring MVC 어노테이션과 유사합니다.
데이터 엑서스(Data Access) / 통합(Integration)
데이터 엑세스/통합 계층은 JDBC, ORM, OXM, JMS 및 트랜잭션 모듈로 구성되어 있다. spring-jdbc : 자바 JDBC프로그래밍을 쉽게 할 수 있도록 기능을 제공합니다. spring-tx : 선언적 트랜잭션 관리를 할 수 있는 기능을 제공합니다. spring-orm : JPA, JDO및 Hibernate를 포함한 ORM API를 위한 통합 레이어를 제공합니다. spring-oxm : JAXB, Castor, XMLBeans, JiBX 및 XStream과 같은 Object/XML 맵핑을 지원합니다. spring-jms : 메시지 생성(producing) 및 사용(consuming)을 위한 기능을 제공, Spring Framework 4.1부터 spring-messaging모듈과의 통합을 제공합니다.
웹(Web)
웹 계층은 spring-web, spring-webmvc, spring-websocket, spring-webmvc-portlet 모듈로 구성됩니다. spring-web : 멀티 파트 파일 업로드, 서블릿 리스너 등 웹 지향 통합 기능을 제공한다. HTTP클라이언트와 Spring의 원격 지원을 위한 웹 관련 부분을 제공합니다. spring-webmvc : Web-Servlet 모듈이라고도 불리며, Spring MVC 및 REST 웹 서비스 구현을 포함합니다. spring-websocket : 웹 소켓을 지원합니다. spring-webmvc-portlet : 포틀릿 환경에서 사용할 MVC 구현을 제공합니다.
프레임워크 : 작성자(프로그래머)가 쉽게 접근가능하고 만들 수 있는 기본 토대 및 환경
(그런데 강의 내용의 반제품이 더 와닿네요.)
라이브러리 : 작성자가 어떤 로직이나 원하는 연산결과를 얻을 수 있도록 제공하는 함수 또는 그런 기능
(강의 내용을 기반으로 한다면, 반제품을 완제품으로 만들기 위한 망치, 톱, 본드, 사포, 페인트 붓 등등이 라이브러리가 될 것 같습니다.)
###Spring IoC/DI 컨테이너
컨테이너(Container)
컨테이너는 인스턴스의 생명주기를 관리하며, 생성된 인스턴스에게 추가적인 기능을 제공합니다.
예를 들어, Servlet을 실행해주는 WAS는 Servlet 컨테이너를 가지고 있다고 말합니다.
WAS는 웹 브라우저로부터 서블릿 URL에 해당하는 요청을 받으면, 서블릿을 메모리에 올린 후 실행합니다.
개발자가 서블릿 클래스를 작성했지만, 실제로 메모리에 올리고 실행하는 것은 WAS가 가지고 있는 Servlet 컨테이너입니다.
Servlet컨테이너는 동일한 서블릿에 해당하는 요청을 받으면, 또 메모리에 올리지 않고 기존에 메모리에 올라간 서블릿을 실행하여 그 결과를 웹 브라우저에게 전달합니다.
컨테이너는 보통 인스턴스의 생명주기를 관리하며, 생성된 인스턴스들에게 추가적인 기능을 제공하는 것을 말합니다.
IoC(Inversion of Control)
컨테이너가 코드 대신 오브젝트의 제어권을 갖고 있어 IoC(제어의 역전)이라 합니다.
예를 들어, 서블릿 클래스는 개발자가 만들지만, 그 서블릿의 메소드를 알맞게 호출하는 것은 WAS입니다.
이렇게 개발자가 만든 어떤 클래스나 메소드를 다른 프로그램이 대신 실행해주는 것을 제어의 역전이라고 합니다.
DI(Dependency Injection)
DI는 의존성 주입이란 뜻을 가지고 있으며, 클래스 사이의 의존 관계를 빈(Bean) 설정 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것을 말합니다.
DI가 적용 안 된 예
개발자가 직접 인스턴스를 생성합니다.
class 엔진 {
}
class 자동차 {
엔진 v5 = new 엔진();
}

Spring에서 DI가 적용된 예
엔진 type의 v5변수에 아직 인스턴스가 할당되지 않았습니다.
컨테이너가 v5변수에 인스턴스를 할당해주게 됩니다.
@Component
class 엔진 {
}
@Component
class 자동차 {
@Autowired
엔진 v5;
}
IoC : 프로그램이 개발자에게 틀을 강요해서 그 형식으로 만들게 하는것
DI : 강요하는 내용들 ex) 박스를 만들때 높이는 4cm, 너비는 10cm로 해라 등등
장점 : 모양이 정형화 됨으로 유지및 관리가 쉽다,

Spring에서 제공하는 IoC/DI 컨테이너
- BeanFactory : IoC/DI에 대한 기본 기능을 가지고 있습니다.
- ApplicationContext : BeanFactory의 모든 기능을 포함하며, 일반적으로 BeanFactory보다 추천됩니다. 트랜잭션처리, AOP등에 대한 처리를 할 수 있습니다. - BeanPostProcessor, BeanFactoryPostProcessor등을 자동으로 등록하고, 국제화 처리, 어플리케이션 이벤트 등을 처리할 수 습니다.
- BeanPostProcessor : 컨테이너의 기본로직을 오버라이딩하여 인스턴스화 와 의존성 처리 로직 등을 개발자가 원하는 대로 구현 할 수 있도록 합니다.
- BeanFactoryPostProcessor : 설정된 메타 데이터를 커스터마이징 할 수 있습니다.
Spring컨테이너가 관리하는 객체를 빈(Bean)이라고 말합니다. (여러분들이 직접 new연산자로 생성해서 사용하는 객체는 빈(Bean)이라고 말하지 않습니다.) Spring은 빈을 생성할 때 기본적으로 싱글톤(Singleton)객체로 생성합니다. 싱글톤이란 메모리에 하나만 생성한다는 것입니다. 메모리에 하나만 생성되었을 경우, 해당 객체를 동시에 이용한다면 어떤 문제가 발생할 수 있을까요? 이런 문제를 해결하려면 어떻게 해야할까요? ( 참고로 Spring에서 빈을 생성할 때 스코프(scope)를 줄 수 있습니다. 스코프를 줌으로써 기본으로 설정된 싱글톤 외에도 다른 방법으로 객체를 생성할 수 있습니다. )
참고: https://gmlwjd9405.github.io/2018/11/10/spring-beans.html
Java config를 이용한 설정을 위한 어노테이션
@Configuration
스프링 설정 클래스를 선언하는 어노테이션 @Bean
bean을 정의하는 어노테이션 @ComponentScan
@Controller, @Service, @Repository, @Component 어노테이션이 붙은 클래스를 찾아 컨테이너에 등록 @Component
컴포넌트 스캔의 대상이 되는 애노테이션 중 하나로써 주로 유틸, 기타 지원 클래스에 붙이는 어노테이션 @Autowired
주입 대상이되는 bean을 컨테이너에 찾아 주입하는 어노테이션
Spring JDBC
JDBC 프로그래밍을 보면 반복되는 개발 요소가 있습니다. 이러한 반복적인 요소는 개발자를 지루하게 만듭니다. 개발하기 지루한 JDBC의 모든 저수준 세부사항을 스프링 프레임워크가 처리해줍니다. 개발자는 필요한 부분만 개발하면 됩니다.

Spring JDBC 패키지
org.springframework.jdbc.core
JdbcTemplate 및 관련 Helper 객체 제공 org.springframework.jdbc.datasource
DataSource를 쉽게 접근하기 위한 유틸 클래스, 트랜젝션매니져 및 다양한 DataSource 구현을 제공 org.springframework.jdbc.object
RDBMS 조회, 갱신, 저장등을 안전하고 재사용 가능한 객제 제공 org.springframework.jdbc.support
jdbc.core 및 jdbc.object를 사용하는 JDBC 프레임워크를 지원
JDBC Template
org.springframework.jdbc.core에서 가장 중요한 클래스입니다. 리소스 생성, 해지를 처리해서 연결을 닫는 것을 잊어 발생하는 문제 등을 피할 수 있도록 합니다. 스테이먼트(Statement)의 생성과 실행을 처리합니다. SQL 조회, 업데이트, 저장 프로시저 호출, ResultSet 반복호출 등을 실행합니다. JDBC 예외가 발생할 경우 org.springframework.dao패키지에 정의되어 있는 일반적인 예외로 변환시킵니다.
DTO란?
DTO란 Data Transfer Object의 약자입니다. 계층간 데이터 교환을 위한 자바빈즈입니다. 여기서의 계층이란 컨트롤러 뷰, 비지니스 계층, 퍼시스턴스 계층을 의미합니다. 일반적으로 DTO는 로직을 가지고 있지 않고, 순수한 데이터 객체입니다. 필드와 getter, setter를 가진다. 추가적으로 toString(), equals(), hashCode()등의 Object 메소드를 오버라이딩 할 수 있습니다.
DTO의 예
public class ActorDTO {
private Long id;
private String firstName;
private String lastName;
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public Long getId() {
return this.id;
}
// ......
}
DAO란?
DAO란 Data Access Object의 약자로 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 객체입니다. 보통 데이터베이스를 조작하는 기능을 전담하는 목적으로 만들어집니다.
ConnectionPool 이란?
DB연결은 비용이 많이 듭니다. 커넥션 풀은 미리 커넥션을 여러 개 맺어 둡니다. 커넥션이 필요하면 커넥션 풀에게 빌려서 사용한 후 반납합니다. 커넥션을 반납하지 않으면 어떻게 될까요?
ConnectionPool DataSource란?
DataSource는 커넥션 풀을 관리하는 목적으로 사용되는 객체입니다. DataSource를 이용해 커넥션을 얻어오고 반납하는 등의 작업을 수행합니다.
https://lazymankook.tistory.com/30
MVC란?
- MVC는 Model-View-Controller의 약자입니다. 원래는 제록스 연구소에서 일하던 트뤼그베 린즈커그가 처음으로 소개한 개념으로, 데스트톱 어플리케이션용으로 고안되었습니다.
- Model : 모델은 뷰가 렌더링하는데 필요한 데이터입니다. 예를 들어 사용자가 요청한 상품 목록이나, 주문 내역이 이에 해당합니다.
- View : 웹 애플리케이션에서 뷰(View)는 실제로 보이는 부분이며, 모델을 사용해 렌더링을 합니다. 뷰는 JSP, JSF, PDF, XML등으로 결과를 표현합니다.
- Controller : 컨트롤러는 사용자의 액션에 응답하는 컴포넌트입니다. 컨트롤러는 모델을 업데이트하고, 다른 액션을 수행합니다.


참고: https://tte-yeong.tistory.com/70
Spring MVC가 지원하는 메소드 인수 애노테이션
@RequestParam @RequestHeader @RequestBody @RequestPart @ModelAttribute @PathVariable @CookieValue
@RequestParam
- Mapping된 메소드의 Argument에 붙일 수 있는 어노테이션 @RequestParam의 name에는 http parameter의 name과 멥핑 @RequestParam의 required는 필수인지 아닌지 판단
@PathVariable
- @RequestMapping의 path에 변수명을 입력받기 위한 place holder가 필요함 place holder의 이름과 PathVariable의 name 값과 같으면 mapping 됨 required 속성은 default true 임
@RequestHeader
- 요청 정보의 헤더 정보를 읽어들 일 때 사용 @RequestHeader(name=”헤더명”) String 변수명
서블릿은 서블릿 객체를 항상 상속받아서 구현하기 때문에 servlet에 종속적인 프로그램이 되는 반면에
Spring MVC는 서블릿에 종속되지 않고 일반 클래스로 작성할 수 있어 서블릿에 종속되지 않는 프로그램을 작성할 수 있습니다. 다만 Spring MVC로 작성하는 경우에는 프레임워크 구조나 여러가지 어노테이션들을 알아야하기 때문에 배우는 데 시간이 걸릴 수 있습니다.
Controller에서 중복되는 부분을 처리하려면?
별도의 객체로 분리합니다. 별도의 메소드로 분리합니다. 예를 들어 쇼핑몰에서 게시판에서도 회원 정보를 보여주고, 상품 목록 보기에서도 회원 정보를 보여줘야 한다면 회원 정보를 읽어오는 코드는 어떻게 해야 할까요?
컨트롤러와 서비스
- 비지니스 메소드를 별도의 Service객체에서 구현하도록 하고 컨트롤러는 Service객체를 사용하도록 합니다.

컨트롤러와 서비스
####서비스(Service)객체란?
비지니스 로직(Business logic)을 수행하는 메소드를 가지고 있는 객체를 서비스 객체라고 합니다.
보통 하나의 비지니스 로직은 하나의 트랜잭션으로 동작합니다.
트랜잭션(Transaction)이란?
트랜잭션의 특징은 크게 4가지로 구분됩니다.
원자성 (Atomicity) 일관성 (Consistency) 독립성 (Isolation) 지속성 (Durability)
원자성 (Atomicity)
예를 들어 “출금”이라는 기능의 흐름이 다음과 같다고 생각해봅시다.
잔액이 얼마인지 조회한다. 출금하려는 금액이 잔액보다 작은지 검사한다. 출금하려는 금액이 잔액보다 작다면 (잔액 - 출금액)으로 수정한다. 언제, 어디서 출금했는지 정보를 기록한다. 사용자에게 출금한다. 위의 작업이 4번에서 오류가 발생했다면 어떻게 될까요?
4번에서 오류가 발생했다면, 앞의 작업을 모두 원래대로 복원을 시켜야 합니다.
이를 rollback이라고 합니다.
5번까지 모두 성공했을 때만 정보를 모두 반영해야 합니다.
이를 commit 한다고 합니다.
이렇게 rollback 하거나 commit을 하게 되면 하나의 트랜잭션 처리가 완료됩니다.
일관성 (Consistency)
일관성은 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것입니다.
트랜잭션이 진행되는 동안에 데이터가 변경되더라도 업데이트된 데이터로 트랜잭션이 진행되는 것이 아니라, 처음에 트랜잭션을 진행하기 위해 참조한 데이터로 진행됩니다.
이렇게 함으로써 각 사용자는 일관성 있는 데이터를 볼 수 있는 것입니다.
독립성 (Isolation)
독립성은 둘 이상의 트랜잭션이 동시에 병행 실행되고 있을 경우에 어느 하나의 트랜잭션이라도 다른 트랜잭션의 연산을 끼어들 수 없습니다.
하나의 특정 트랜잭션이 완료될 때까지, 다른 트랜잭션이 특정 트랜잭션의 결과를 참조할 수 없습니다.
지속성 (Durability)
지속성은 트랜잭션이 성공적으로 완료되었을 경우, 결과는 영구적으로 반영되어야 한다는 점입니다.
JDBC 프로그래밍에서 트랜잭션 처리 방법
DB에 연결된 후 Connection객체의 setAutoCommit메소드에 false를 파라미터로 지정합니다.
입력, 수정, 삭제 SQL이 실행을 한 후 모두 성공했을 경우 Connection이 가지고 있는 commit()메소드를 호출합니다.
@EnableTransactionManagement
Spring Java Config파일에서 트랜잭션을 활성화 할 때 사용하는 애노테이션입니다.
Java Config를 사용하게 되면 PlatformTransactionManager 구현체를 모두 찾아서 그 중에 하나를 매핑해 사용합니다.
특정 트랜잭션 메니저를 사용하고자 한다면 TransactionManagementConfigurer를 Java Config파일에서 구현하고 원하는 트랜잭션 메니저를 리턴하도록 합니다.
아니면, 특정 트랜잭션 메니저 객체를 생성시 @Primary 애노테이션을 지정합니다.
서비스 객체에서 중복으로 호출되는 코드의 처리
데이터 엑세스 메소드를 별도의 Repository(Dao) 객체에서 구현하도록 하고 Service는 Repository객체를 사용하도록 합니다.
레이어드 아키텍처

레이어드 아키텍처 설정의 분리
Spring 설정 파일을 프리젠테이션 레이어쪽과 나머지를 분리할 수 있습니다.
web.xml 파일에서 프리젠테이션 레이어에 대한 스프링 설정은 DispathcerServlet이 읽도록 하고, 그 외의 설정은 ContextLoaderListener를 통해서 읽도록 합니다.
DispatcherServlet을 경우에 따라서 2개 이상 설정할 수 있는데 이 경우에는 각각의 DispathcerServlet의 ApplicationContext가 각각 독립적이기 때문에 각각의 설정 파일에서 생성한 빈을 서로 사용할 수 없습니다.
위의 경우와 같이 동시에 필요한 빈은 ContextLoaderListener를 사용함으로써 공통으로 사용하게 할 수 있습니다.
ContextLoaderListener와 DispatcherServlet은 각각 ApplicationContext를 생성하는데, ContextLoaderListener가 생성하는 ApplicationContext가 root컨텍스트가 되고 DispatcherServlet이 생성한 인스턴스는 root컨텍스트를 부모로 하는 자식 컨텍스트가 됩니다.
참고로, 자식 컨텍스트들은 root컨텍스트의 설정 빈을 사용할 수 있습니다.
레이어로 구성하지 않을 경우 어떤 문제가 발생할까요? -> 레이어를 구성하지 않는다면, 프로세스 수행을 위한 코드들이 집중되어 있기 때문에, 나중에 코드를 유지보수할 때 복잡하여 어려움이 있을것 같습니다.
레이어를 구성하지 않고 중복코드를 제거할 수 있을까요? ->객체지향의 특성을 살려서, 모듈화 할 수 있지만, 분류가 무분별하여 정리되어있지 않다면 개수가 많아질 수록 관리가 어려워질 것 같습니다.
모든 처리를 presentation에서 하게 되는데 이경우에 Model을 다루는 건지 Controller를 다루는 건지 모호해지는 경우가 생길 수 있습니다.