[Spring] 스프링 개념 정리

merci·2023년 1월 23일
1

Spring

목록 보기
8/21
post-thumbnail

관련된 개념들을 조금씩 정리했다.

코드 작성 팁

  • 반복되는 코드는 클래스로 분리해라 -> 한번만 수정하면되니까 유지보수가 편하다

  • 코드가 중복되지 않도록 노력해야 한다

  • 요청을 처리하는 클래스를 분리한다 -> 서비스 클래스

  • 특정 기능을 가져 여러 클래스가 접근하는 코드도 클래스로 분리한다 -> DAO ( Data Access Object )

  • 하위폴더를 적극적으로 사용하는것이 개발과정과 유지보수에 이롭다



Http 의 get / post 특징

get - 검색, 링크 // 데이터가 uri에 있다 ( 노출됨 )

  • get은 QueryString 을 이용해서 데이터 전송 ( posts?keyword=keywordname )

  • 쿼리스트링은 보통 테이블의 조건으로 사용 ( endpoint 는 테이블이름으로 사용됨 )

post - submit, 로그인, 회원가입 // 데이터가 바디에 있다

  • post 방식을 이용하더라도 데이터를 알수 있기 때문에 암호화를 통해 데이터를 전송해야 한다.
  • 클라이언트가 할수있는 4가지 요청 - SELECT(GET) , INSERT(POST) , UPDATE(PUT) , DELETE(DELETE) ( http1.1 버전 )

  • 폼은 getpost 방식만 가능 ( 자바스크립트는 put, delete도 가능 )
    html은 post를 이용해서 다른 요청 처리
    ( 예를들어 user/update, user/insert, user/delete를 이용해 작업 처리 )
    ( Rest 공부하기 전에 이렇게 했었음 )

스프링의 기본파싱전략 ( MYME TYME ) -> x-www-form-urlencoded ( key = value 형태 )
폼 태그로 보내는 데이터를 디폴트로 key = value 로 받는다

  • MIME TYPE 이란? - 바디에 넣을 데이터를 설명 -> 브라우저에게 알려줌

  • get 데이터에는 바디가 없다 -> MIME TYPE도 없음 -> 서버에서 기본파싱으로 읽음

  • JSP 의 contentType 은 JSP 의 MIME TYPE을 설정 ( 디폴트 - text/html )

  • 네트워크에서 주고 받는 데이터는 페이로드( body )에 헤더가 합쳐진것




웹 서버 / 웹 어플리케이션 서버

  • URL 요청은 웹서버 ( 아파치 ) 에서 처리 -> 정적리소스 - html
    ( 리소스폴더는 클래스패스로 지정되어 있음, 웹서버가 접근 가능 )

  • URI 요청은 웹어플리케이션 서버 ( 톰캣 ) 에서 처리

  • 톰캣은 서블릿을 생성하여 요청을 처리
    ( jsp페이지 -> .java -> .class( 서블릿 ) )

  • 서버가 초기에 요청을 받으면 스레드 생성 - 요청 처리
    -> 스레드 초기화에 시간이 소모되므로 서버 실행시 스레드풀을 생성해야함

웹 어플리케이션의 영역

  • PAGE 영역 - 하나의 JSP 페이지 범위
  • REQUEST 영역 - 한번의 요청 - 요청을 처리하는 모든 JSP 페이지를 포함
    요청마다 request객체/ response객체 생성
  • SESSION 영역 - 하나의 클라이언트와 관련된 모든 요청을 포함
  • APPLICATION 영역 - webapp 폴더 범위, 위 3가지 영역을 모두 포함
  • 웹 어플리케이션의 모든 jsp 가 application 기본 객체를 공유

MVC 패턴에서는 REQUEST / SESSION 기본 객체를 많이 사용한다.




쿠키 / 세션

쿠키

  • 브라우저가 도메인 요청을 통해 서버에 연결되면 서버에서는 세션을 생성하고 세션의 ID( Key )를 응답헤더 ( Set-Cookie )에 담아 브라우저에게 보내게 되는데 이때 보내는 Key가 JSSESSIONID 가 된다.

  • 쿠키는 브라우저의 요청헤더에 담겨서 서버로 가는데 서버에서는 세션저장소의 세션 ID와 쿠키의 세션 ID를 비교 - 같으면 동일한 연결이라 판단한다.

  • 쿠키는 도메인( 오리진 )별로 관리된다 - 접속한 도메인에서만 쿠키를 받고 보낸다.

  • 기본적으로 방문에 대한 기록을 남기는 쿠키도 있겠지만 로그인상태에 관한 쿠키도 존재한다.

  • 쿠키를 사용할때는 Null인지 확인부터 - NullPointer익셉션이 발생한다.
    ( 쿠키의 수명은 setMaxAge()로 설정 )

  • 메모리 쿠키라면 브라우저 종료시 서버에 저장된 세션 id는 소멸

  • 브라우저는 쿠키를 자동저장하게 만들어져 있다. 앱개발자는 쿠키를 저장하는 기능을 만들어야 한다.

세션

  • 세션은 클라이언트의 상태를 저장해서 상태를 저장하지 않는 stateless한 http를 stateful로 만들어주는 기술이다.

  • 서버는 응답헤더의 쿠키헤더( Set-cookie )에 쿠키를 넣어서 리턴
    -> JSESSIONID 의 값으로 세션의 ID ( key ) 를 브라우저와 공유

  • 세션저장소에 세션은 ( key:value - HashMap 구조 )로 저장됨

  • 세션저장소에 유저 오브젝트를 저장( value )하고 요청헤더의 쿠키( JSESSIONID )와 비교해서 로그인상태 확인 - 인증

  • 로그인세션은 로그아웃시 삭제됨 ( invalidate() )
    로그인과 상관없이 브라우저 세션도 저장함 ( 단순 방문 )

  • 세션의 값은 오직 서버에만 존재하기 때문에 보안에 좋다
    모든 유저의 세션을 저장하면 서버부하가 커진다 -> 토큰으로 보완




스프링을 알아보기 전에 JSP 모델과 MVC 패턴을 먼저 알아보자

JSP 모델1 / 모델2

모델 1

  • JSP 모델1 구조는 브라우저의 요청을 JSP가 처리 ( 비즈니스로직 + 출력코드가 한곳에 있음, 모델+뷰+컨트롤러 )
    기능분리가 안되어 유지보수가 힘들다 ( 간단한 처리에 이용 )

모델 2

  • 모델2 구조는 모든 요청을 서블릿이 처리 후 -> jsp페이지로 포워딩
  • 로직처리가 필요하다면 로직클래스에서 처리된 데이터를 빈객체에 담아서 jsp로 포워딩
  • 모델2의 특징 - 모든 요청을 하나의 단일 진입점 ( 서블릿 ) 에서 처리 -> 요청을 구분하는 방법이 필요


MVC 패턴

  • MVC 패턴은 JSP 의 모델2 구조와 완벽하게 매핑된다
MVC 패턴JSP 모델2 구조
컨트롤러서블릿
모델로직 처리 클래스, 자바빈
JSP


컨트롤러

  • MVC 패턴은 모든 요청을 컨트롤러( 서블릿 )로 보낸다
    ( 전체 웹 어플리케이션에서 일괄적으로 적용되는 기능은 컨트롤러에서 처리 )

  • 컨트롤러는 입력을 분석, 처리 ( 모델 사용 - 모델의 메소드 호출 ) 하고 흐름을 제어한다

  • 요청을 서비스클래스에 전달하고 결과를 뷰에 전달한다
    모델에서 반환된 데이터를 객체에 저장 - 뷰로 포워딩

  • 서블릿은 모델이 어떻게 로직을 처리하는지 알 필요가 없다. 자기 역할만 하면 된다.

  • 컨트롤러가 뷰를 부르는것은 호출이 아닌 통신 - 객체에 데이터 넣고 전달하기 때문에

  • 사용자에게 보여줄 화면을 만든다 ( jsp 페이지 )

  • 뷰는 화면을 출력하기도 하지만 다시 컨트롤러로 요청을 보내기도 한다. ( form태그 )

  • 새로운 사용자가 생성되면 ( 예를들어 모바일 접속 ) 뷰만 추가하면 된다

모델

  • 모델은 서비스 클래스나 DAO 클래스를 이용해서 비즈니스 로직을 수행

  • 모델은 외부 DB나 서버와 통신을 한다 - 모델의 책임 = 데이터 접근

MVC 패턴의 핵심은 기능 분리 -> 서로 독립적이라 영향을 주지 않는다 -> 유지보수와 확장을 쉽게 한다




컨텍스트, 서블릿

컨텍스트

  • 컨텍스트( Context ) - 어떤 객체를 핸들링하기 위한 접근 수단
    예를들어 IoC 컨테이너 -> ApplicationConText 라고 표현함
    컨텍스트를 가지고 있다는 것은 대상에 대한 모든것을 안다는것이다.

  • 웹 컨텍스트 = 웹 어플리케이션 = 서블릿 컨텍스트 ( 웹어플리케이션 단위로 생성 )
    웹 어플리케이션은 정적인컨텐츠와 동적인컨텐츠들의 집합

  • 서버 실행하면 웹 컨텍스트( 웹 애플리케이션 )마다 한 개의 서블릿 컨텍스트 객체를 생성
    애플리케이션 전체의 공통 자원이나 정보를 미리 바인딩해서 서블릿들이 공유하여 사용

  • 프로젝트명을 contextPath 라고 한다. ( getContextPath() 로 프로젝트 경로 얻음 )

서블릿

  • 서블릿은 웹페이지를 동적으로 생성하는 서버( 톰캣 ) 측 프로그램이다.
    서블릿은 컨트롤러를 사용한다.

  • 서블릿은 단순히 자바에서 동적 페이지를 편하게 만들기위한 소프트웨어 컴포넌트다.

  • 서블릿을 사용하여 개발자가 비즈니스 로직에 집중하게 만든다.

  • @Controller 같은 어노테이션을 붙여서 클래스로 서블릿의 역할을 할 수 있다.

  • 이러한 흐름을 컨테이너( 톰캣 )가 제어 -> IoC ( 제어의 역전 )




스프링의 처리 흐름

클라이언트의 요청 -> 필터
-> 디스패처 서블릿 ( 위임 ) -> 핸들러매핑 -> 핸들러어댑터
-> 컨트롤러( 페이지컨트롤러 ) -> 서비스 호출( 로직을 처리 ) -> 리포지토리 ( DB 접근 ) -> 데이터를 모델에 저장
-> 컨트롤러 -> 뷰 리턴( jsp )
-> 디스패처 서블릿에서 뷰리졸버 -> 컴포넌트( jsp )
-> 클라이언트에게 응답

  • 디스패처 서블릿이 어떤 컨트롤러에게 요청을 위임할지 결정, 컨트롤러가 리턴한 결과를 뷰에 전달
    디스패처 서블릿은 공통적인 작업을 처리 ( 처리 후 위임 )
  • 디스패처 서블릿은 FrontController 패턴( 단일진입점 )과 RequestDispatcher( 포워딩 )를 합친것

  • 핸들러 매핑 - 요청URI 를( get/post/put/delete )을 컨트롤러( 핸들러 )에 매핑해준다

  • 커맨드핸들러(인터페이스) 를 구현한 핸들러에서 로직을 통해 뷰를 리턴

  • 핸들러( 컨트롤러 ) -> 서비스클래스 - 비즈니스 로직 처리를 위임 ( 서비스의 메소드 호출 )

  • DB 연결이 필요하다면 컨트롤러 -> 서비스 클래스를 거쳐 DB 에 접근하는 리포지토리 - DAO 를 통해 결과를 받아온다 ( JPA같은 라이브러리가 가 DAO를 구현해준다 )

  • 서비스 클래스( 로직 처리 )는 MVC 패턴의 모델로 볼 수 있다

  • 로직은 서블릿 안에서 인스턴스 생성하여 처리 ( 다형성을 이용한 구현체 )

  • 컨트롤러가 jsp를 리턴하면 디스패처서블릿이 뷰리졸버를 호출 -> 처리 결과를 보여줄 뷰를 결정

  • 컨트롤러가 오브젝트를 리턴( @ResponseBody )하면 메세지컨버터 호출

  • 디스패처 서블릿이 요청에 맞는 컨트롤러를 찾고 컨트롤러가 없을 경우에만 정적인 자원을 탐색하게 하는 방식이 유용



스프링 실행 시 인스턴스 생성 순서

web.xml 실행
-> ContextLoaderListener 실행
-> root-ApplicationContext 실행
-> @Service, @Repository 등을 스캔 -> DB 관련 객체를 생성
-> 디스패처 서블릿에 의해서 -> servlet-ApplicationContext 실행
-> 뷰리졸버, 핸들러매핑 등의 객체 생성
-> 웹과 관련된 @Controller, @RestController등을 스캔함
// root-ApplicationContext 에 의해서 로드된 객체들은 이후에 생성된 객체들에 접근할 수 없다
생성된 시점이 다르기 때문에 접근못함 !

  • ContextLoaderListenerroot-ApplicationContext 실행시켜서
    모든객체가 접근할수 있는 객체 생성( DB 관련 객체, 스레드마다 공통적으로 접근 )

  • 위임을 받기 위해서는 먼저 메모리에 떠있어야 한다

  • 디스패처 서블릿이 의존할 컨트롤러는 서버 실행시 디스패처 서블릿이 생성될때 같이 IoC 에 떠야함

  • 디스패처 서블릿의 역할은 컴포넌트 스캔 -> ApplicationContext( IoC ) 에 등록

  • ApplicationContext 는 두종류 root-ApplicationContext // servlet-ApplicationContext
    servlet-ApplicationContextViewResolver, Interceptor, MultipartResolver등의 객체 생성
    ( 웹과 관련된 어노테이션 스캔 )

  • @Bean 은 eager loading / @Lazy 를 붙이면 lazy loading - 필요할때 메모리( IoC )에 로딩




스프링부트의 기본 개념

  • 스프링부트로 REST API 구현 + 프론트엔드 분리

  • 스프링부트는 서블릿 엔진( 서블릿 컨테이너 = 톰캣 )을 사용하여 동적 웹 서버 구현을 쉽게 만들어준다

  • 톰캣( 서블릿 기반 서버 )이 이해하는 클래스는 HttpServlet 을 상속한 클래스
    톰캣을 이용하려면 javax.servlet.http.HttpServlet 을 상속받는 서브클래스를 작성해야함

  • 아래 처럼 HttpServlet 을 상속한 디스페처 서블릿을 만들 수 있다
    ( 스프링이 request객체에서 자동 파싱 )

@WebServlet("/")  
// 서블릿클래스를 주소와 매핑시킨다
// HttpServlet 상속 -> 웹에서 사용될 서블릿클래스 생성
public class MyServlet extends HttpServlet 
    @Override
    protected void doGet.......    
    @Override
    protected void doPost.......
  • 스프링 부트는 DispatcherServlet 을 이미 구현하고 있음 ( HttpServlet 을 상속 )

  • 스프링에서 구현한다면 아래의 web.xml 을 통해서 DispatcherServlet을 구현하게 된다.

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/dispatcher-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

스프링 부트에서는 @SpringBootApplication 을 찾아서 애플리케이션이 실행될때 자동으로 디스패처 서블릿을 등록하게 된다.

  • Gradle 은 빌드자동화 툴 - 컴파일, 라이브러리 다운, 패키징, 테스팅 - JVM에서 실행되는 언어의 빌드 자동화

  • 스프링의 spring-boot-starter-web 라이브러리가 저장시 자동으로 컴파일 -> 서블릿 생성

  • 어노테이션과 인터페이스를 이용해 스프링이 비즈니스 로직을 이해하도록 구현하면 된다.

application.yml

  • 스프링부트에서 사용하는 설정파일 ( .xml 파일을 대체함 )

    • web.xml - 서블릿 매핑정보 ( key-value 구조로 저장 )
    • server.xml - 설계도 / 서버( 톰캣 ) 실행시 필요한 정보를 정의
      포트 정보, DB 접속정보, 웹 리소스경로 등..
    • context.xml - 웹어플리케이션 설정, 웹컨텍스트가 참조
      서버 실행시 메모리에 띄어놔야 할 여러가지 경로들을 여기에 설정
      데이터베이스/ 정적 어플리케이션/ 동적 어플리케이션 / 여러 서블릿





스프링에서 정말 중요한 개념


IoC 컨테이너 ( 스프링 컨테이너 ), DI ( 의존성 주입 )

⭐⭐⭐ 스프링 프레임워크의 핵심은 DI ( 의존성 주입 ) ⭐⭐⭐

  • DI ( 의존성주입 ) -> IoC컨테이너에 존재하는 인스턴스를 클래스가 의존함.

  • 스프링은 IoC 컨테이너의 오브젝트가 필요로 할때 의존하는 오브젝트를 주입해준다 ( @Autuwired - DI )

  • DI -> 디자인 패턴, IoC를 구현하는 방법중 하나
    DI 는 유닛테스트에 좋다 ( Mock ( 테스트에 사용하는 임시 객체 ) 오브젝트 주입에 유용 )

IoC ( 제어의 역전 )

  • IoC - 기존 객체들은 개발자가 관리했지만 스프링에서는 컨테이너가 객체의 생성과, 생명주기를 관리한다 ( 제어의 역전 )
    객체 관리의 주체는 프레임워크가 된다.

  • IoC 컨테이너 ( 자바 오브젝트 )에 인스턴스( 자바빈 )를 생성 -> 개발자는 마음대로 생성하지 못하고 IoC컨테이너의 인스턴스를 사용 -> 제어의 역전( IoC )

  • IoC 컨테이너에 생성된 인스턴스는 하나만 존재 -> 싱글톤 ( <-> 프로토타입 - 매번 다른 객체 사용 )
    세션객체도 브라우저마다 1개가 존재 -> IoC 컨테이너에 존재

  • IoC로 싱글톤을 사용하는 이유 - 프로젝트 규모가 커지면 오브젝트 생성시간이 길어진다

  • @Componet - 클래스를 자바빈으로 등록하라고 알려주는 어노테이션 - IoC컨테이너에 인스턴스 저장
    @SpringBootApplication이 실행될때 자동적으로 컴포넌스 스캔이 실행되어 @Componet이 붙은 클래스를 IoC에 등록한다.

  • @Controller, @Repository, @Service 같은 스테레오 타입 어노테이션들은 보다 구체적인 기능의 인스턴스를 생성
    ( 내부에 @Component가 달려있다 ) - 마찬가지로 IoC 컨테이너에 생성

    • Repository - DB접근
    • Service - 비즈니스 로직을 트랜잭션으로 관리하는 레이어
    • Configuration - 자바 설정 파일
  • @Bean 어노테이션은 @Componet와 다르게 메소드에 붙여서 메소드가 반환하는 객체를 IoC 에 등록하게 되는데 @Configuragion과 함께 사용된다.




서비스 클래스

  • 사용자의 요청( 가입신청, 조회, 글쓰기, 회원정보수정 등..)을 처리 하는 기능 ( 비즈니스 로직 )

  • DAO 클래스( 스프링의 @Repository ) 이용해서 DB연동 처리 ( MyBatis 이용하면 @Mapper )
    ( 일반적으로 DB 와 DAO 는 1:1 매칭 )

  • @Service 어노테이션을 이용해서 IoC 컨테이너에 인스턴스 생성

  • 서비스 클래스에서 비즈니스 로직을 트랜잭션으로 관리한다 - 하나라도 익셉션 발생시 롤백

  • DB 에 접근하기 위해 DB 커넥션 객체와 DAO 객체에 접근한뒤 PreparedStatement로 쿼리를 작성해야 하는데 라이브러리( MyBatis )가 이를 대신해준다




트랜잭션

  • 처리의 최소 단위, 예를들면 송금할때 나의 계좌에서 돈이 빠져나가고, 상대의 계좌에 돈이 추가되고, 송금에 대한 history를 기록하는 3가지의 과정을 말함

  • 트랜잭션은 ACID 원칙을 지켜야하는데
    A ( 원자성 ) -> 트랜잭션의 모든 처리가 완료되지 않으면 처음상태로 롤백 하게 되고, 모든 처리가 성공적으로 완료되면 커밋을 한다.

  • 여러 트랜잭션을 처리할때는 서비스 레이어에서 처리한다

  • 컨트롤러와 리포지토리 사이에서 트랜잭션 처리가 필요하면 서비스 레이어를 거쳐야 한다

  • 트랜잭션 중에는 동기화가 이루어진다 -> 컨트롤러에서 트랜잭션을 걸면 안된다 ( 대기 시간 낭비 )

  • 따라서 최대한 DB와 가까운 레이어에서 트랜잭션을 걸어야 한다

  • 서비스 레이어의 존재 이유는 트랜잭션을 줄이기 위함이다

  • 스프링에서는 @Transactional 어노테이션을 붙이면 런타임 익셉션 발생시 강제로 롤백을 해준다
    ( setAutoCommit(false) + commit() // rollback() )





필터

  • 필터 또한 서블릿

  • 필터에서 로그인 상태를 확인 -> 로그인 상태에 따른 다른 페이지 제공 ( 동적 페이지, 서버로직 )

  • 필터는 조건에 따라 흐름을 제어한다

  • 필터는 데이터를 변화시킬 수 있다 ( 데이터의 흐름을 변화 시킨다 - 다른 리소스 제공 )

  • 여러개의 필터가 사용될 수 있다 ( 예를들면 로그인 후 구독자 전용 페이지, 회원 등급에 따른 페이지 )

  • 필터 분리 -> 서블릿( 클래스 ) 분리 -> 유지보수가 편하다




profile
작은것부터

0개의 댓글