TIL 13 | SQL과 ORM 그리고 MVC란?

Seon Kang choi·2021년 10월 3일
0
post-thumbnail

SQL

SQL을 알아보기 전에 DBMS(Database Management System)을 알아보자

데이터베이스란?
대량의 정보를 컴퓨터가 효율적으로 접근할 수 있도록 가공 및 저장한 것이다.

DBMS란?
다수의 사용잘들이 데이터베이스 내 데이터를 접근할 수 있도록 해주는 소프트웨어 도구 집합이다.

관계형 데이터베이스

key와 value의 간단한 관계를 테이블 형식으로 나타낸 데이터베이스이다. 하나의 데이터베이스에는 여러 개의 테이블이 존재한다.

RDBMS(Relational Database Management System)

관계형 데이터베이스를 생성, 갱신, 관리하기 위한 시스템이다. 레코드 단위로 읽기/쓰기가 이루어진다.
클라이언트가 요청을 보낼 때 주로 사용하는 언어가 SQL이다.

SQL

SQL은 RDBMS에 저장된 데이터와 통신하기 위해 필요한 프로그래밍 언어이다.

명령어
크게 4가지 그룹으로 나뉜다.

  • DDL : 데이터베이스 스키마와 설명을 처리를 정의하는 언어, 데이터베이스 테이블 생성/변경/삭제 등의 작업을 포함한다.(CREATE, ALTER, DROP 등)
  • DML : 데이터 검색, 삽입, 변경, 삭제를 수행하여 조작하는 언어, 저장된 데이터에 처리할 때 사용한다.(SELECT, INSERT, UPDATE, DELETE 등)
  • DCL : 데이터에 접근할 수 있는 권한을 관리하는 언어이다.(GRANT, REVOKE)
  • TCL : 트랜잭션을 다루는 언어이다.(COMMIT, ROLLBACK, SAVEPOINT 등)

데이터 타입

  • varchar(size): 최대 크기 255자의 문자를 저장한다. 문자열의 길이는 가변적이다.
  • int(m) : m은 정수의 크기가 아닌 자릿수 개수이다.
  • bigint(m) : m은 정수의 크기가 아닌 자릿수 개수이다.
  • float(m, d) : m은 정수 자릿수, d는 소수점 아래 자릿수 개수이다.
  • date : 'YYYY-MM-DD'로 표기된다.
  • time : 'HH:MM:SS'로 표기된다.

ORM(Object Relational Mapping)

영속성(Persistence)

  • 데이터를 생성한 프로그램이 종료되더라도 없어지지 않는 데이터의 특성이다.
  • 영속성을 갖지 않은 데이터는 단지 메모리에만 있기에 프로그램이 종료하면 모두 없어진다.
  • Object Persistence(영구적인 객체)
    1. 메모리 상의 데이터를 파일 시스템, 관계형 데이터베이스 혹은 객체 데이터베이스 등을 활용하여 영구적으로 저장하여 영속성을 부여한다.
    2. 데이터를 데이터베이스에 저장하는 3가지 방법
    JDBC, Spring JDBC, Persistence Framework(Hibernate, Mybatis 등)
  • Persistence Layer
    1. 프로그램 아키텍처에서 데이터에 영속성을 부여하는 계층이다.
    2. Persistence framework를 이용한 개발이 많이 이루어지고 있다.
  • Persistenct Framework
    1. JDBC프로그래밍의 복잡함이나 번거로움 없이 간단한 작업만으로 데이터 베이스와 연동되는 시스템을 빠르게 개발할 수 있으며 안정적인 구동을 보장한다.
    2. Persistence Framework는 SQL Mapper와 ORM으로 나눈다.(JPA, Hibernate, Mybatis 등)

ORM이란?

  • 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해주는 것을 말한다.
    1. 객체지향 프로그램은 클래스를 관계형 데이터베이스는 테이블을 사용한다.
    1. 객체 모델과 관계형 모델 간의 불일치가 존재, ORM을 통해 객체 간의 바탕으로 SQL을 자동으로 생성하여 불일치를 해결한다.
  • 데이터베이스 <- 매핑 -> Object

ORM 장단점

  • 장점
  1. 객체 지향적인 코드와 비즈니스 로직에 더 집중할 수 있다. SQL 쿼리가 아닌 객체 모델로의 프로그래밍에 더욱 집중하고 코드에 집중하기에 가독성을 올려준다.
  2. 재사용 및 유지보수의 편리성이 증가한다. ORM이 독립적으로 작성되어 있어 해당 객체들을 재활용할 수 있다. 때문에 모델에서 가공된 데이터로 디자인패턴을 견고하게 유지할 수 있다.
  3. DBMS에 대한 종속성이 줄어든다. SQL을 자동으로 생성하기 때문에 DBMS의 데이터 구조와 Java의 객체지향 모델 사이의 간격을 좁힐 수 있다. 또한 자바의 기능을 이용할 수 있고, 간결하고 빠른 가공이 가능하다.
  • 단점
  1. 완벽한 ORM으로만 서비스를 구현하기 어렵다. 사용하기는 편하지만 설계는 매우 신중하게 해야 하고, 프로젝트의 복잡성이 커질수록 난이도도 올라간다.
  2. 프로시저가 많은 시스템에서는 ORM의 객체 지향적인 장점을 활용하기 어렵다. 프로시저가 많은 시스템에선 다시 객체로 바꿔야하며, 이 과정에서 생산성 저하나 리스크가 많이 발생한다.

Spring MVC 구조 정리


스프링 MVC는 프로트 컨트롤러 패턴으로 구현되어 있다. 그리고 프론트 컨트롤러가 DispatcherServlet 이다.
org.springframework.web.servlet.DispatcherServlet
DispatcherServlet도 부모 클래스로 HttpServlet을 상속 받아 사용하고, 동작한다.


위 그림은 DispatcherServlet의 다이어그램이다. DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet 으로 상속받는다.

HttpServlet의 service() 호출로 FrameworkServlet.service()가 시작된다. 여러 메서드가 시작되면서 DispatcherServlet.doService()가 호출되고 DispatcherServlet의 핵심인 doDispatch() 코드가 실행된다. doDispatch()에 SpringMVC의 모든 구조가 다 들이 있다.

DispatcherServlet.doDispatch()

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  HttpServletRequest processedRequest = request;
  HandlerExecutionChain mappedHandler = null;
  
  try {
    ModelAndView mv = null;
    
    try {
      // 1. 핸들러 조회
      mappedHandler = getHandler(processedRequest);
      if (mappedHandler == null) {
        noHandlerFound(processedRequest, response);
        return;
      }
      
      // 2. 핸들러를 처리할 수 있는 핸들러 어댑터 조회
      HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
      
      // 3. 핸들러 어댑터 실행 -> 4. 핸들러 어댑터를 통해 핸들러 실행 -> 5. ModelAndView 반환
      mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
      
      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
  }
}

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
  if (mv != null && !mv.wasCleared()) {
    // view 랜더링 호출
    render(mv, request, response);
  }
}

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
  View view;
  String viewName = mv.getViewName();
  
  if (viewName != null) {
    // 6. view 리졸버를 통해 view 찾기 -> 7. view 반환
    view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
  }
  
  // 8. view 렌더링
  view.render(mv.getModelInternal(), request, response);
}
  • 동작 순서
  1. 핸들러 조회 : URL에 매핑된 핸들러 조회
  2. 핸들러 어댑터 조회 : 핸들러를 실행할 수 있는 어댑터 조회
  3. 핸들러 어댑터 실행 : 핸들러 어댑터 실행
  4. 핸들러 실행 : 핸들러 어댑터가 실제 핸들러 실행
  5. ModelAndView 반환 : 핸들러 어댑터가 반환하는 정보를 ModelAndView로 변환해서 반환
  6. viewResolver 호출 : viewResolver 찾고 실행
  7. view 반환 : view 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 view 객체를 반환
  8. view 렌더링 : view 렌더링

스프링MVC의 큰 강점은 DispatcherServlet 코드의 변경 없이 원하는 기능을 변경하거나 확장할 수 있다는 것이다. 대부분을 확장 가능하게 인터페이스로 제공한다.

profile
유쾌한 개발 생활~

0개의 댓글