본문 바로가기
카테고리 없음

WIL (SQL,MVC,ORM)

by 소년수 2022. 8. 7.

이번주 간 내가 배운 SQL,MVC,ORM에 대해서 WIL을 적어보겠다.

 

 

SQL은 곧 DB

  • JPA 가 제공하는 연관관계는 결국 DB 의 연관관계를 표현하기 위함
  • 따라서 먼저 DB 의 연관관계를 이해해야 함
  • DB 의 연관관계는 비즈니스 요구사항에 맞춰 이루어짐

SQL이란?

SQL(Structured Query Lanaguage)은 데이터를 쉽게 검색하고 조작(추가, 삭제, 수정 등) 할 수 있도록 고안된 컴퓨터 언어이다. SQL은 아래 3가지 종류로 분류된다.

SQL의 분류

  • DML (Data Manipulation Language): 데이터 조작 ex) INSERT, UPDATE, DELETE, SELECT
  • DDL (Data Definition Lanaguage): 데이터베이스의 스키마 정의 또는 조작. ex) CREATE, DROP, ALTER
  • DCL (Data Control Lanaguage): 데이터 제어. 권한 관리, 데이터 보안, 무결성 등을 정의. ex) GRANT, REVOKE

 

일단 DB연결을 하려면 Mysql Driver를 사용해야한다.
나는 의존성관리를 Gradle로 세팅했다.
그래서 Gradle에 사용법에 대해 먼저 학습하기 위해 Dependencies를 설정을 하기전에 Configuration에 대해 가볍게 알아보았다.

api : 런타임과 컴파일
implementation : 런타임과 컴파일
compileOnly : 컴파일
runtimeOnly : 런타임

 

DB에 붙기위해 정보를 입력해야한다.
다음과 같이 application.properties에서 설정해주면 된다.

spring.datasource.url=jdbc:mysql://DB주소:3306/DB명

spring.datasource.username=유저이름

spring.datasource.password=비밀번호

spring.jpa.show-sql: true

spring.datasource.driver-class-name =com.mysql.jdbc.Driver

이렇게 설정해주면 MySQL의 연결설정은 끝이난다.


1. 모델(Model)

DATA, 정보들의 가공을 책임지는 컴포넌트를 말합니다.

모델(Model)은 어플리케이션의 정보, 데이터를 나타냅니다. 데이타베이스, 처음의 정의하는 상수, 초기화 값, 변수 등을 뜻합니다. 비즈니스 로직을 처리한 후 모델의 변경사항을 컨트롤러와 뷰에 전달합니다.

모델은 다음과 같은 규칙을 가지고 있습니다.

  • 사용자가 편집하길 원하는 모든 데이터를 가지고 있어야 합니다.
  • 뷰나 컨트롤러에 대해서 어떤 정보도 알지 말아야 합니다.
  • 변경이 일어나면, 변경 통지에 대한 처리 방법을 구현해야만 합니다.

2. 뷰(View)

사용자에게 보여지는 부분, 즉 유저 인터페이스(User interface)를 의미합니다.

MVC 패턴은 여러 개의 뷰(View)가 존재할 수 있으며, 모델에게 질의하여 데이터를 전달받습니다. 뷰는 받은 데이터를 화면에 표시해주는 역할을 가지고 있습니다. 모델에게 전달받은 데이터를 별도로 저장하지 않아야 합니다. 사용자가 화면에 표시된 내용을 변경하게 되면 모델에게 전달하여 모델을 변경해야 합니다.

뷰는 다음과 같은 규칙을 가지고 있습니다.

  • 모델이 가지고 있는 정보를 따로 저장해서는 안됩니다.
  • 모델이나 컨트롤러와 같이 다른 구성요소들을 몰라야 됩니다.
  • 변경이 일어나면 변경통지에 대한 처리방법을 구현해야만 합니다.

3. 컨트롤러(Controller)

모델(Model)과 뷰(View) 사이를 이어주는 브릿지(Bridge) 역할을 의미합니다.

모델이나 뷰는 서로의 존재를 모르고 있습니다. 변경 사항을 외부로 알리고 수신하는 방법만 있습니다. 컨트롤러(Controller)는 이를 중재하기 위해 모델과 뷰에 대해 알고 있어야 합니다. 모델이나 뷰로부터 변경 내용을 통지 받으면 이를 각 구성 요소에게 통지해야 합니다. 사용자가 어플리케이션을 조작하여 발생하는 변경 이벤트들을 처리하는 역할을 수행합니다.

컨트롤러는 다음과 같은 규칙을 가지고 있습니다.

  • 모델이나 뷰에 대해서 알고 있어야 합니다.
  • 모델이나 뷰의 변경을 모니터링 해야 합니다.

2. MVC 패턴 왜 사용할까?

MVC 패턴에 대한 여러 글을 읽어봤지만, 결국 **'유지보수의 편리성'**이라는 하나의 결론으로 수렴합니다. 최초 설계를 꼼꼼하게 진행한 시스템이라도 유지보수가 발생하기 시작하면 각 기능간의 결합도(coupling)가 높아지는 경우가 발생합니다. 이는 최초 설계 이념을 정했던 사람들의 부재 혹은 비즈니스 요건 변경으로 인해 필연적으로 발생하는 것 같습니다. 결합도가 높아진 시스템은 유지보수 작업 시 다른 비즈니스 로직에 영향을 미치게 되므로 사소한 코드의 변경이 의도치 않은 버그를 유발할 수 있습니다.

선배 개발자들은 이런 문제점을 해결하기 위해 UI 시스템의 핵심 컴포넌트를 모델, 뷰, 컨트롤러로 나누고 각 컴포넌트가 자신의 수행 결과를 다른 컴포넌트에게 전달하는 프로그래밍 방식을 만들었습니다. MVC 패턴을 가진 시스템의 각 컴포넌트는 자신이 맡은 역할만 수행한 후 다른 컴포넌트로 결과만 넘겨주면 되기 때문에 시스템 결합도를 낮출 수 있습니다. 유지보수 시에도 특정 컴포넌트만 수정하면 되기 때문에 보다 쉽게 시스템 변경이 가능합니다. (화면의 변경은 only 뷰, 데이터나 비즈니스 요건이 변경은 only 모델, 뷰와 모델 변경에 따른 일부 컨트롤러 변경)

타임리프(Thymeleaf)

[ 설명 ]

개념

  • 스프링에서 권장하는 템플릿 엔진
  • HTML파일을 가져와서 파싱하고 분석한 후, 정해진 위치에 데이터를 치환해서 웹 페이지를 생성

JSP vs Thymeleaf

  • JSP
    • 템플릿 엔진이 X --> HTML내에 Java코드를 삽입해서 동적 페이지를 생성하는 서버사이드 스크립트 언어
    • Java Servlet으로 변환되어 실행 O
    • 배포를 위해 WAR(Web Application Archive) 타입이 사용 (JAR에 비해 무거움)
    • HTML파일 미리보기시 코드와 함께 존재하므로 정상 결과 X
  • Thymeleaf
    • 템플릿 엔진 O
    • Java Servlet으로 변환되어 실행 X
    • 배포를 위해 JAR(Java Archive) 타입 사용
    • HTML파일 미리보기시 정상 결과 O

추가

  • 템플릿 엔진 ?
    • HTML과 데이터를 결합해서 결과물을 만들어 주는 도구
    • ex) Thymeleaf / Velocity / Mustach 등
  • SpringBoot 경로
    • 정적 파일 : /resources/static
    • 동적 파일(템플릿 엔진 등) : /resources/templates
  • WAR vs JAR
    • WAR(Web application ARchive)
      • Servlet / JSP 컨테이너에 배치할 수 있는 웹 어플리케이션(Web Application) 압축 파일 포맷
      • Servlet 해석과 관련된 모든 패키지들을 포함해서 무거운 구조를 가짐
      • 단독으로 실행 불가하며 WEB / WAS가 함께 수행되어야 함
    • JAR(Java ARchive)
      • 쉽게 Java 어플리케이션이 동작할 수 있도록 Java 프로젝트를 압축한 파일
      • JDK(Java Development Kit)에 있는 JRE(Java Runtime Environment)만 있으면 실행 가능
      • Java만 설치되면 실행 가능

https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FebrXGP%2FbtqCO2BFpl6%2FRQkqJTJe3C3AecxZUk9REk%2Fimg.png

[ 문법 ]

핵심th:xxx가 붙은 부분은 서버 사이드에서 렌더링 되고, 기존 속성을 대체 하는 원리서버에서 동적으로 데이터를 변경할 때 th:xxx로 속성을 대체하는 것HTML파일을 직접 열었을 때, 브라우저는 th: 속성을 모르니까 무시하고 출력됨


  • 선언

  • URL 링크 표현식
    • 타임리프에서 URL링크를 사용하는 경우 @{...}를 사용한다
    • Path Variable 뿐만 아니라 Query Parameter도 생성해서 사용할 수 있다
/* 기본 사용 */
<a th:href="@{/css/bootstrap.min.css}"/>

/* Path Variable / Query Parameter */
<a th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}" />
실제 생성 링크 예시 --> <http://localhost:8080/basic/items/1?query=test>

  • 속성 변경
    • 타임리프의 핵심이 바로 기존 속성을 동적으로 대체할 수 있게 속성을 변경하는 것
    • 아래 예시는 onclick시 특정 경로로 이동하게 동적으로 처리
<button
   onclick="location.href='addForm.html'"th:onclick="|location.href='@{/basic/items/add}'|"/>

  • 리터럴 대체
    • 타임리프에서 문자와 표현식 등은 분리되어 있기 때문에, 더해서 사용해야 한다
    • 하지만, 가독성과 사용성이 떨어지므로 |...|를 통해 리터럴을 대체할 수 있다
/* 기존 방법 */
<button
   onclick="location.href='addForm.html'"th:onclick="location.href=' + '/'' + @{/basic/items/add} + '\\'"/>

/* 리터럴 대체 사용 */
<button
   onclick="location.href='addForm.html'"th:onclick="|location.href='@{/basic/items/add}'|"/>

  • 반복 출력
    • th:each를 사용해서 model에 포함된 값을 반복적으로 순회하며 수행할 수 있다
<tr th:each="item : ${items}"><td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}">회원id</a></td><td><a href="item.html" th:href="@{|/basic/items/${item.id}|}"th:text="${item.itemName}">상품명</a></td></tr>

  • 내용 변경
    • text 속성 값을 특정 값으로 대체
/* 정적인 경우의 10000을 가지지만, 값이 넘어오면 item.price로 대체 */
<td th:text=${item.price}">10000</td>

PRG(Post-Redirect-Get) 패턴

[ 개요 ]

PRG 패턴PRG 패턴은 웹 개발시 자주 사용되는 디자인 패턴POST 요청에 대한 응답이 또 다른 URL로의 GET 요청을 위한 리다이렉트(응답 코드가 3XX)여야 한다는 것만약 POST요청에 대한 응답이 리다이렉트가 아닌 단순 페이지 이동이면 문제가 발생함

  • 문제점(POST 응답이 단순 페이지 이동인경우)
    • 브라우저 새로고침을 할 때 마다 POST요청이 수행된다 --> 중복 수행
    • 따라서 반드시 PRG 패턴을 적용해야 함

[ PRG 패턴 적용 ]

  • Redirect를 이용해서 GET을 호출하도록 설계
  • 이제 브라우저 새로고침이 있어도 해당되는 GET만 다시 요청됨
  • Post 요청 후 redirect 수행시 주의사항
    • 특정 값을 추가해서 redirect할 때, 해당 값은 인코딩 과정이 수행되지 않는다-> 한글인 경우 모두 깨지게 됨-> 이것을 해결하기 위해 RedirectAttributes를 사용할 수 있음
@PostMapping("/add")
public String addItemV5(Item item) {
  itemRepository.save(item);
  /* Path Variable로 추가되는 item의 id와 같은 변수를 추가적으로 인코딩 되지 않음 */
  return "redirect:/basic/items/" + item.getId();
}

RedirectAttributes

[ 개념 ]

Redirect를 할 때 URL 인코딩, Path Variable / Query Parameter를 처리해주는 도구특정 View에서 Redirect의 여부를 확인하기 위해 변수를 전달하기 위해 사용하기도 함

[ 적용 ]

@PostMapping("/add") public String addItemV6(Item item, RedirectAttributes redirectAttributes) { Item savedItem = itemRepository.save(item); redirectAttributes.addAttribute("itemId", savedItem.getId()); redirectAttributes.addAttribute("status", true); return "redirect:/basic/items/{itemId}"; }

  • RedirectAttributes 객체 사용
  • .addAttribute로 값을 추가할 수 있음
  • url 경로에 변수가 존재하면 넣어주며, 없으면 자동으로 Query Parameter로 처리됨
  • 실제 요청 예시 : http:localhost:8080/basic/items/3?status=true


ORM 이란?

  • Object Relational Mapping(객체-관계-매핑)
  • MVC 패턴에서 모델(Model)을 기술하는 도구
  • 객체와 데이터베이스의 관계를 매핑해주는 도구
    • ORM 사용 이유? 
    •  객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다.
      -> 불일치하는 모델 ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 해결한다.
  • Persistant API라고도 한다. 
    • Ex) JPA, Hibernate 등

 

ORM 예시

  • DB : MySQL
  • ORM : MyBatis
  • Program : Java Application

 

ORM 장점

  1. 객체 지향적 코드로 인해 더 직관적인 코드(가독성)+ 비즈니스 로직에 집중 가능(생산성)
  2. 재사용 및 유지보수의 편리성
    • ORM은 디자인 패턴을 견고하게 만드는 데 유리하다.
    • ORM은 독립적으로 작성되었고 해당 객체들을 재활용 할수 있기 때문이다.
  1. DBMS에 대한 종속성 낮다
    • 객체 간 관계를 바탕으로 SQL을 자동으로 생성하기 때문에 RDBMS의 데이터 구조와 프로그래밍 언어의 객체 모델 사이의 간격을 좁힌다.
    • 대부분의 ORM 솔루션은 DB에 종속적이지 않다.
    • 프로그래머는 Object에 집중하므로 DBMS를 다루는 큰 작업에도 비교적 적은 리스크와 시간만 소요할 수 있다.

 

ORM 단점

  1. 완벽한 ORM 으로만 서비스를 구현하기가 어렵다.
  2. 프로젝트의 복잡성이 올라갈 수록 난이도가 높아진다
  3. 프로시저가 많은 시스템을 전환하기가 어렵다
    • 프로시저가 많은 시스템에선 ORM의 객체 지향적인 장점을 활용하기 어렵다.
      이미 프로시저가 많은 시스템에선 다시 객체로 바꿔야하며, 그 과정에서 생산성 저하나 리스크가 많이 발생할 수 있다.
  4. 프로시저가 많은 시스템에선 ORM의 객체 지향적인 장점을 활용하기 어렵다.
    이미 프로시저가 많은 시스템에선 다시 객체로 바꿔야하며, 그 과정에서 생산성 저하나 리스크가 많이 발생할 수 있다.
  5. 잘못 구현된 경우 속도저하 및 일관성이 무너지는 문제점이 생길 수 있다. 

 

ORM 종류

  • Sequelize : Node.js에서 가장많이 사용되고 있는 ORM이며 MySQL, PostgreSQL, MariaDB, SQLite, MSSQL을 지원
  • Prisma : GraphQL스키마를 기반으로 DB를 자동생성 해줌
  • myBatis : 개발자가 지정한 SQL, 저장 프로시저 그리고 몇 가지 고급 매핑을 지원하는 SQL Mapper
  • jdbc : DB에 접근할 수 있도록 Java에서 제공하는 API
  • jpa : JPA는 ORM을 사용하기 위한 표준 인터페이스를 모아둔 것, JPA의 대표적인 구현체로는 Hibernate, EclipseLink, DataNucleus, OpenJPA, TopLink Essentials 등
  • hibernate : HQL(Hibernate Query Language)이라 불리는 매우 강력한 쿼리 언어를 포함

 

댓글