[백엔드 로드맵] DB 기초

Gyubster·2022년 2월 5일
0

백엔드 로드맵

목록 보기
5/11

인터넷에 대한 기초를 어느정도는 정리한 것으로 생각해 Database에 대한 이야기를 진행해보고자 한다. 대략적으로 다룰 내용은 RDBMS-Mysql 위주(기회가된다면 NoSQL-MongoDB, Firebase 도..)로 해볼 생각이다.
첫번째로 다룰 RDBMS에 관련한 내용은 검색 및 "SQL 첫걸음"을 통해서 정리하여 작성되었다. 기본적인 구문 보단 개념적인 것을 정리할 예정이다.(실습은 모두 되어있기때문에, 관련한 포스팅을 적는 것 보다는 기초를 위한 개념 정리를 하고자한다. 명령어 정도는 정리를 할지도...?)


Database

: 데이터를 저장 및 보존하는 시스템이다. Application에서는 데이터가 메모리 상에서 존재한다. 하지만 메모리는 휘발성이기 때문에 재부팅시 모든 데이터가 사라진다. 따라서, 이를 장기간 동안 보관하여 활용하기 위해서 Database를 사용하는 것이다. Database는 크게 RDBMS(Relational DataBase Management System)와 No SQL(Non-Relational DataBase Management System)으로 나눠져 있다.

RDBMS

: 관계형 데이터 모델을 기초로 둔 시스템이다. 즉, Column 과 Row로 이루어진 2차원 테이블로 구성되는 데이터들을 다루는 System이라고 생각하면된다. 테이블은 one to one, one to many, many to many로 서로 상관관계를 가진다. 이러한 상관관계는 Foreign Key를 통해 참조하면서 이뤄진다. 이는 각 테이블마다 중복되는 데이터들의 양을 줄이고 또한, 같은 데이터에 대한 다른 값을 작성할 수 있는 가능성을 없애주는 장점을 가지고 있다. 이를 Normalization이라고 부른다.

SQL

: RDBMS를 사용하기 위한 언어이다. 관계형 데이터베이스의 데이터를 더 효율저기고 체계적으로 저장 및 관리할 수 있다. 미리 저장하는 데이터들의 구조를 정의함으로써 데이터의 완전성이 보장된다. 하지만, 테이블이 모두 정의가 되어있어야하기 때문에 확장성이 쉽지 않다. 또한, 확장을 하기위해서는 Scale Up을 통해 확장이 가능하다. 즉, 서버를 늘려 분산 저장하기에 불리하다. 정리하자면, 정형화된 데이터들 그리고 완전성이 중요한 데이터들을 저장하는데 유리하다.

No SQL Database

: 비관계형 모델을 기초로 둔 시스템이다. 데이터의 저장을 위해 정의할 필요가 없다.

No SQL

: 데이터의 구조 변화에 유연하다는 장점을 가지고 있다. Scale Out을 통해 확장이 수월하다. 이러한 장점때문에 방대한 양의 데이터를 저장하는데 수월하다. 하지만, Transaction이 안되거나 불안정하다. 따라서, 비정형화 데이터 및 완전성이 떨어지는 로그데이터와 같은 데이터를 저장할 때 사용한다.


Additional Information

  • Transaction 이란?
    : 일련의 작업들이 하나로 취급 되어 모든 작업들이 통과되어야만 성공하고 하나의 작업이라도 불통되면 실패하는 것을 이야기한다. 이를 all-or-nothing이라고 부른다. 대표적인 예로, A가 B에게 돈을 보내는 은행 송금 업무를 생각해보자. A의 은행에서 돈이 빠져나갔지만 오류로 인해 B에게 돈이 전달이 안되는 최악의 상황이 Transaction을 통해서 방지 될 수 있다. 이는 Transaction의 ACID라는 특징으로 데이터의 유효성이 보장되기 때문에 가능하다.
  • ACID란?
    : A(Atomicity) C(Consistency) I(Isolation) D(Durability)를 의미한다.
    Atomicity는 모든 작업이 commit되거나 모두 rollback되는 것을 의미한다. 즉, 트랜잭션과 관련된 작업들이 부분적으로 실행되다가 중단되지 않는 것을 의미한다.
    Consistency는 데이터가 미리 정의된 약속에 의해서만 수정이 가능하다.(문자열로 정의된 데이터에는 숫자를 넣을 수 없다.) 즉, 트랜잭션이 성공적으로 완료되면 일관성있게 데이터베이스 상태를 유지하는 것을 의미한다.
    Isolation은 동시에 두 트랜잭션이 일어나는 경우, 서로의 트랜잭션에게 간섭할 수 없는 것을 보장하는 것을 의미한다.
    Durability는 성공적으로 수행된 트랜잭션이 영원히 반영되어야하는 것을 의미한다.
  • SQL의 JOIN란?
    : SQL에서는 두개 이상의 테이블을 결합하여 데이터를 검색하는 방법을 JOIN이라고 한다. 이는 Primary Key와 Foregin Key를 참조하여 가능하다. JOIN의 종류는 여러가지지만, 가장 많이 쓰이는 JOIN은 LEFT JOIN, INNER JOIN이다.
  • LEFT JOIN이란?
    Table A와 Table B가 있다고 가정해보자. Table A를 기준으로 하여 Table B과 LEFT JOIN을 한다면, 순수 Table A에 대한 데이터들과 함께 참조된 Table B에 대한 정보가 같이 정리되어 나온다. 특징으로 Table A에 B를 참조하지 않은 경우(NULL)인 경우, 참조된 값들은 모두 Null처리가 된다. 위의 사진은 일반적으로 Table users를 불러냈을 때이고, 아래의 사진은 INNER JOIN을 통해 Table users가 참조한 Table genders를 결합하여 데이터를 검색한 경우이다. 아쉽게도 모든 값이 다 참조되고 있어서.. 자동으로 NULL로 처리된 좋은 예시는 아니다.


    정리하자면, 아래의 벤다이어 그램과 같다고 생각하면 된다. 선행되는 그룹의 모든 데이터들을 가져오고 참조한 데이터가 있으면 나타내고 없으면 NULL로 채워넣는다.

    이미지 출처:https://admm.tistory.com/40
  • INNER JOIN란?
    마찬가지로 Table A와 Table B가 있다고 가정해보자. Table A를 기준으로 하여 Table B과 INNER JOIN을 한다면, Table A와 Table B가 값을 가진 데이터들만 표현한다는 것이다. 즉, 서로가 다 값을 가지고 있는 Cell만 가져온 데이터를 보여준다는 것이다.
    벤다이어 그램으로 보면 아래와 같다.

    이미지 출처:https://admm.tistory.com/40
  • SQL Injection란?
    : 보안상의 취약점을 이용하여 SQL 구문을 주입하여 데이터베이스가 비정상적인 동작을 하도록 조작하는 행위를 말한다. 종류로는 논리적 에러를 이용한 방법, Union 명령어를 이용한 방법 등 다양한 방법이 있다.
    관련한 자세한 내용은 https://noirstar.tistory.com/264에서 확인하면 좋다.
  • 정규화란?
    : 정규화는 데이터베이스의 테이블을 규정된 올바른 형태로 개선해나가는 개선해 나가는 것을 의미하며 궁극적으로는 하나의 데이터가 한곳에 저장되어야하는 걸 목표로한다. 단계적으로 존재하는 정규형은 제 1정규형부터 제 5 정규형까지 존재한다.(실제로는 거의 제 3정규형까지만 다룬다.)
  1. 제 1 정규형
    : 테이블 분할과 기본키 지정이 일어난다.
  2. 제 2 정규형
    : 함수 종속성을 기반으로한 테이블 분할이 일어난다.
  3. 제 3 정규형
    : 기본키 이외의 부분에서 중복이 없는지 조사한다.
  • ORM 이란?
    : ORM은 Persistence Framework 중 하나이다. Persistence Framework는 데이터에 영속성(데이터가 프로그램이 종료되더라도 지워지지 않는 속성) 부여하는 도구 라고 생각하면된다. Persistence Framework는 Persistence Layer(프로그램 아키텍쳐에서 데이터에 영속성을 부여하는 계층)을 만드는 데 사용되며, JDBC, Spring JDBC를 사용하는 것 보다 간단한 작업으로 만들 수 있기 때문에 선호되는 방식이다.
    ORM은 Object Relational Mapping을 의미한다. 즉, 객체와 관계지향형 데이터베이스의 데이터를 자동으로 연결해주는 역할은 한다. 객체 지향형 프로그래밍은 Class 형태를 이용하고 관계지향형 데이터는 Table 형태를 이용하는데 이 차이를 ORM을 통해서 객체간의 관계를 통해서 SQL을 자동으로 생성하여 불일치를 해결한다는 것이다. 즉, RDBMS Data- Mapping(ORM) - Object 라고 생각하면 된다.
    이러한 ORM의 장단점은 아래와 같다.
    장점 1. 객체 지향적인 코드를 통해서 직관성을 얻을 수 있다.
    : SQL Query보다 직관적인코드로 데이터를 조작할 수 있어 개발자가 객체 모델로 프로그래밍을 가능하게한다.또한, 이를 통해서 코드의 가독성 및 부수적인 코드 작성의 불편함이 해결된다.
    장점 2. 재사용 및 유지보수의 편리성이 증가한다.
    : ERD(Entity Relationship Model)의 의존도를 낮출 수 있다.
    장점 3. DBMS에 대한 의존도가 줄어든다.
    : 객체 관의 관계를 바탕으로 자동적으로 SQL을 생성하기 때문에 DBMS 교체와 같은 극단적인 상황에도 비교적 적은 리스크와 시간이 걸린다.
    단점 1. 완벽한 설계가 어렵다.
    : 사용하기 편하지만 설계가 어렵고 프로젝트가 크고 복잡해질수록 난이도가 올라간다.
    단점 2. 프로세스가 많은 시스템에선 객체 지향적인 장점 활용이 어렵다.
  • ORM - Django
    : Django에서 쓰이는 Django ORM에 대해서 추가적으로 내용을 정리하고자한다. Django에 대한 심화적인 이해를 원해서 Pycon Korea 2020에 나온 김성렬님의 동영상을 보고 정리한 내용이다.
    Django ORM은 Lazy-loading: 정말 필요할때 SQL을 호출, Caching: QuerySet 캐싱을 통해 SQL 호출의 절약, EagerLoading(Resolve N+1 ): select_related, prefetch_related를 통해서 Lazy-loading가 n개의 데이터에서 x번째 데이터를 가져오는데 n+1번 데이터를 검색하고 찾음으로 인한 성능 저하이슈를 해결하는 방법 . 방식을 이용한다. ORM에서 명령을 실행할 때마다 데이터베이스에 접근하여 데이터를 가져오는 것이 아닌 모든 명령 처리가 끝나고 실제 데이터를 불러와야할때 데이터베이스의 쿼리문이 실행되는 방식을 말한다.
    Django에서는 slicing, caching, len(), list(), bool(), repr()를 호출할 때 쿼리가 실행된다. 예를 들어, users = User.objects.all(), posts = Post.objects.all(), print(posts) 이 세가지 명령어가 작성되어 있는 경우를 생각해보자. users 와 posts를 각 객체들의 데이터를 받아 변수를 선언한 것으로 생각하여 쿼리가 2번 돌아갔다고 생각할 수 있지만 실제로는 쿼리는 단 한번 posts를 출력할때 실행된다. 다른 예시로 이야기해보자. users = User.objects.all(), print(users[0]), user_list=list(users)users = User.objects.all(), user_list=list(users), print(users[0])의 쿼리 실행 횟수는 어떻게 될까? 오른쪽의 예시는 slicing때 한번, list()때 한번 해서 총 두번이다. 왼쪽의 예시는 list()때 한번 그리고 slicing때는 쿼리를 실행하지 않는다. 그 이유는 list(users) 실행하게 되면서 QuerySet에 데이터를 캐싱하게 된다. 따라서, slicing은 캐싱된 Queryset에서 이뤄지기 때문에 쿼리를 실행하지 않는다.
  • ORM - Django - select_related(), prefetch_related()
    : select_related()는 JOIN으로 쿼리 실행 횟수가 증가하지는 않는다. prefetch_related()는 추가 쿼리를 실행하는 것으로 횟수가 증가한다. 정방향 참조의 경우는 두개 모두 사용 가능하지만, 역방향 참조의 경우는 select_related()는 사용할 수 없다. prefetch에서는 Prefetch()함수를 통해서 queryset에 대한 옵션을 추가 할 수 있다.
  • Index 란?
    : Index는 색인이라고도 불린다. 테이블내에 Index를 지정할 수 있는데, 이를 통해, 검색 속도를 향상 시킬 수 있다. 비유하자면 책안에 정보를 빠르게 찾을 수 있게 해주는 목차라고 생각하면된다. Index를 이용하면 데이터를 Binary Search(이진탐색)을 통해서 검색하여 Full Table Scan 보다 검색 속도의 향상이 일어나게된다.
    좀 더 구체적으로 이야기하자면, 테이블에 Index를 작성하면 테이블데이터와는 별개로 Index용 데이터가 Binary Tree(이진 트리) 형태로 저장장치에 저장이된다. 중간 값을 Root Node로 지정하여 나눠진 2 그룹의 중간 값을 그다음 상위 Node로 지정하는 것을 반복하여 Tree 구조를 아래의 사진처럼 만들어 저장된다. 단, 같은 값을 가지는 Node는 만들 수 없기 때문에 Primary Key를 가지고 있는 경우에 많이 활용된다.
  • DBCP란?
    : DB Connection Pool을 의미하며, 웹컨테이너가 실행되면서 DB와 미리 connection을 해놓은 객체들을 pool에 클라이언트 요청이 오면 connection을 빌려주고, 처리가 끝나면 connection을 반납받아 pool에 저장하는 방식을 이야기한다. 요청마다 DB와의 연결 부하를 줄 일 수 있다는 점이 장점이다. 동시 접속자가 많을 경우에는 WAS에서 Connection Pool을 조절하여 해결하면된다. 단, Connection Pool을 늘리면 메모리 소모가 크다는 문제가 생긴다.
  • Data Replication이란?
    : Data는 Apllication Server를 통해 DB에 요청을 보내 가져온다. 대부분의 데이터는 SELECT를 통해 가져오게 되는데, Data Replication은 이에 대한 로드를 해결하는 방법으로 2개 이상의 DBMS 시스템을 Master/Slave 로 나눠서 동일한 데이터를 저장하는 방식이다. Master에는 데이터의 수정사항이 있을때 반영이 사용된다, Slave는 SELECT가 일어날때 사용된다. 즉, 읽기 부하를 분한시키는 것을 의미한다.
profile
공부하는 예비 개발자

0개의 댓글