[Spring] Spring 개념정리

최웅진·2023년 6월 26일
0

Spring

목록 보기
1/5

1. Spring FramWork 란?


JAVA 기반의 기업용 애플리케이션 개발을 위한 오픈 소스 애플리케이션 프레임워크이다.
동적인 웹 사이트를 개발하기 위한 여러 가지 서비스를 제공하고 있다.
대한민국 공공기관의 웹 서비스 기발 시 사용을 권장하고 있는 전자정부 표준프레임워크의 기반 기술로서 쓰이고 있다.

Spring Framework

  • 핵심기술: 스프링 DI 컨테이너, AOP, 이벤트...
  • 웹 기술: 스프링 MVC..
  • 데이터 접근 기술: 트랜잭션, JDBC, ORM 지원..
  • 기술 통합: 캐시, 스케줄링..
  • 테스트: 스프링 기반 테스트 지원

스프링을 사용하는 핵심적인 이유는?

스프링 자바(java)언어 기반의 프레임워크이다.
자바 언어의 가장 큰 특징은 객체 지향 언어 인데, 스프링은 이러한 객체지향 언어가 가진 특징을 살려서 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크이다.
(물론, 위에 언급한듯이 웹 애플리케이션을 만들고, 전자 정부 프레임워크이기 때문에 등의 이유도 있다)

💡'좋은 객체 지향 애플리케이션을 개발하는데 어떻게 도움을 주는가?'에 대해서 알아보자면, 객체 지향의 핵심은 다형성 이다.
하지만 다형성 만으로는 클라이언트 코드 변경을 하게 되어, OCP, DIP를 지키기가 어렵다.
그래서 이때, 스프링은 다형성 을 극대화해서 편리하게 이용할 수 있게 지원해주는 기능이다.
그중에서 제어의 역전(IoC), 의존관계 주입(DI)다형성을 활용해서 역할구현을 편리하게 다룰 수 있도록 지원한다.
이를 통해서 우리는 역할에 따른 구현을 레고 블럭 조립하듯이 맘대로 편리하게 변경 할 수 있다.
(이때 역할이 가장 중요하므로 잘 설계되어있어야 문제가 안생긴다!)


📕라이브러리

라이브러리는 개발에 필요한 기능이 있을 때 직접 가져와 사용할 수 있도록 자주 사용되는 기능들을 모아 미리 구현해 둔 것 이다.

예를 들어 JAVA에서는 문자열을 사용할 때 String name = "최웅진"; 이렇게 사용한다.
String은 java.lang.String에 미리 만들어져있는 기능이고 우리는 java.lang.String 이라는 라이브러리에서 기능을 가져와 사용하는것이다.

📕프레임워크

프레임워크도 개발에 필요한 기능이 미리 구현되어 있는 것이다.
하지만 프레임워크에는 라이브러리와 달리 기본 틀이 정해져있다.
때문에 제약없이 사용할 수 있는 라이브러리와 달리 프레임워크는 정해진 틀 안에서 미리 구현 된 기능을 사용해야한다.

스프링 프레임워크에서는 MVC라는 정해진 구조 안에서 개발자가 프로그램을 개발한다.

📕프레임워크 vs 라이브러리 차이

프레임워크, 라이브러리의 가장 큰 차이는 "흐름을 누가 결정하는가"이다.
라이브러리는 개발자가 직접 프로그램의 흐름을 결정하지만 프레임워크는 정해진 흐름에 맞게 개발자가 프로그램을 개발한다.


📕스프링은 아래 그림과 같이 구성되어있는 프레임워크이다. (출처)


2. Spring MVC 구조란?

스프링 프레임워크는 MVC 구조로 이루어져 있다.

📕MVC 구조란?
Model - View - Controller 의 줄임말

Spring의 MVC 구조를 살펴보면 아래와 같다.

  • View - Controller - Service - Serviceimpl - DAO - DAOimpl - DTO
    각 구조에 대해 보면 크게 View, COntoller, Service, DAO, DTO로 이루어져 있다.
    이외에도 DispatcherServlet, servlet-context가 있지만 우선 위 구조만 살펴보자.

  • View
    말 그대로 사용자에게 보여지는 화면을 View라고 한다.
    Spring에서는 JSP를 통해 화면을 구성하고 Controller를 통해 백엔드 서버와 연결한다.

  • Controller
    View와 Service 사이를 연결한다.
    클라이언트에서 입력한 URL에 맞는 View를 보여주고, View에서 처리하는 데이터를 Service로 전달해준다.

@RequestMapping(value = "/")
	public String home() {
    service.method();
    	return "index";
    } // localhost:port/로 접속한 클라이언트에게 index.jsp를 반환한다.
  • Service
    실제 로직을 처리하는 곳으로 모든 기능은 Service에서 만들어진다.
    Controller를 통해 화면과 연결되고, DAO를 통해 데이터베이스와 연결된다.

  • DAO
    Data Access Object의 줄일말인 DAO는 프로젝트와 데이터베이스를 연결한다.
    Mapper에 SQL을 명시한뒤 Mapper와 함께 데이터베이스와 데이터를 주고받는다.

  • DTO
    Data Transfer Object의 줄임말이고 VO(Value Object)라고도 불리는 DTO는 MVC구조 사이사이에서 데이터 교환을 위한 오브젝트이다.
    특이하게 getter/setter 두가지 함수만 가지고 있으며 주로 데이터베이스 테이블과 매칭된다.
    👉DTO와 VO가 완벽하게 같은 말은 아니지만 크게 차이를 두진 않는다.

public class temp { //데이터 베이스 테이블 컬럼과 GET,SET만 가지고있다.
	
    private int id;
    private String name;
    
    public int getId() {return id;}
    public void setId(int id) {this.id = id;}
    
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
}

👉Service -Serviceimpl / DAO - DAOimpl은 무엇일까?
impl은 implement의 줄임말로 Serviceimpl은 Service라는 인터페이스를 implemets,
Daoimpl은 DAO라는 인터페이스를 implements한 것이다.

interface와 impl을 나누어 설계하는 이유는 다음번에 알아보려고한다.

3. Ioc, DI

3-1. Ioc (Inversion of Control)**

IoC를 그대로 해석하면 제어의 역전이다.
무엇인가 제어하는 주체가 바뀐다는 의미인데 어떤 제어가 어떻게 바뀌는 것일까?

Spring을 사용해 본 사람이면 알듯이 Service, DAO같은 객체를 사용자가 직접 생성(new) 하지 않는다.
@Autowired를 통해 받아 사용하는데 이 @Autowired가 IoC(제어의 역전)이다.

//기존 자바 프로젝트

public class order {
	private Customer customer;
    
    public order() {
    	this.customer = new Customer();
    }
}

// Spring 프로젝트
public class order {
	
    @Autowired
    private Customer customer;
}

스프링 컨테이너(IoC container)는 프로젝트에서 사용되는 객체들을 Bean으로 관리하고 있고 @Autowired를 통해 객체를 주입해준다.

기존엔 사용자가 생성(new)해 파라미터로 다른 객체로 보내거나, 사용할 일이 없을 경우 객체를 소멸하는 등 객체에 대한 제어를 직접 진행했다.
하지만 Spring에서는 위처럼 제어를 사용자가 아닌 Spring Framework가 진행하기 때문에 제어의 역전이라고 표현한다.

Spring Bean

Spring에서 Bean은 스프링 프레임워크에 의해서 관리되는 자바 객체이다.

👉Spring Bean은 Java Bean과 다른 의미이다.

IoC는 왜 필요할까?

IoC 프로그램 모델은 곧 역할과 책임의 분리 라는 내용과 관련이 있다.
역할과 책임을 분리해 응집도를 높이고 결합도를 낮추며, 이에 따라 변경에 유연한 코드 를 작성할 수 있는 구조가 될 수 있다.
결국 IoC를 사용하면 결과적으로 객체지향 원칙을 잘 지키는 코드를 만들 수 있다.

서브웨이에 간것을 예시로 들어보자. 🌯

  • 우선, 제어의 역전이 없다면(❌),
    우리는 직접 원하는 대로 재료를 선택한다면 알바생들은 이미 레시피(코드)에 지정되어 있는 재료의 샌드위치가 아니여서 당황을 겪게된다.
    각 재료들에 대한 제어권 이 객체 내부에 있기 때문이다.
    만약 요구를 반영하고자한다면 객체 내에 큰 변경이 생기게 된다.
  • But, 제어를 역전시킨다면(⭕️),
    각 재료들에 대한 제어권을 우리가 갖게 되어 우리가 직접 조합을 요청하여 자신만의 조합의 샌드위치를 주문할 수 있다.
    객체 내부에서 재료의 종류를 제어해 변경이 자유롭지 못하던 코드가 외벵서 제어를 받으면서 변경이 자유롭게 가능해진다.
    이를 통해 위에서 제어의 역전이 없을 때 생기는 큰 변경에 대한 문제를 해결할 수 있게 되었다.

할리우드 법칙 (Hollywood Principle)

Don't call us, we'll call you

우리가 어떤 것을 주도하여 호출하는 것이 아니라, 주도권은 빼앗기고 호출 당하기를 기다리는 모습과 유사하다.

3-2. DI (Dependency Injection)

제 3자가 제어를 관리하는 순간 제어의 역전이고, 스프링이 생기기 전부터 있던 개념이었기에 IoC는 다른 프레임워크와 다른 스프링만의 차별점을 설명하기 부족했다.
그래서 스프링만의 차별점을 설명하기 위해 만들어진 개념이 DI이다.

DI는 Spring에서 IoC 구조를 만드는 방식이다.
DI를 그대로 해석하면 의존성 주입이다. 의존성은 무엇이고 왜 주입할까?
프로그래밍에서 뜻하는 의존성은 객체간의 관계를 먼저 알아야 이해하기 쉽다.

DI를 사용하는 이유는 개체간의 의존성을 줄이기 위함이다.
밖에서 객체를 생성해 넣어주기 떄문에 재사용성이 늘어나고 수정에 용이해진다.

//기존 자바 프로젝트
class concept_api implements Post(){}
class concept_Spring implements Post(){}

class Blog_log() {
private Post post; // 블로그 글 클래스

	public Blog_log() {
    	this.post = new concept_api();
        	this.post = new concept_Spring();
    }
}

// DI
private Post post; // 블로그 글 클래스

	public Blog_log(Post post) {
    	this.post  = new post();
    }

만약 기존 프로젝트 처럼 interface를 직접 만든다면 글마다 CRUD 함수가 필요하지만, DI처럼 의존성을 주입해 사용한다면 Blog_log 하나의 클래스 만으로 모든 글을 관리할 수 있다.

의존관계 주입에서 의존관계주입 은 무엇일까?

  • 의존성
    클래스 간 의존 관계(의존성)가 있다면, 한 클래스가 바뀌면 다른 클래스도 영향을 받는다.
    결국 의존은 영향을 받는 관계라는 것을 의미한다.

  • 주입
    의존성을 다른 곳으로부터 주입해주는 것이다.

의존성은 어떻게 주입하면 될까?

3가지 방법이 존재한다.
1.생성자 주입 , 2.Setter 주입 , 3.Interface 주입

Spring 에서의 DI

Spring Framework에서 DI는 어떻게 이루어질까?

예시로 @Controller, @Service를 들 수 있다.
Controller, Service는 의존관계를 지니고 있다. Controller에서 Service를 호출할때, Service를 받는 생성자가 어딘가에서 호출되어야 하지만 instance를 주입하는 코드를 쓰지 않아도 가능하다.

의존관계 자동 주입

스프링에서 객체 생성을 자동으로 생성해주는 역할
스프링 빈으로 등록되면 스프링이 자동으로 인스턴스를 생성하며 이때 필요한 의존성도 주입해준다.

Spring의 의존관계를 자동으로 주입하는 방법은 Autowored 를 사용하면 된다.
@Autowired는 스프링 컨테이너가 주입하려 하는 객체의 타입이 일치하는 객체를(등록된 스프링 빈을) 찾아서 자동으로 주입 한다.
Autowired 방법에도 필드, 생성자, setter 주입이 있다.
(이때 생성자 주입은 완전한 생성자일 경우 NullPointerException을 방지할 수 있다.)

profile
PlayData

0개의 댓글