Spring이란?
- Spring Framework는 자바 기반의 강력한 프레임워크로, IoC, DI, AOP와 같은 기능을 통해 효율적이고 안정적인 애플리케이션 개발을 지원한다.
- 현대적인 Java 웹 개발에서는 Spring Boot와 함께 사용하는 경우가 많다.
- 환경설정이 불편하다는 단점을 보완하기 위해 Spring Boot 출시.
Spring의 장점
✔️ 빠른 개발 → DI, AOP, MVC 등의 기능으로 개발 생산성 향상
✔️ 강력한 확장성 → 다양한 모듈과 플러그인 지원
✔️ 테스트 용이성 → JUnit 및 Mock 기반 테스트 지원
✔️ 강력한 커뮤니티 → 광범위한 문서와 레퍼런스 제공
IoC(Inversion of Control, 제어의 역전)
1. IoC란?
- IoC는 객체의 생성, 초기화, 의존성 주입, 생명주기 관리 등의 제어권을 개발자가 아닌 스프링 프레임워크가 담당하는 디자인 원칙입니다.
- "객체의 제어권을 개발자에서 프레임워크로 넘기는 것"*(생성, 의존성 관리, 초기화, 소멸)
- IoC를 사용하지 않는다면 개발자가 직접 객체를 생성, 관리, 소멸 해야함.
- 프로젝트가 커지고 개발자가 직접 관리하는 경우 순환 참조 오류가 발생할 수 있음.
2. IoC의 핵심 개념
- 기존 Java에서는 개발자가 new 키워드로 직접 객체를 생성하고 관리했습니다.
- IoC에서는 스프링이 객체의 생성, 의존성 관리, 초기화, 소멸을 담당합니다.
- 이 기능은 IoC 컨테이너에 의해 자동으로 이루어집니다.
- 스프링은 IoC 컨테이너를 통해 객체(Bean)를 생성하고 관리합니다.
✔️IoC가 없다면 객체 관리에 많은 신경을 써야함.
DI(Dependency Injection, 의존성 주입)
DI란?
- DI는 객체 간의 의존성을 스프링이 자동으로 주입해 주는 기능입니다.
(객체 직접 생성X -> 외부에서 필요한 객체 주입 받는 것)
- 즉, 객체 생성과 의존성 관리를 개발자가 아닌 스프링 컨테이너가 담당하는 설계 방식입니다.
- "개발자는 객체 생성과 초기화를 하지 않고, 스프링이 자동으로 주입한다"라는 것이 핵심입니다.
- @Autowired를 사용하면 Spring이 알아서 필요한 객체를 넣어줌
DI의 장점
- ✔️ 결합도 감소 → 코드의 유연성과 확장성 향상
- ✔️ 테스트 용이성 → Mock 객체를 사용한 단위 테스트가 용이
- ✔️ 객체 관리 자동화 → new 키워드 없이 객체 생성 및 주입 자동화
- ✔️ 유지보수성 향상 → 객체의 변경이 필요할 경우 주입만 변경하면 됨
AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)
AOP란?
- 서비스 로직마다 로깅, 트랜잭션, 보안 처리가 반복되는 것을 막기 위함
- 각 클래스에 필요한 기능이 있으면 같은 기능을 여러 곳에서 관리해야함.
- AOP는 공통 기능(로깅, 보안 등)을 모듈화하여 비즈니스 로직과 분리하는 강력한 기법
- @Aspect, @Before, @After, @Around 등 다양한 기능을 통해 스프링에서 AOP를 구현할 수 있음.
중복 코드 증가 + 유지보수 어려움
AOP의 장점
- ✔️비즈니스 로직과 공통 관심사의 완전한 분리
- ✔️중복 코드 제거 → 유지보수 및 확장성 향상
- ✔️핵심 로직 가독성 강화
- ✔️로깅, 보안, 트랜잭션 등 다양한 기능 추가 가능
Spring의 흐름
흐름 순서
- 클라이언트의 요청 (웹 브라우저 → URL 요청)
- DispatcherServlet이 요청을 받음
- HandlerMapping을 통해 요청을 처리할 Controller 찾음
- Controller에서 서비스 호출
- 서비스에서 비즈니스 로직 수행 → Repository 호출
- Repository에서 DB 접근 후 데이터 반환
- Controller가 반환받은 데이터를 View에 전달
- DispatcherServlet이 View Resolver를 통해 응답 생성
- 클라이언트에 최종 응답 반환
요약
DispatcherServlet(모든 요청을 받아들이는 스프링의 핵심 컨트롤러)
-> HandlerMapping(요청을 처리할 컨트롤러를 찾는 역할)
-> HandlerAdapter(컨트롤러의 메소드를 실행하는 역할)
-> ViewResolver(클라이언트에게 응답 화면을 제공하는 역할)
예제 코드
Controller
- @GetMapping : 클라이언트의 요청을 받을 수 있는 클래스로 만들어줌.(빈 스캐닝)
- RequestMapping(value="url", method=RequestMethod.GET), GetMapping("url")
package com.gn.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
// @Controller 클라이언트의 요청을 받을 수 있는 클래스로 만들어줌.
// 전문용어 : 빈 스캐닝
@Controller
public class HomeController {
// 요청 메소드. 클라이언트가 요청한 url과 연결된 메소드
// @RequestMapping(value="/", method=RequestMethod.GET)
// 위의 아래 두개의 mapping이 같은 것을 의미한다.
// @GetMapping("/")
// 여러개의 url을 적용하고싶다면? 배열 형태는 아래처럼!
@GetMapping({"/",""})
public String home() {
// servlet-context.xml에 어디다 보내는지 써놨다.
// /WEB-INF/views/home.jsp
return "home";
}
}
jsp
- controller에서 설정한 GetMapping의 url(Path)와 동일한 위치에 jsp 생성.
- jsp의 이름은 controller의 메소드의 반환값으로 맞춰준다.
- url="/" 라면 /webapp/WEB-INF - views 폴더 - home.jsp 생성.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
Hello World!!
</body>
</html>
매개변수
// Servlet 방식의 작성법
String title = request.getParameter("title");
// Spring 환경에서 작성법
public String create(@RequestParam("title") String title){
// 컨트롤러 코드
}
✔️순환 참조 오류 : 자기 자신을 참조할 때 발생
ex) A = B + 1과 B = A + 1이 동시에 있는 경우
✔️빈(bean) :
1) IoC 컨테이너가 관리하는 객체를 의미합니다.
2) @Component, @Service, @Controller, @Repository와 같은 어노테이션으로 빈을 등록합니다.