
자바를 개발하기 위한 프레임워크로서, 절대적이 위치를 차지하고 있다. Java 플랫폼에서의 엔터프라이즈 애플리케이션 개발을 위한 솔루션(Java EE)의 대체재를 제공하기 위해 시작되었다.
서브 프레임워크
Spring Data, Spring Security, Spring Batch, Spring Cloud, Spring AMQP 등 다양한 서브 프레임워크를 포함하고 있어, 개발자가 웹 애플리케이션을 효율적으로 개발할 수 있도록 도와준다.
Spring의 개발 철학
불필요한 것은 없애고, 필요한 것만 남기자!
소프트웨어 개발할 때 도움을 주는 다른 사람들이 만든 소프트웨어
Library
프로그램의 흐름을 개발자가 직접 제어하는 소프트웨어
Framework
Spring Framework의 핵심 개념은 의존성 주입(Dependency Injection)과 관점 지향 프로그래밍(Aspect Oriented Programming)이다.
객체 간의 의존 관계를 관리하고 조정하는 데 중점을 두며, 이를 통해 소프트웨어의 모듈화, 테스트 용이성, 유지보수성을 크게 향상시키는 중요한 설계 패턴
핵심원리
객체가 필요로 하는 의존성을 외부에서 주입받음으로써, 객체의 생명주기와 의존성 관리를 프레임워크에 맡기고, 개발자는 비즈니스 로직에 집중할 수 있도록 하는 것이다.
객체의 생성, 초기화, 의존성 관리 등의 제어 흐름을 애플리케이션 코드가 아닌 IoC 컨테이너가 담당하도록 함으로써, 소프트웨어 설계의 전환점을 제공한다.
개념
애플리케이션의 제어 권한을 애플리케이션 코드에서 IoC 컨테이너로 넘기는 것
즉, 객체의 생성 및 초기화, 그리고 객체 간의 의존성을 IoC 컨테이너가 관리하게 된다.
정리
Spring Framework에서 IoC를 구현하는 주요 방법이 DI이다.
DI는 객체 간의 의존관계를 외부로부터 주입 받는 것이고, 이러한 DI를 IoC컨테이너라고 불리는 Spring Container가 수행하는 것이다.
공통 관심사(cross-cutting concerns)와 같은 비즈니스 로직과는 별도로 처리해야 하는 관심사를 모듈화하여 코드 중복을 줄이고 유지보수성을 높인다.
new를 통해 객체를 선언관심의 분리
정리
OOP에서는 공통적인 핵심 기능을 각 객체의 종단으로 입력했다면, AOP는 핵심 기능에서 중복되는 공통적인 기능을 종단간으로 삽입할 수 있도록 한 것이다.
DI가 의존성(new)의 주입이라면, AOP는 기능(logic)의 주입이라고 할 수 있다.
어플리케이션의 객체를 관리하고, 의존성을 주입하며, 객체 간의 상호작용을 조율하는 중심적인 역할을 수행하는 핵심 구성 요소이다. 스프링 컨테이너는 의존성 주입과 제어의 역전 원칙을 기반으로 작동한다.
핵심 기능
Bean 객체
IoC 컨테이너의 기본 구현체로서, 빈(Bean)이라고 불리는 애플리케이션 객체의 생성, 관리, 의존성 주입을 담당하는 핵심 구성 요소이다. BeanFactory는 애플리케이션의 구성 요소를 관리하며, 객체 간의 결합도를 낮추고 모듈화된 구조를 구현하는 데 중요한 역할을 한다.
주요 기능
빈의 생명주기 관리와 의존성 주입
빈을 초기화할 때 필요한 의존성을 자동으로 주입
IoC컨테이너가 관리하는 Java 객체로, 애플리케이션의 구성 요소로서 중요한 역할을 한다. Spring Container의 BeanFactory에 의해 생성되고 관리되며, 컨테이너는 이 Bean들의 생명주기와 의존성 관리를 책임진다.
빈 팩토리를 상속받아 확장한 IoC 컨테이너로, 스프링 어플리케이션 전반에 걸쳐 모든 구성 요소를 관리, 제어하고, 다양한 기능을 제공하여 애플리케이션 개발의 생산성을 높이는 데에 중요한 역할을 한다. 단순히 Bean을 생성하고 관리하는 기능을 넘어, 애플리케이션 전반에 걸친 다양한 기능을 지원하는 종합적인 컨테이너로서의 역할을 수행한다.
설정 방식
ClassPathXmlApplicationContext : XML 설정 파일을 사용
FileSystemXmlApplicationContext : 파일 시스템에서 XML 설정 파일을 읽어옴
AnnotationConfigApplicationContext : 어노테이션 기반의 설정을 지원
일반적으로 웹 애플리케이션을 사용할 때, 웹 서버는 클라이언트(웹 브라우저)의 요청을 받아서 이를 처리하고, 처리된 결과를 클라이언트에게 반환한다.
Web Server
WAS
자바 언어를 사용해서 웹 페이지를 동적으로 생성하기 위한 기술 사양(명세) 인터페이스
웹 프로그래밍에서 클라이언트 요청을 처리하고 처리 결과를 클라이언트에게 전송하는 기술
doGet(), doPost()등)를 통해 클라이언트와의 상호작용을 처리한다.HTML 안에 자바 코드를 삽입하게 해주는 기술로, 서블릿과 함께 사용된다. JSP 파일은 기본적으로 HTML을 렌더링하는 데 사용되지만, 동적인 데이터를 삽입하거나 서블릿과의 연동을 통해 웹 페이지를 동적으로 생성할 수 있다.
서블릿을 관리해주는 컨테이너로, 대표적으로 톰캣이 있다. 서블릿 컨테이너는 클라이언트의 요청을 받아주고 응답할 수 있도록 객체를 생성하여 웹 서버와 소켓을 만들어 통신한다.

서블릿 컨테이너가 구동될 때 필요한 설정들을 저장해둔 파일로, 배포 설명자(Deployment Descriptor) 라고도 부른다. 웹 애플리케이션에서 사용하는 환경변수를 등록할 수 있다.

(톰캣이라는 서블릿 컨테이너도 있음. 이 그림 밖에 큰 박스가 있다고 생각하면 되고 그게 톰캣)
클라이언트가 HTTP 요청을 보내면, 어떤 메서드와 매핑되어있는지 보고 해당 요청을 적절한 컨트롤러로 분배하는 역할을 하는 클래스
서블릿 컨테이너로부터 들어오는 모든 요청을 Presentation Layer 제일 앞에 두고 전처리를 담당하는 중앙 제어점(Front Controller)이다.
왜 사용할까?
URL마다 서블릿을 등록하는 번거로움을 피하고, 요청을 효율적으로 처리할 수 있다.
Handler Mapping은 요청 URL에 따라 어떤 컨트롤러(Handler)를 호출할지 결정한다.
RequestMappingHandlerMapping 이라는 클래스를 통해 요청 URL과 적합한 컨트롤러 메서드를 매핑한다./user라는 요청이 오면, @RequestMapping("/user")이 선언된 메서드를 찾아 해당 메서드를 실행한다.역할
컨트롤러가 반환한 뷰 이름을 실제 뷰 파일로 변환해주는 역할을 한다.
"greeting"이라는 뷰 이름을 반환하면, ViewResolver는 이를 실제 JSP 파일이나 템플릿 파일로 변환하여 응답을 생성한다.역할
DispatcherServlet이 처리한 결과(모델 데이터와 뷰 이름)를 받아 실제 뷰로 렌더링한다.DispatcherServlet은 Spring MVC에서 모든 요청을 처리하는 중앙 서블릿으로, 요청을 핸들러 매핑을 통해 적절한 컨트롤러로 전달하고, 그 결과를 모델과 함께 반환하고, 뷰 리졸버를 통해 뷰 파일로 변환하여 응답을 생성합니다.
애플리케이션을 모델, 뷰, 컨트롤러라는 3가지 구성요소로 분리한 아키텍처 디자인 패턴
Model
애플리케이션의 데이터와 비즈니스 로직을 처리한다.
View
모델에 있는 데이터를 사용자에게 데이터를 보여주고, 컨트롤러로 데이터를 전달한다.
데이터를 직접적으로 처리하지 않고, 단지 보여주기만 한다.
Controller
클라이언트 측의 요청을 처리하고, 그에 따른 모델에 데이터를 업데이트하거나, 요청에 따른 적절한 View에 넣어서 전달한다.
Spring Framework의 생태계에서 중요한 위치를 차지하는 프로젝트로, 복잡한 Spring 애플리케이션 설정 과정을 단순화하고 개발자의 생산성을 크게 향상시키기 위해 설계되었다.
빈으로 등록될 준비를 마친 클래스들을 스캔하여, 빈으로 등록해주는 것이다. (@Configuration, @Repository, @Service, @Controller, @RestController 포함)
@ComponentScan은 @Component가 붙은 모든 클래스를 스프링 빈으로 등록한다.
메인 클래스에 붙어 있는 @SpringBootApplication은 크게 3가지가 합쳐진 것이라고 생각할 수 있다.
@EnableAutoConfiguration
AutoConfiguration은 결국 Configuration이다.
즉, Bean을 등록하는 자바 설정 파일이다.
스프링 부트에서 필요한 자동설정에 관한 설정을 해준다. ComponentScan을 먼저 진행한 후에 자동설정(Auto Configuration)을 한다.
@SpringBootConfiguration
단순히 Configuration 어노테이션이 적용된 빈임을 나타내는 어노테이션이다.
하나의 클래스는 하나의 기능만, 하나의 책임만을 가져야 하며, 클래스는 그 책임을 완전히 캡슐화 해야 한다.
확장(기능 추가)에는 열려있고, 수정에는 닫혀있어야 한다. 기능의 변경이 있을 때 코드를 확장하여, 기존 코드의 수정을 최소화한다. 기존 코드는 변경하지 않고 기능을 추가할 수 있도록 설계해야 한다.
자식 클래스를 부모 클래스로 문제없이 바꿀 수 있어야 한다. 어떠한 클래스의 서브 타입은 반드시 기반 타입으로 교체될 수 있어야 한다.
예를 들어, Person이라는 클래스와 Person을 상속받은 Bob 클래스가 있을 때, Person 클래스에 있는 walk() 메서드를 오버라이딩한 Bob 클래스의 walk()메서드에서 뜬금없이 fly와 관련된 메서드가 정의되면 안된다는 것이다.
하나의 인터페이스는 하나의 기능만 가지고 있어야 한다. 여러 개로 분리된 인터페이스가 하나의 범용적인 인터페이스보다 낫다. 클라이언트가 사용하지 않는 메서드에 의존하지 않도록 인터페이스는 특정 클라이언트에게 맞게 세분화해야 한다.
예를 들어 Animal 인터페이스에 walk(), fly(), swim() 메서드를 두고, Cat이라는 클래스가 Animal 인터페이스를 구현한다. 이러면 고양이 클래스에게 필요없는 메서드가 생긴다. 그래서 Eatable(), Flyable(), Swimmable() 이라는 인터페이스로 세분화하고 다중 구현하는 것이다.
의존관계를 맺을 때 변하기 쉬운 구체적인 것보다 잘 변하지 않는 추상적인 것에 의존해야 한다. 즉, 구체적인 구현 클래스보다 추상적인 추상클래스, 인터페이스에 의존하라는 것이다.
고수준 모듈이 저수준 모듈에 의존하지 말고 둘 다 추상화에 의존해야 한다. (구현이 아닌 추상화에 의존)
참조를 하면 의존관계가 생긴다고 말한다. 이 때 구현 클래스보단 추상 클래스나 인터페이스에 의존하자.
우와... 오늘 정말.. 내용이 너무 많았다. 처음 하다보니 뭔가 흡수해야 할 게 많았던 것 같다. 그래도 한 번 쭉 정리하고나니 이해가 좀 된다 ! 오늘 실습에서 했던 내용은 헷갈리긴한데.. 스프링부트로 직접 구현할 땐 이렇게 안 한다고 하니 다행이다.
오늘 내용은 너무 많아서 정리했지만,, 다시 한 번 더 봐야할 것 같다. 그리고,, 아직 스프링 부트 실습은 시작도 안 했지만, 지금까지는 재미있는 것 같다 ㅎㅎ 앞으로가 아주 기대가 되는군 !
파이팅하고 남은 오늘 하루도 파이팅해야지 :) 내일 목요일 두근두근