BEB 07 6-5

Donghun Seol·2022년 10월 21일
0

코드스테이츠 BEB 07

목록 보기
24/39

데이터베이스시스템 8장 데이터 저장과 파일

정리하기 복기

일단 무지성으로 강의의 정리하기를 따라치면서 복기해 보자.

  1. 물리적 저장장치들은 데이터 접근 속도 관점에서 계층적으로 분류 된다. 상위 계층은 접근 속도가 빠르지만 고가의 장비이며 하위 계층은 접근 속도가 느리지만 저가의 장비이다.
  2. 일반적으로 상위의 저장장치들은 전원 공급이 차단되면 데이터가 소멸 되는 휘발성이며 하위의 저장장치들은 전원 공급이 차단 되어도 데이터가 소멸되지 않는 비 휘발성이다.
  3. 데이터베이스는 여러개의 파일로 구현 된다 파일이란 데이터를 영구적으로 저장하기 위해 사용하는 구조이다. 파일은 물리적으로 여러 블럭으로 나뉘어 저장 되기도 한다. 하나의 파일은 다수의 레코드를 저장하고 있다 레코드는 관계형 모델에서 투플에 대응하는 개념이다.
  4. 레코드의 형식은 고정 길이 레코드와 가변 길이 레코드가 있다. 레코드의 형식에 따라 파일 및 블럭에서 레코드를 관리 하는 방식이 달라진다. 특히 슬롯 페이지 구조는 가변 길이 레코드를 관리할때 이용되는 블럭 구조이다.
  5. 특정 컬럼에 대한 빠른 접근이 요구 되는 경우 파일이 저장 되는 레코드를 구조화 하는 것이 좋다. 파일 구조화 방법으로는 힙 파일 구조화 순차 파일 구조화 해쉬 파일 구조화가 있다. 파일 구조 중 다중 테이블 군집 파일 구조는 여러개의 테이블을 하나의 파일에서 관리하는 특수한 파일 구조이다.
  6. 메모리와 디스크는 블럭 단위로 데이터를 주고 받는다. 데이터베이스 시스템에서는 블럭의 입출력을 최소화 하기 위해 메모리 내 버퍼 라는 공간을 만들며 버퍼를 효율적으로 관리 하기 위해 버퍼 관리자를 사용한다.

알아야할 키워드

휘발성
파일 구조
블럭
고정길이 레코드
가용리스트
가변길이 레코드
멀티셋
슬롯 페이지 구조
힙 파일 구조
순차 파일 구조
해시 파일 구조
탐색키
키 순차 파일
오버플로 블럭
순차파일방식의 장단점
버퍼
버퍼 관리자
버퍼교체 전략
고정 블럭
블럭 강제 출력

데이터 저장과 파일

ORM content

sequelize를 사용해 보았으므로 패스~

ORM Sprint

sequelize cli 활용

generate model
npx sequelize-cli model:generate --name urls --attributes url:string,title:string,visits:integer

db migrate
npx sequelize-cli db:create
npx sequelize-cli db:migrate

sequelize model initialization

model에서 정의된 db 클래스의 인스턴스를 생성하는데,
생성자의 인자로 현재 접속설정이 주입된 Sequelize의 인스턴스를 넣는다.
db.url = url(sequelize, Sequelize.DataTypes);

tossing data inside of callback flow

다른 부분은 평이한 웹서버를 작성하는 로직이라 손쉽게 해결했지만
getUrlTitle이라는 콜백함수 안에서 res.json()을 호출하는 부분에서 많이 고민했다.
사실은 비동기가 아닌데 비동기라고 생각해서 비동기 처리를 해주느라 많이 고민함....
아래의 코드는 비동기라 생각하고 작성한 결과고, 딱 봐도 무슨 역할을 하는 코드인지 알아보기 힘들다.

exports.post = async (req, res, next) => {
  try {
    getUrlTitle(req.body.url, async (err, title) => {
      if (err) next(err);
      extractedTitle = title;
      const result = await url.create({
        "url": req.body.url,
        "title": extractedTitle,
        "visits": 1
      });
      res.status(201).json(result);
    });
  } catch (err) {
    console.error(err);
    next(err);
  }
};

RDB

sprint

항상 마주치는 문제이지만, 코드를 작성하기 전에 문제를 충~분히 이해하고 시작하자
결국 이렇게 코딩하는 습관이 시간이 훨씬 단축된다.

단편적으로만 읽고, 내 마음대로 해석하고, 신나게 작성하다가...
오잉 오류를 마주치면 평향된 내 사고를 되돌리고, 코드도 갈아엎야되고, 디버그도 또 해야되니깐 에구..
이처럼 미련한 짓이 없다. 항상 명세서를 잘 읽고, 확실히 읽고, 정확히 읽고, 이해하고 난 다음에 키보드를 두들기자...

아무튼 내 힘으로 스프린트를 끝내서 뿌듯하긴 하다.

prepared statement 활용법 sql injection 방지

스프린트 리뷰세션에서 배운 매우매우 중요한 내용이다.

preapared statement를 활용해서 동적으로 SQL을 처리할 수 있는데, 동적이라 간편하고, 가독성이 높으며, 성능까지 우월하다. 심지어 sql injection 공격도 방지할 수 있다.

이번 스프린트의 핵심적인 내용이 모두 담긴 model.post 함수의 레퍼런스 코드
잘 기억하고, 또 찾아보고, 자주 사용해서 익숙해지자.

prepared statement와, query params로 배열을 전달해서 multi creation 하는 방법을 눈여겨 보면 된다.

  post: (userId, orders, totalPrice, callback) => {
      // TODO: 해당 유저의 주문 요청을 데이터베이스에 생성하는 함수를 작성하세요
      const queryString = `INSERT INTO orders (user_id, total_price) VALUES (?, ?)`;
      const params = [userId, totalPrice];

      db.query(queryString, params, (error, result) => {
        if (result) {
          const queryString = `INSERT INTO order_items (order_id, item_id, order_quantity) VALUES ?;`;
          const params = orders.map((order) => [
            result.insertId,
            order.itemId,
            order.quantity,
          ]);

          return db.query(queryString, [params], (error, result) => {
            callback(error, result);
          });
        }
        callback(error, null);
      });
    },

멀티쿼리의 transaction화

만약 멀티쿼리를 수행중 (알수 없는) 특정한 쿼리에서 오류가 난다면?
게다가 idempotent하지 않은 쿼리를 수행중이었다면 데이터 무결성을 어떻게 보장하나?

동료 수강생의 날카로운 질문에 ??을 탁 칠수 밖에 없었다.
정말 중요한 포인트라 생각하고, 그 동료분은 CS에 대한 이해가 깊은 분이라는 걸 다시 한번 느꼈다.
강사님이 찾아주신 패턴이다. 당장 습득하진 못하겠지만, 언제든지 찾아 볼 수 있도록 머리속에 키워드를 인덱싱 해놓자.
https://github.com/mysqljs/mysql#transactions

indexing

join

multi insertion method

callback 처리

자세한 책

이화식 대용량

https://dappradar.com/

profile
I'm going from failure to failure without losing enthusiasm

0개의 댓글