728x90

HttpMessageConverter란?

웹 브라우저 같은 클라이언트에서 보여지는 HTML 컨텐츠가 렌더링(Rendering)되는 방식은 크게 두 가지로 나눈다.

 

1. 웹 애플리케이션 서버에서 동적으로 변하는 데이터를 포함하는 HTML을 만들어서 HTML 자체를 한번에 클라이언트 쪽으로 내려주는 방식이다.


이 방식은 JSP나 타임리프(Thymeleaf) 같은 기술을 사용해서 HTML을 템플릿화 한 다음에 Controller의 핸들러 메서드에서 리턴하는 모델 데이터를 템플릿에 동적으로 채워 넣은 후, 최종적으로 완성된 HTML을 클라이언트 쪽으로 내려주는 방식이다. 이 방식을 바로 서버 사이드 렌더링(Server Side Rendering)이라고 한다.

 

2. 클라이언트 쪽을 담당하는 Apache나 NginX 같은 웹 서버에 HTML을 올려 놓은 후, 자바스크립트의 Ajax 기술을 이용해서 웹 애플리케이션 서버에 데이터를 요청한다. 그리고 응답으로 전달받은 데이터를 웹 서버에 올려둔 HTML에 동적으로 채워 넣은 후, 최종적으로 완성된 HTML을 클라이언트 쪽으로 내려주는 방식이다.

 

이 방식을 바로 클라이언트 사이드 렌더링(Client Side Rendering)이라고 한다.

 

위 두가지 방식 중에서 HttpMessageConverter는 두 번째 방식인 클라이언트 사이드 렌더링과 관련이 있다.

 

즉, 클라이언트 사이드 렌더링을 위해 필요한 데이터를 특정 형식으로 변환해 주는 것이 바로 HttpMessageConverter다.


HttpMessageConverter의 사용 목적

HttpMessageConverter는 크게 두 가지 목적으로 사용된다.

 

1. 웹 서버에서 전송된 Reqeust Body를 DTO 같은 클래스의 객체로 변환해서 웹 애플리케이션 서버 쪽에서 사용할 수 있도록 해주는 것이고, 

 

2. 웹 서버 쪽으로 전달할 응답 데이터를 Response Body로 변환해주는 것이다.


HttpMessageConverter의 동작 과정

Spring MVC 요청/응답 동작 과정

 

위 그림은 클라이언트의 요청을 처리하는 Spring MVC의 기본 동작 과정이다.


이 Spring MVC의 동작 과정에서 HandlerAdapter의 동작 과정을 조금 더 구체적으로 설명하겠다.

 

* 요청 처리 시 HandlerAdapter의 동작 과정

  • HandlerMapping을 통해 적절한 HandlerAdapter를 찾으면 HandlerAdapter Controller로 넘겨줄 파라미터를 결정하기 위해 이 작업을 HandlerMethodArgumentResolver에게 위임한다.
  • HandlerMethodArgumentResolver HttpMessageConverter에게 HTTP Request Body를 특정 타입의 객체로 변환해주기를 요청한다.
  • HttpMessageConverter는 HTTP Request Body를 특정 타입의 객체로 변환한다.
  • HandlerMethodArgumentResolver는 변환된 데이터를 전달 받아서 이 데이터를 다시 HandlerAdapter에게 전달한다.
  • HandlerAdapter HandlerMethodArgumentResolver로부터 전달 받은 데이터를 핸들러 메서드의 파라미터로 포함 시킨 후, 핸들러 메서드를 호출한다.

 

* 응답 처리 시 HandlerAdapter의 동작 과정

  • 핸들러 메서드가 응답으로 전달할 데이터를 리턴한다.
  • HandlerMethodReturnValueHandler는 핸들러 메서드로부터 전달 받은 응답 데이터를 HttpMessageConverter에게 전달한다.
  • HttpMessageConverter HandlerMethodReturnValueHandler로부터 전달 받은 데이터를 HTTP Response Body에 포함되는 형식의 데이터로 변환한다.
  • HandlerMethodReturnValueHandler HttpMessageConverter로부터 전달 받은 데이터를 HandlerAdapter에게 전달한다.

REST API에서의 HttpMessageConverter

Spring MVC에서는 기본적으로 아래의 HttpMessageConverter 구현체가 활성화 되어 있다.

  • ByteArrayHttpMessageConverter
  • StringHttpMessageConverter
  • ResourceHttpMessageConverter
  • SourceHttpMessageConverter
  • FormHttpMessageConverter
  • Jaxb2RootElementHttpMessageConverter
  • MappingJackson2HttpMessageConverter
  • MappingJacksonHttpMessageConverter
  • AtomFeedHttpMessageConverter
  • RssChannelHttpMessageConverter

 

만약 우리가 HTTP Request 또는 Response를 위한 통신 프로토콜로 JSON을 사용하는 REST API Controller를 구현했다고 가정해 보자.

 

특정 Controller의 핸들러 메서드 파라미터에 @RequestBody 애너테이션이 추가되거나 파라미터의 타입이 HttpEntity라면 위에서 나열한 HttpMessageConverter가 순서대로 HTTP Request Body를 체크해서 핸들러 파라미터에 지정한 클래스로 변환이 되는지, HTTP Message의 Content Type을 지원하는지 여부를 확인하게 된다.

 

이 두가지 조건을 모두 만족한다면 아마도 MappingJackson2HttpMessageConverter가 Request Body를 해당 클래스의 객체로 변환할 것이고, 조건에 부합하는 HttpMessageConverter가 존재하지 않는다면 예외가 발생할 것이다.

 

이제 응답 데이터를 JSON 형식으로 전달하는 상황을 생각해 보자.

 

핸들러 메서드에 @ResponseBody 애너테이션을 추가하거나 핸들러 메서드의 리턴 타입이 HttpEntity라면 역시 위에서 나열한 HttpMessageConverter가 순서대로 핸들러 메서드의 리턴 값을 체크해서 해당 클래스 타입을 지원하는지, Accept Header에 명시된 MediaType으로 변환이 되는지 여부를 확인하게 된다.


HttpMessageConverter가 동작하는 시점

HttpMessageConverter가 동작하는 시점은 JSON을 DTO로 deserialization 할 때와 DTO를 JSON으로 serialization 할 때가 다르다. 아래는 HttpMessageConverter의 대략적인 동작 흐름이다.

 

* JSON -> DTO로 deserialization

HandlerMethodArgumentResolverComposite.resolveArgument() 

 RequestResponseBodyMethodProcessor.resolveArgument()

 RequestResponseBodyMethodProcessor.readWithMessageConverters() > converter.read()

 objectReader.readValue()

 

* DTO -> JSON serialization

HandlerMethodReturnValueHandlerComposite.handleReturnValue() 
→ HttpEntityMethodProcessor.handleReturnValue() 
→ AbstractMessageConverterMethodProcessor.writeWithMessageConverters() > genericConverter.write() 
→ AbstractGenericHttpMessageConverter.write() 
→ AbstractJackson2HttpMessageConverter.writeInternal() > objectWriter.writeValue(generator, value)
→ write() and flush() 과정을 거친다.
→ ...
→ ...
 CoyoteAdapter.service() > response.finishResponse() // response가 close되면서 클라이언트 쪽에 출력

728x90
728x90

HTML을 편리하게 생성하는 뷰 기능은 다음과 같다.

1. JSP

• 속도 느림, 기능 부족

 

2. 프리마커(Freemarker), Velocity(벨로시티)

• 속도 문제 해결, 다양한 기능

 

3. 타임리프(Thymeleaf)

• 내추럴 템플릿: HTML의 모양을 유지하면서 뷰 템플릿 적용 가능

• 스프링 MVC와 강력한 기능 통합

• 최선의 선택, 단 성능은 프리마커, 벨로시티가 더 빠름

 

그 중 jsp와 타임리프에 대해 설명하고자 한다.

 

일단 java 기반의 서버 프레임워크를 공부하다보면 jsp 라는 것을 쓰게 된다.

 

jsp는 일반적인 자바 프레임워크 MVC 구조에서 'V' , 즉 뷰 역할을 담당한다.

 

그리고 jsp의 상위버전? 이라 하는 Thymeleaf라는것도 있다. 타임리프는 요즘 스프링에서 밀고있는 스프링 프레임워크의 뷰라고 보면 될것같다. 

 

Thymeleaf 이외에도 Apache Freemarker, Mustache, Groovy Templates 등 여러 템플릿 엔진이 있지만 요즘은 Thymeleaf를 많이 쓰는 것 같다. ( JSP는 옛날 회사에서는 아직도 많이 쓴다)

 

자 아무튼 오늘은 Thymeleaf와  jsp 차이점을 알아보고, 그리고 간단하게 Thymeleaf를 사용하는 방법을 알아보도록하자!!

 

먼저 jsp 의 경우에는 아시다시피 서블릿 이라는 형태로 변환되어 실행이 된다. 서블릿이 자바소스 이다 보니 JSP내에서도 자바코드를 사용할 수 있게된다. (요즘에는 보통 JSP 내부에 비지니스 로직이 포함된 자바코드를 넣는 것은 지양한다)

 

반면 Thymeleaf는 html, xml, js, css 등을 처리할 수 있는 웹 및 독립형 환경에서 사용이 가능한 java 템플릿 엔진이다. Thymeleaf는 html 파일을 가져와서 파싱하고 그걸 분석하여 정해진 위치에 데이터를 뿌려준다.

 

Thymeleaf 의 장점은 코드자체가 앞서 말한것처럼 html 같은 웹형태이기에 was없이도 그냥 브라우저에서 직접 띄어볼 수 가 있다. thymeleaf 가 jsp 처럼 전용 문법을 사용하지 않고 그냥 html 엘리먼트에 속성으로 값을 넣어주기 때문이다.

(브라우저는 html의 모르는 속성으 무시해버리니깐 브라우저에서 그냥 띄어볼수 있는거다)

 

물론 Thymeleaf 가 만능은 아니다.. ( 그나마 3.x 버전대는 굉장히 괜찮아진듯하다.)

JSP 에 비해 속도가 좀 떨어지는 것 같고, 구조적인 부분에서 꽤나 한계가 있는 것을 느꼈다. 

 

그래도 SpringBoot와는 굉장히 궁합이 잘맞는듯하니 스프링부트를 하시는 분들은 한번쯤 써보는 것은 참 좋을듯하다.

 

그럼 이제 실제로 스프링 부트환경에서 구현한번 해보자.

 

일단 스프링부트 프로젝트에서 Thymeleaf를 사용하려면  build.gradle 파일안에

dependencies {
   ...
   implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
   ...
}

Thymeleaf에 대한 의존관계를 설정해줘야한다. 

 

자, 그리고 오늘 간단하게 실습해볼 건

이렇게 Controller 하나랑 html 파일 하나 만들어주면된다.

 

먼저 Controller 부터 보자.

 

아주 간단한 코드다.

 

여기서는 하나만 알고 넘어가자 .model 객체에 속성을 채워서 던져주면 던져주는 뷰 페이지에서 그데이터를 쓸수 있다는 것이다.

 

다음은 html 페이지이다. 여기 보면 

 

Hi!, banker 라는 게 있는데 이건 그냥 브라우저에서 열어보면 나올 문구이다.

 

자 이번에는 서버사이드에서 돌려보자.

 

만들어진 프로젝트를 실행해보면

이번엔 모델로 넘어온 데이터인 Babo가 출력되는걸 볼 수 있따.

 

(참고로 그냥 html은 static 디렉토리에 넣어서 작업해주면된다.)

728x90
728x90

JSP & Servlet을 활용한 WEB 개발에 대해서 전체적으로 학습을 진행하는 와중,  Redirect와 foward 개념에 대해서 정리해보고자 한다. 또한 간단한 코드를 통해서 동작 방식이 어떻게 다른지 역시 알아보고자 한다.

 

1. Forward 방식


[ Forward 방식 ]

Forward 방식을 적절한 비유를 통해서 간단하게나마 이해해보자. 

고객을 클라이언트, 상담원을 서버, URL을 통해서 서버의 자원에 접근한다고 생각하시면 된다.

 

 

  1. 고객이 고객센터로 상담원에게 100번으로 전화를 건다.
  2. 상담원은 해당문의 사항에 대해서 전문적인 지식을 갖춘 상담원에게 문의해 답을 얻는다.
  3. 상담원은 고객에게 문의사항을 처리해준다.

 

Forward는 Web Container 차원에서 페이지의 이동만 존재한다. 실제로 웹 브라우저는 다른 페이지로 이동했음을 알 수 없다. 그렇기 때문에 웹 브라우저에는 최초에 호출한 URL이 표시되고, 이동한 페이지의 URL 정보는 확인할 수 없다. 또한 현재 실행중인 페이지와 forward에 의해 호출될 페이지는 Request 객체와 Response 객체를 공유한다. 

 

위와 같이 Foward는 다음으로 이동 할 URL로 요청정보를 그대로 전달한다. 그렇기 때문에 사용자가 최초로 요청한 요청정보는 다음 URL에서도 유효하다. 예를 들어 게시판을 작성하는 과정이라고 할 때, 사용자가 보낸 요청 정보를 이용하여 글쓰기 기능을 수행한다고 할 때, forward를 사용하여 응답 페이지를 부르면 다음과 같은 문제가 발생하게 된다. 만약 사용자가 실수 혹은 고의로 글쓰기 응답 페이지에서 새로고침을 누른다면, 요청 정보가 그대로 살아있기 때문에 요청이 여러 번 전달되어 동일한 게시물이 여러 번 등록될 수 있다. 그렇기 때문에 게시판을 제작하는 과정에서는 시스템에 변화가 생기지 않는 단순 조회 요청(글 목록 보기, 검색)의 경우 forward로 응답하는 것이 바람직하다.

package controller;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import model.MockDAO;
 
@WebServlet("/ForwardTestServlet")
public class ForwardTestServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //Model과 연동 
           MockDAO dao=new MockDAO();
           dao.register("상품정보");
           //forward 방식으로 이동 
           String path="forward-result.jsp";
           //forward 방식은 기존 request와 response 가 유지된 상태로 이동된다 
           //아래와 같이 request에 정보를 할당할 수 있다 
           request.setAttribute("shareInfo", "검색정보");
           request.getRequestDispatcher(path).forward(request, response);
    }
}

 

 

 

 

2. Redirect 방식


[ Redirect 방식 ]

Redirect를 잘 설명해주는 적절한 비유로 이해를 해보자.

고객을 클라이언트, 상담원을 서버, URL을 통해서 서버의 자원에 접근한다고 생각하시면 된다.

 

  1. 고객이 고객센터로 상담원에게 100번으로 전화를 건다. 
  2. 상담원은 고객에게 다음과 같이 이야기한다. "고객님 해당 문의 사항은 200번으로 다시 문의해주세요"
  3. 고객은 다시 200번으로 문의해 일을 처리한다.

Redirect는 Web Container로 명령이 들어오면, 웹 브라우저에게 다른 페이지로 이동하라고 명령을 내린다. 그러면 웹 브라우저는 URL을 지시된 주소로 바꾸고 해당 주소로 이동한다. 다른 웹 컨테이너에 있는 주소로 이동하며 새로운 페이지에서는 Request와 Response객체가 새롭게 생성된다.

 

Redirect의 경우 최초 요청을 받은 URL1에서 클라이언트에게 redirect할 URL2를 반환하고, 클라이언트에서는 새로운 요청을 생성하여 URL2에 다시 요청을 보낸다. 그러므로 처음 보냈던 최초의 Request와 Response 객체는 유효하지 않고 새롭게 생성되는 것이다. 예를 들어 게시판을 작성하는 과정이라고 할 때, 사용자가 보낸 요청 정보를 이용하여 글쓰기 기능을 수행한다고 할 때, redirect를 사용하여 응답 페이지를 부르면 사용자가 실수 혹은 고의로 글쓰기 응답 페이지에서 새로고침을 누른다고 하더라도, 처음의 요청 정보는 존재하지 않으므로 게시물이 여러 번 등록되지 않는다. 그렇기 때문에시스템에 변화가 생기는 요청(회원가입, 글쓰기 등)의 경우에는 redirection을 사용하는 것이 바랍직하다.

 

package controller;
 
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import model.MockDAO;
 
 
@WebServlet("/RedirectTestServlet")
public class RedirectTestServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;           
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //모델 연동 
        MockDAO dao=new MockDAO();
        dao.register("상품정보");
        //redirect 방식으로 이동 
        //redirect 방식은 응답시에 클라이언트에게 이동할 url 을 지정해서 클라이언트가 view로 요청하게 하는 방식으로
        //기존 request와 response는 유지되지 않는다 
        //아래 코드와 같이 정보를 공유할 수는 없다 
        request.setAttribute("shareInfo", "검색정보");
        response.sendRedirect("redirect-result.jsp");
    }
}

 

3. 정리


 

우선 Redirect의 경우 URL에 변화가 생긴다. 처음에는 /RedirectTestServlet으로 URL 요청을 하였다면 응답으로 받은 경로인 /redirect-result.jsp로 요청을 다시 보낼 것이다. 따라서 새로운 request, response가 생성이 된다.

 

반면에 Forward의 경우 /ForwardTestServlet으로 URL 요청을 하였다면 서버 내부적으로 Controller가 View에게 작업을 넘기고 View가 JSP 파일을 렌더링하여 결과 페이지로써 클라이언트에게 넘긴다. 이는 클라이언트가 알지 못한다. 따라서 URL 요청이 바뀌는것이 없다. 

 

결론!

DB에 변화를 주는 작업 (회원가입, 게시판 글쓰기등)의 경우 Redirect 방식으로 사용하고,

시스템에 변화가 생기지 않는 작업 (단순 조회, 검색)의 경우 forward 방식이 적합하다.

728x90

'Spring' 카테고리의 다른 글

HttpMessageConverter란?  (0) 2023.02.23
[Spring] Thymeleaf 와 jsp 비교  (0) 2023.02.05
[JAVA] JDBC란?  (0) 2023.01.29
Spring과 SpringBoot 의 정의와 사용 이유  (0) 2023.01.29
스프링이란?  (1) 2023.01.05
728x90

JDBC란?

JDBC란 Java DataBase Connectivity 의 약어로 Java와 DB연결을 위한 표준 API이다. 
  • JDBC는 관계 데이터베이스에 접근하는 자바 API이다.
  • 클라이언트가 데이터베이스에 접근하는 방법을 정의한 어플리케이션 프로그래밍 API이다. 
  • 자바언어와 DB를 연결을 위해 사용되는 통로같은 데이터 접근 기술이다.
  • JDBC는 데이터베이스와 커넥션을 만들고, SQL 작업을 위한 인터페이스를 제공하고, 결과를 처리한다.
  • JDBC API는 데이터베이스와 연결하기 위해 JDBC 드라이버를 사용한다.
  • JDBC는 자바 프로그래밍 언어와 다양한 데이터베이스 SQL 또는 데이블 형태의 데이터 사이에 독립적인 연결을 지원하는 표준이다.
  • 즉 다양한 형태의 관계형 데이터베이스에 접속하여 자바 프로그래밍 언어와 데이터베이스 사이에 데이터를 주고받을 수 있도록 지원하는 표준 자바 응용 프로그래밍 인터페이스이다.
  • JDBC API는 자바 프로그래밍 언어로 작성된 인터페이스, 클래스, 및 예외 클래스들의 집합으로 구성되어 있으며, SQL을 이용해 자바 프로그래밍 언어로 데이터베이스 응용 프로그래밍을 작성할 수 있도록 지원한다.
  • 또한 JDBC API는 관계형 데이터베이스 관리 시스템에 SQL문을 쉽게 보낼 수 있도록 지원한다.
  • JDBC API의 가장 큰 장점은 자바 응용 프로그램이 거의 모든 데이터에 접근할 수 있도록 지원하는 것이며, 자바 가상머신이 설치된 모든 종료의 데이터베이스 플랫폼에서 실행될 수 있다는 것이다.
 

필요한 이유

  • db 학습시 SQL이용해서 db에다 직접 값을 넣거나 조회하는 등의 일을 수행했음.
  • 하지만 우리가 웹을 동작,수행시킬 때마다 매번 그럴 수는 없음.
  • 그래서 프로그램이 이 일을 대신할 수 있게 만들어줘야 하는데 이때 사용하는 것이 JDBC이다.

  • JAVA는 표준 인터페이스인 JDBC API를 제공한다. 그래서 사용하기 편하다. 인터페이스가 이미 정의되어 있기 때문에, 어떤 db벤더든 간에 다 똑같은 방법으로 사용하면 된다.
  • DB벤더, 또는 기타 써드파티에서는 JDBC 인터페이스를 구현한 드라이버(driver)를 제공한다. 그래서 사용자들은 이런 드라이버를 이용하면 된다.

 

JDBC를 이용한 프로그래밍 방법

JDBC 클래스의 생성관계

  • 드라이버 로딩시 DriverManager라는 객체가 갖고 있는 메서드를 이용해서 드라이버를 로딩한다. 그래서 DriverManager 객체를 이용해서 Connection 인스턴스를 얻어내고, Connection 인스턴스를 통해서 Statement 객체를 얻어내고, Statement객체를 통해 ResultSet을 얻어낸다. 그래서 닫을때는 열때와 반대순서로 닫아주어야 한다.

 

JDBC API 역할

 
  • - JDBC API는 표준 응용 프로그래밍의 인터페이스만을 제공해주는 것이고, 실질적인 인터페이스의 메소드 기능들에 대한 실제 구현은 DBMS 제조사들이 자신들의 데이터베이스에 맞게 구현하여 제공하며, 이를 JDBC 드라이버라고 한다. - 즉 JDBC 드라이버란 DBMS 회사들이 자신들의 데이터베이스 시스템에 접근할 수 있도록 표준 JDBC 인터페이스에 명시된 메소드들을 구현한 것이다.
  • 따라서 JDBC API를 사용할 경우 하나의 자바 응용 프로그램만으로 JDBC 드라이버를 제공하는 어떤 종류의 관계형 DBMS에도 접근이 가능한 것이며, 사용자들은 특정 회사의 데이터베이스의 정확한 사용 방법을 몰라도 JDBC API만 배우면 데이터베이스 응용 프로그램을 구현할 수 있는 것이다.
  • 조금더 자세하게 설명하면 자바에서 DB를 연결하고, 그 안에 있는 데이터를 가져오기 위해서 사용하는 API이다. 

 

우선 전체적인 구조를 보면

크게 4가지로 나뉜다. 

 

자바와 DB를 연결하기 위해서는 두 단계를 거쳐야한다.

JDBC API는 JDK에 포함되어있으며 DBMS에 상관없이 사용할 수 있는 API를 제공한다. JDK에 이미 포함이 되어있기 때문에 따로 다운로드하거나 설치할 필요는 없다. 

대부분의 api는 java.sql 패키지나 javax.sql 패키지에 있는 api를 사용한다. 

주요 클래스 및 인터페이스로 

  • DriverManger : JDBC 드라이버 로드
  • Connectoin : DB와 연결하기 위한 인터페이스
  • Statement / PreparedStatement / CallableStatement (SQL을 보내기 위한 통로)
    • Statement : SQl을 보내기 위한 통로. 인자가 없음.  
    • PreparedStatement : Statement와 동일한데 차이점은 인자값으로 SQL을 받기 때문에 특정한 SQL에 대한 통로라고 생각하면 된다. 
    • CallableStatement : PL/SQL을 호출할 때 사용
  • ResultSet : SQL문의 결과를 저장하는 객체

등이 있다. 

 

JDBC Driver는 아래 4가지가 있다.

 

  1. JDBC-ODBC Bridge Driver
  2. Native API Driver (partially java driver)
  3. Network Protocol Driver (fully java driver)
  4. Thin Driver (fully java driver)

 

 

<< JDBC를 하기 위한 환경 설정 >>

https://yoon990.tistory.com/58

728x90
728x90

1. 스프링(Spring)이란?

스프링프레임워크(Spring Framework)

① 흔히 스프링이라 부르지만 "스프링 프레임워크(Spring Framework)"라고 하는 것이 정확한 표현이다.

② 자바(JAVA) 엔터프라이즈 개발을 위한 "오픈소스(Open Source)" 애플리케이션 프레임워크(Framework)

- Open Source : 소프트웨어(S/w) 혹은 하드웨어의(H/W) 제작자의 권리를 지키면서 원시 코드를 누구나 열람할 수 있도록 한 소프트웨어, 오픈 소스 라이선스에 준하는 모든 통칭을 일컫는다. (소스가 공개되어 여러 개발자가 플랫폼을 함께 개발, 구축, 보완해 나가는 시스템. )

 - Framework : 개발할 때 설계 기본이 되는 뼈대나 구조 / 환경 (문제 영역을 해결한 재사용, 확장 가능한 라이브러리.)

1.1 스프링의 개념

Spring은 Java를 기반으로 한 웹 어플리케이션 프레임워크다. spring.io 사이트에서 확인하면 '스프링 프레임워크는 현대 자바 기반의 엔터프라이즈 어플리케이션을 위한 프로그래밍 및 Configuration Model 제공한다'라고 언급하고 있다.

스프링은 위와 같은 구조를 가지고 있으며, Python을 이용한 Django, Ruby를 이용한 Ruby on Rails, Javascript를 이용한 Node.js 기반의 웹 서버 개발과 같이 Java 개발자들은 Spring을 사용하여 웹 서비스를 만들 수 있다.

 

1.2 스프링의 특징

경량 컨테이너

  • 제어의 역전(IoC, Invertion of Control)
  • 의존성 주입(Di, Dependency Injection)
  • 관점지향 프로그래밍(AOP, Aspect-Oriented Programming)

스프링은 자바 객체와 라이브러리들을 관리해주며, 톰캣과 같은 웹 어플리케이션 서비스가 내장되어 있어 자바 웹 어플리케이션을 구동할 수 있다. 또한, 스프링은 경량 컨테이너로 자바 객체를 직접 스프링 안에서 관리한다. 객체의 생성 및 소멸과 같은 생명 주기를 관리하며, 스프링 컨테이너에서 필요한 객체를 가져와 사용한다.

 

① "경량 컨테이너"(크기와 부하의 측면)로서 자바 객체를 직접 스프링 안에서 관리

 - 각각의 객체 생성, 소멸과 같은 라이프 사이클을 관리하며 스프링으로부터 필요한 객체를 얻어올 수 있다.

 

 제어의 역전(IoC : Inversion of Control)

 - 애플리케이션의 느슨한 결합을 도모.

 - 컨트롤의 제어권이 사용자가 아니라 프레임워크에 있어 필요에 따라 스프링에서 사용자의 코드를 호출한다.

 - 결론적으로 말하자면, 제어의 역전이란 객체의 제어권을 프레임워크의 컨테이너에게 넘기는 개념을 말한다.
- 일반적으로 자바에서는 개발자가 각 객체를 직접 생성하고 제어해야 했다.

- 하지만 스프링에서는 스프링 컨테이너에 Bean(객체)를 등록하기만 하면, 스프링 컨테이너에서 객체의 생명주기를 컨트롤 해준다.
- 즉, 객체에 대한 제어권이 스프링 컨테이너로 역전되기 때문에 제어의 역전이라고 한다.

 

 의존성 주입(DI : Dependency Injection)

 - 각각의 계층이나 서비스들 간에 의존성이 존재할 경우 프레임워크가 서로 연결시켜준다.

- 의존성 주입이란, 클래스간 의존성을 클래스 외부에서 주입하는 것을 뜻한다.
- 더 자세히 말하자면, 어떤 객체(B)를 사용하는 주체(A)가 객체(B)를 직접 생성하는게 아니라 객체를 외부(Spring)에서 생성해서 사용하려는 주체 객체(A)에 주입시켜주는 방식이다.

- 사용하는 주체(A)가 사용하려는 객체(B)를 직접 생성하는 경우 의존성(변경사항이 있는 경우 서로에게 영향을 많이 준다)이 높아진다. 하지만, 외부(Spring)에서 직접 생성하여 관리하는 경우에는 A와 B의 의존성이 줄어든다.
- 즉, 의존성 주입은 재사용성을 높여주고, 코드를 단순화시켜주며, 결합도를 낮춰준다.

- '의존성이 있다.'라는 것은 '한 클래스(A)에서 다른 클래스(B)를 사용한다'라고 이해하면 된다.
- 의존성이 있다면 B가 변경이 되었을때, A도 변경을 해야하며, 이를 'A가 B에 의존해 있다.'라고 라고 표현한다.

 

 관점지향 프로그래밍(AOP : Aspect-Oriented Programming)

 - 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리할 수 있다.

 - AOP를 공부하려면 Filter, Interceptor, AOP를 비교하면서 공부하면 이해가 더 빠를 것이다.

   http://goddaehee.tistory.com/154

 

[Spring] Filter, Interceptor, AOP 차이 및 정리

[Spring] Filter, Interceptor, AOP 차이 및 정리 안녕하세요. 갓대희 입니다. 이번 포스팅은 [ [Spring] 필터, 인터셉터, AOP 정리 ] 입니다. : ) 공통 프로세스에 대한 고민자바 웹 개발을 하다보면, 공통적으

goddaehee.tistory.com

 

- AOP는 OOP(객체지향 프로그래밍)을 더욱 보완하고 확장한 개념이다. 하나의 소프트웨어가 하나의 거대한 OOP로써 설계, 프로그래밍 되었다면 이것을 각 기능별로 모듈화 해서 분리를 시키는 개념이다.

- OOP를 통해서 객체를 재사용함으로써 개발자들은 반복되는 코드의 양을 많이 줄일 수 있었다.

- 하지만, 객체의 재사용에도 불구하고 필수적으로 반복되는 코드들을 없앨수는 없었다.

- 이를 횡단 관심사라하며 트랜잭션, 로깅, 성능 분석 등이 있다.

- 이것을 각각의 OOP 소스코드에서 제거하고 외부로 빼내 하나의 공통 모듈로 만드는 것이 기존의 OOP에 AOP 관점을 더해 발전시킨 기법이다.

- AOP의 핵심은 공통 모듈을 분리시켜 해당 소스코드가 외부의 다른 클래스에서 존재하는 것이다.
- 즉, '관심의 분리(Separation of Concerns)' 이며, AOP를 통해서 중복 코드 제거, 효율적인 유지보수, 높은 생산성, 재활용성 극대화, 변화 수용 용이 등의 이점을 얻을 수 있다.

 

④ 애플리케이션 객체의 생명 주기와 설정을 포함하고 관리한다는 점에서 일종의 "컨테이너"(Container)라고 할 수 있다.

 - iBatis, myBatis나 Hibernate 등 완성도가 높은 데이터베이스처리 라이브러리와 연결할 수 있는 인터페이스를 제공한다.

 

 트랜잭션 관리 프레임워크

 - 추상화된 트랜잭션 관리를 지원하며 설정파일(xml, java, property 등)을 이용한 선언적인 방식 및 프로그래밍을 통한 방식을 모두 지원한다.

 

 모델-뷰-컨트롤러 패턴

 - 웹 프로그램밍 개발 시 거의 표준적인 방식인 "Spring MVC"라 불리는 모델-뷰-컨트롤러(MVC) 패턴을 사용한다. 

 -  DispatcherServlet이 Controller 역할을 담당하여 각종 요청을 적절한 서비스에 분산시켜주며 이를 각 서비스들이 처리를 하여 결과를 생성하고 그 결과는 다양한 형식의 View 서비스들로 화면에 표시될 수 있다.

 

⑦ 배치 프레임워크

 - 스프링은 특정 시간대에 실행하거나 대용량의 자료를 처리하는데 쓰이는 일괄 처리(Batch Processing)을 지원하는 배치 프레임워크를 제공한다. 기본적으로 스프링 배치는 Quartz 기반으로 동작한다.

 

 즉 공통 부분의 소스 코딩이 용이하며 확장성도 매우 높다.

 

1.3 스프링 모듈

① Spring Core

 - Spring 프레임워크의 근간이 되는요소. IoC(또는 DI) 기능을 지원하는 영역을 담당.

 - BeanFactory를 기반으로 Bean 클래스들을 제어할 수 있는 기능을 지원

 

②Spring Context

 - Spring Core 바로 위에 있으면서 Spring Core에서 지원하는 기능외에 추가적인 기능들과 좀 더 쉬운 개발이 가능하도록 지원

 - 또한 JNDI, EJB등을 위한 Adaptor들을 포함

 

③Spring DAO

 - 지금까지 우리들이 일반적으로 많이 사용해왔던 JDBC 기반하의 DAO개발을 좀 더 쉽고, 일관된 방법으로 개발하는 것이 가능하도록 지원

 - Spring DAO를 이용할 경우 지금까지 개발하던 DAO보다 적은 코드와 쉬운 방법으로 DAO를 개발하는 것이 가능

 

④Spring ORM

 - Object Relation Mapping 프레임워크인 Hibernate, IBatis, JDO와의 결합을 지원하기 위한 기능 

 - Spring ORM을 이용할 경우 Hibernate, IBatis, JDO 프레임워크와 쉽게 통합하는 것이 가능

 

⑤Spring AOP

 - Spring 프레임워크에 Aspect Oriented Programming을 지원하는 기능이다. 이 기능은 AOP Alliance 기반하에서 개발

 

⑥Spring Web

 - Web Application 개발에 필요한 Web Application Context와 Multipart Request등의 기능을 지원

 - 또한 Struts, Webwork와 같은 프레임워크의 통합을 지원하는 부분을 담당

 

⑦Spring Web MVC

 - Spring 프레임워크에서 독립적으로 Web UI Layer에 Model-View-Controller를 지원하기 위한 기능

지금까지 Struts, Webwork가 담당했던 기능들을 Spring Web MVC를 이용하여 대체하는 것이 가능하다. 또한 Velocity, Excel, PDF와 같은 다양한 UI 기술들을 사용하기 위한 API를 제공

 

2. 스프링 부트(Spring Boot)란?

2.1 스프링 부트의 개념

Spring Boot는 Java를 기반으로 한 웹 어플리케이션 프레임워크다. Spring Boot가 등장하기 전 Spring 프레임워크가 먼저 등장했는데 Spring의 초기 환경 설정시 시간이 많이 할애되는 문제를 해결하고자 등장한 프레임워크가 Spring Boot이다.

- 스프링 부트는 스프링 프레임워크를 사용하기 위한 설정의 많은 부분을 자동화하여 사용자가 편하게 스프링을 활용할 수 있도록 돕는다.

- 스프링 부트 starter dependency만 추가해주면 바로 API를 정의하고, 내장된 톰캣이나 제티로 웹 어플리케이션 서버를 실행할 수 있다.

 - 스프링 프레임워크를 사용하는 프로젝트를 아주 간편하게 설정할 수 있는 스프링 프레임웍의 서브 프로젝트라고 할 수 있다.

- Python을 이용한 Django, Ruby를 이용한 Ruby on Rails, Javascript를 이용한 Node.js 기반의 웹 서버 개발과 같이 Java 개발자들은 Spring을 사용하여 웹 서비스를 만들 수 있다.

 

2.2 Spring과 비교한 Spring Boot의 장점

내부에 톰캣이 포함되어 있어 톰캣 설치 및 버전 관리를 하지 않아도 된다.

  • starter를 통한 dependency 자동화
  • XML 설정을 하지 않아도 된다.
  • jar file을 이용해 java 옵션만으로 손쉽게 배포할 수 있다.

여기서 Spring Boot starter란, 목적을 달성하기 위한 의존성 그룹이라 생각하면 이해하기 쉽다. starter는 마치 npm처럼 간편하게 dependency를 제공해주는데, 만약 우리가 JPA가 필요하다면 메이븐이나 그래들에 'spring-boot-starter-data-jpa'만 추가해주면 spring boot가 그에 필요한 라이브러리들을 알아서 받아온다.

스프링 부트는 스프링의 많은 부분을 자동화하였고, 많은 개발자들이 현재 스프링 부트를 이용해 개발을 진행하고 있다.

 

▶ 스프링 부트를 왜 사용해야 하나? 장점?

 스프링 프레임 워크와 비교하여 여러 가지 장점이 있다.

 

 - 스프링 프레임 워크를 사용 하면 많은 XML 설정파일등을 작성 하는 등 설정하는 방법이 어려운 편이기 때문에 보통 검색을 통해 설정 내용을 복사 하거나, 기존 설정파일들을 복붙하기 일수였다.

- 하지만 스프링 부트는 반복되는 개발환경 구축을 위한 코드작성등의 노력을 줄여주고 쉽고 빠르게 프로젝트를 설정할 수 있도록 도와준다.

 - 매우 빠르게 모든 스프링 개발에 관한 경험에 광범위한 접근을 제공한다.

 - 프로젝트 환경 구축에서 큰 영역을 차지하는 비기능적인 기능들을 기본적으로 제공한다.

   (내장형 서버, 시큐리티, 측정, 상태 점검, 외부 설정)

 

등등 다양한 장점을 갖고 있지만, 무엇보다 스프링 부트를 직접 사용해보고 체감해보는 것이 빠를 것 같다!

 

>> 스프링 부트 프로젝트를 시작하면서 배워보는 것이 나을 것같고 이는 

https://goddaehee.tistory.com/238

 

[스프링부트 (1)] 스프링부트 시작하기 (SpringBoot 프로젝트 설정 방법)

[스프링부트 (1)] 스프링부트 시작하기 (SpringBoot 프로젝트 설정 방법) 안녕하세요. 갓대희 입니다. 이번 포스팅은 [ 스프링 부트 기초. 스프링 부트란? 그리고 스프링 부트 프로젝트 생성 방법 ] 입

goddaehee.tistory.com

위 블로그를 참고하여 시작해보자!

 

728x90

'Spring' 카테고리의 다른 글

[Spring] Thymeleaf 와 jsp 비교  (0) 2023.02.05
[Servlet & JSP] Redirect vs forward 방식 비교  (0) 2023.02.03
[JAVA] JDBC란?  (0) 2023.01.29
스프링이란?  (1) 2023.01.05
좋은 객체 지향 설계의 5가지 원칙(SOLID)  (0) 2023.01.04
728x90

개인적으로 어려웠던 스프링의 원리과 사용기술을 학습하기 위하여 작성한 글입니다~! 김영한 강사님 최고..!!

🔥 개요
- 스프링이란?
스프링 프레임워크는 자바 진영의 웹 프레임워크이다. EJB라는 겨울을 넘어 새로운 시작이라는 뜻으로 시작된 스프링은 현재는 다양한 생태계를 구축하고 있다.
- 개발자로 활동하며 스프링을 사용하는 입장에서 스프링이 제공하고 있는 다양한 기능을 당연하게 사용해왔지만, 정작 스프링을 왜 사용하는지? 사용되는 기술이 무엇인지? 핵심원리를 파악하지 못하고 스프링을 사용해왔다.
- 그래서 스프링 프레임워크는 왜 만들어졌는지, 핵심개념은 무엇인지 알아보고 그 내용을 정리하기 위하여 이 글을 작성한다.

=> 스프링은 자바 언어 기반의 프레임워크이고, 자바는 객체 지향 언어이다.

그렇다면 좋은 객체 지향 프로그래밍이란 무엇일까?

  • 객체 지향 프로그래밍(OOP)

- 객체 지향 프로그래밍(Object Oriented
Programming)은 컴퓨터 프로그래밍의 패러다임 중 하나이다.
- OOP 는 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러개의 독립된 단위인 객체들의 모임으로 파악하고자 하는 것이다.
- 각각의 객체는 메시지를 주고받고 데이터를 처리할 수 있다.
- 객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용된다.

유연하고 변경이 용이하다?

- 그렇다면, 유연하고 변경이 용이하다는 표현은 어떤 뜻일까? 내가 좋아하는 레고는 매우 유연하고 변경이 용이하다. 블럭(객체)을 조립하여 하나의 레고 완성품을 만드는 것처럼, 프로그래밍에서는 컴포넌트를 유연하게 변경하면서 개발하는 것을 의미한다고 생각한다.

핵심개념은 무엇일까?

- 객체 지향 프로그래밍은 추상화, 상속, 다형성 등이 있으며 추가적으로 다중 상속 등의 특징이 존재한다.
- 그 중 OOP 의 핵심 개념인 다형성(Polymorphism) 에 대하여 알아보겠다.
- 유연하고 변경이 용이한 좋은 객체 지향 프로그래밍을 하기 위해서는 다형성이 매우 중요하다. 왜 다형성이 중요할까?

역할과 구현

다형성을 쉽게 이해하기 위해 실세계에 비유하여 생각해보자.

- 자동차에 비유하여 생각해보자. 자동차의 종류는 매우 다양하다. 하지만 운전자는 자동차 사용방법에 대하여 알고 있다면 자동차를 운행하는데 아무런 지장이 없다.
- 자동차(역할)를 생산(구현)한 것이라 생각하면 편하다. 생산(구현)된 자동차는 매우 다양하지만, 그것이 자동차(역할)라는 것은 변함이 없다.
역할과 구현을 분리하면 세상이 단순해지고, 유연해지며 변경이 용이해진다.
- 따라서 우리(클라이언트)는 역할(인터페이스)만 알고있으면 구현의 구체적인 내용은 몰라도 상관없다. 역할만 알고있다면 우리는 구현내용이 변경되더라도 클라이언트에게 영향을 미치지 않는다. 마치 자동차의 엔진, 변속기, 제어 등등의 구체적인 자동차 내부구조 내용을 모르더라도 클라이언트는 인터페이스만 알고있다면 자동차를 운전하는데 큰 문제는 없을 것이다.

역할 - 인터페이스
구현 - 구현클래스

객체를 설계할 때 역할과 구현을 분리하는 것이 매우 중요하다. 수 많은 객체 클라이언트와 객체 서버는 서로 협력관계를 가진다.
클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.

728x90
728x90

SOLID 클린코드로 유명한 로버트 마틴이 좋은 객체 지향 설계의 5가지 원칙을 정리

 

• SRP: 단일 책임 원칙(single responsibility principle)

• OCP: 개방-폐쇄 원칙 (Open/closed principle)

• LSP: 리스코프 치환 원칙 (Liskov substitution principle)

• ISP: 인터페이스 분리 원칙 (Interface segregation principle)

• DIP: 의존관계 역전 원칙 (Dependency inversion principle)

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

1. SRP 단일 책임 원칙

• 한 클래스는 하나의 책임만 가져야 한다.

• 하나의 책임이라는 것은 모호하다.

• 클 수 있고, 작을 수 있다.

• 문맥과 상황에 따라 다르다.

• 중요한 기준은 변경이다. 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것

• 예) UI 변경, 객체의 생성과 사용을 분리

 

=> 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것. SRP원리를 적용하면 책임 영역이 확실해지기 때문에 한 책임의 변경에서 다른 책임의 변경으로의 연쇄작용에서 자유로울 수 있습니다.

 

2. OCP 개방-폐쇄 원칙 Open/closed principle

• 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다

• 이런 거짓말 같은 말이? 확장을 하려면, 당연히 기존 코드를 변경?

• 다형성을 활용해보자

• 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현

• 지금까지 배운 역할과 구현의 분리를 생각해보자

 

OCP 개방-폐쇄 원칙 문제점

• MemberService 클라이언트가 구현 클래스를 직접 선택

• MemberRepository m = new MemoryMemberRepository(); //기존 코드

• MemberRepository m = new JdbcMemberRepository(); //변경 코드

• 구현 객체를 변경하려면 클라이언트 코드를 변경해야 한다.

• 분명 다형성을 사용했지만 OCP 원칙을 지킬 수 없다.

• 이 문제를 어떻게 해결해야 하나?

• 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다.

 

=> 새로운 변경사항이 발생했을 때 객체를 직접 수정하지 않고도 변경사항을 적용할 수 있도록 설계해야함을 말합니다. DI, IoC가 필요합니다.

 

3. LSP 리스코프 치환 원칙 Liskov substitution principle

• 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다

• 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것, 다형성을 지원하기 위 한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요하다.

• 단순히 컴파일에 성공하는 것을 넘어서는 이야기

• 예) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능, 뒤로 가게 구현하면 LSP 위반, 느리 더라도 앞으로 가야함

 

=> 클라이언트는 인터페이스 구현객체의 내부를 모르기 때문에 믿고 쓰기 위해선 인터페이스를 구현한 객체가 인터페이스의 사용 의도에 맞게 구현해야 된다는 것을 의미합니다.

 

4. ISP 인터페이스 분리 원칙 Interface segregation principle

• 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다

• 자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스로 분리

• 사용자 클라이언트 -> 운전자 클라이언트, 정비사 클라이언트로 분리

• 분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에 영향을 주지 않음

• 인터페이스가 명확해지고, 대체 가능성이 높아진다.

 

=> 특정 클래스에서 다 쓰지 않는 다양한 추상메서드가 들어간 커다란 인터페이스 보 다는 인터페이스를 특정 클라이언트에 맞게 구체적이게 쪼개는 것을 의미합니다.

 

5. DIP 의존관계 역전 원칙 Dependency inversion principle

• 프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.” 의존성 주입은 이 원칙 을 따르는 방법 중 하나다.

• 쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻

• 앞에서 이야기한 역할(Role)에 의존하게 해야 한다는 것과 같다. 객체 세상도 클라이언트 가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있다! 구현체에 의존하게 되면 변 경이 아주 어려워진다.

 

DIP 의존관계 역전 원칙 Dependency inversion principle

• 그런데 OCP에서 설명한 MemberService는 인터페이스에 의존하지만, 구현 클래스도 동시에 의존한다.

• MemberService 클라이언트가 구현 클래스를 직접 선택

• MemberRepository m = new MemoryMemberRepository();

• DIP 위반

 

=> 클라이언트가 구현객체에 의존하는 것이 아닌 클라이언트와 구현객체 사이에 인터페이스를 두고 클라이언트와 구현객체가 인터페이스에 의존하여 구현객체를 변경해도 클라이언트에 변경이 없음을 의미합니다.

 

정리

• 객체 지향의 핵심은 다형성

• 다형성 만으로는 쉽게 부품을 갈아 끼우듯이 개발할 수 없다.

• 다형성 만으로는 구현 객체를 변경할 때 클라이언트 코드도 함께 변경된다.

• 다형성 만으로는 OCP, DIP를 지킬 수 없다.

• 뭔가 더 필요하다

 

 

 

출처 : 인프런 김영한 

728x90

'Spring' 카테고리의 다른 글

[Spring] Thymeleaf 와 jsp 비교  (0) 2023.02.05
[Servlet & JSP] Redirect vs forward 방식 비교  (0) 2023.02.03
[JAVA] JDBC란?  (0) 2023.01.29
Spring과 SpringBoot 의 정의와 사용 이유  (0) 2023.01.29
스프링이란?  (1) 2023.01.05

+ Recent posts