HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📯
부스트캠프 7기 BE 멤버쉽 설계
/
3주차

3주차

스프린트
[W2] Airbnb
강의날짜
Sep 21, 2022
키워드
Database

무엇이든 궁금한점 (20분)

🧐
마스터클래스 질의응답 모음
제목
요약
확인
DB에 비즈니스 로직이 늘어나요
JOIN이 늘면서 복잡한 쿼리를 작성하고 있어 고민입니다.
확인
백엔드와 DB의 연산
해야하는 연산이 있을 때 BE에서 하는 것과 DB 쿼리로 하는 것을 어떻게 분배해야 할까요??
확인
비슷한 쿼리를 2개 요청해야 하는 경우
검색 총 개수와 슬라이스된 데이터들을 받아와야 하는데 쿼리를 2개 날리는 게 좋을까요 아니면 deprecated되더라도 SQL_CALC_FOUND_ROWS(FOUND_ROWS)를 쓰는 게 나을까요
확인
DB를 공부할 때 중요한 건 무엇일까요?
읽고 쓰기의 성능, 용어, ERD설계 등등 여러가지가 많은 것 같습니다! 어떤 것을 중심으로 공부하면 좋을까요?
확인
어제 노션에도 올린 질문인데, 그래프를 그리기 위한 데이터?
이미 해결된거 같네요
확인
보안적 측면에서의 uid의 해싱
uid를 안전한 함수로 해싱하면 보안적인 장점은 잡을 수 있겠으나, 그만큼 속도를 놓치겠죠…?
확인
테이블 설계
요구사항을 보고, 데이터베이스 테이블을 설계할 때, 중요하게 보아야하는 점과 사고하는 흐름이 궁금합니다!
확인
MySQL 말고 다른 SQL DB는 없을까요?
다른 SQL DB도 있는데 왜 MySQL이 가장 대중적인 SQL DB가 되었는지 궁금합니다
확인
백엔드 기술스택
부스트캠프 과정에는 자바와 스프링이 없는 것 같은데, 부캠을 진행하면서 따로 공부해야할까요?
확인
DB 외래키
확인
OAuth로 Access_token을 받은 후 어떻게 해야하는지 잘 모르겠어요
Access token까지는 발급을 했는데, 이걸 데이터베이스에 저장해놓으면 회원가입을 한걸로 생각하면 될까요?
확인
MYSQL을 사용하면서 워크벤치가 불편합니다.
쿼리문 날리고 값 확인하는 과정이 mysql 워크벤치가 너무 불편한거같습니다..테스팅과정에서 너무 불편한거같은데 추천할만한 다른 테스팅방법이있을까요? (ex 쿼리문을 날리고 확인하는 과정, session테이블 생성 등등)
확인
기술 블로그 글을 잘 쓰시는 비법이 있으실까요?
블로그 글을 보면 다른 사람이 이해하기 쉽게 글을 잘 작성하시는 편이신데, 글을 쓰실 때 팁이 있을까요? 남이 이해하기 쉽게 공부한 내용을 정리하는 것이 너무 어렵네요ㅠㅠ…
확인
원래 글을 쓰거나 정리하는 습관이 있으셨나요?
개발을 시작하면서 습관을 들이려고 하신건가요?
확인

Database

  • 왜 Database가 있는걸까?
  • 왜 MySQL을 사용하는 것일까?
  • 다른 RDBMS에는 어떤게 있을까?
  • 파일 시스템으로 해결할 수 있지 않을까?
  • 꼭 DB가 필요할까?
  • 꼭 RDBMS를 써야 할까?
  • 꼭 NoSQL을 써야 할까?
  • 이에 대해 답할 수 있으려면 어떤 지식이 필요할까?
 

NodeJS와 MySQL

 
  • NodeJS와 MySQL은 궁합이 좋지 못하다.
    • NodeJS
      • Non-blocking
      • async
      • single thread
    • MySQL
      • Blocking
      • relation
  • MySQL 같은 RDBMS는 어떤 시스템에 어울릴까?
    • Multithread
    • sync
    • blocking
  • 근데 왜 NodeJS와 MySQL을 쓰는 걸까?
  • 그럼 NodeJS는 서비스에 어울릴까?
  • 언어와 DB를 선택하는 기준
    • 언어와 DB에 서비스를 맞추는게 맞을까?
    • 서비스에 언어와 DB를 맞추는게 맞을까?

기본 명령어

  • SELECT
  • ORDER BY
  • WHERE
  • SELECT DISTINCT
  • AND
  • OR
  • IN
  • BETWEEN
  • LIKE
  • LIMIT
  • IS NULL
  • Table & Column Aliases
  • Joins
  • INNER JOIN
  • LEFT JOIN
  • RIGHT JOIN
  • Self Join
  • CROSS JOIN
  • GROUP BY
  • HAVING
  • ROLLUP
  • Subquery
  • Derived Tables
  • EXISTS
  • UNION
  • MINUS
  • INTERSECT
  • INSERT
  • Insert Multiple Rows
  • INSERT INTO SELECT
  • Insert On Duplicate Key Update
  • INSERT IGNORE
  • UPDATE
  • UPDATE JOIN
  • DELETE
  • DELETE JOIN
  • ON DELETE CASCADE
  • REPLACE
 

Table JOIN

  • sample data download
    • https://www.mysqltutorial.org/how-to-load-sample-database-into-mysql-database-server.aspx
  • 문제
    • 영국(UK)에 있는 도시에 근무하는 직원들의 이름(firstName + lastName) 출력
      • solution
        # 1 SELECT concat(firstName, lastName) as Name FROM offices o join employees e on o.officeCode = e.officeCode WHERE o.Country = 'UK'; # 2 SELECT concat(firstName, lastName) as Name FROM offices o join employees e using (officeCode) WHERE o.Country = 'UK'; # 3 SELECT concat(firstName, lastName) as Name FROM offices o natural join employees e WHERE o.Country = 'UK';
    • lastName이 'Patterson'인 직원이 담당하는 고객회사들의 이름(customerName) 출력
      • solution
        SELECT c.customerName FROM customers c Join employees e on c.salesRepEmployeeNumber = e.employeeNumber WHERE e.lastName = 'Patterson';
    • 담당 직원이 배정되지 않은 고객회사의 이름 출력
      • solution
        select c.customerName from customers c where c.salesRepEmployeeNumber is null;
    • 각 고객 회사에 대해 회사명, 주문 회수, 평균 주문 금액, 최대 주문 금액 출력
      • solution
        #1 select c.customerName, count(o.orderNumber) as 주문수, count(distinct o.orderNumber) as 주문수, round(avg(temp.OrderAmount),2) as 평균주문금액, round(max(temp.OrderAmount),2) as 최대주문금액 from ( select od.orderNumber, sum(od.quantityOrdered * od.priceEach) as OrderAmount from orderdetails od group by od.orderNumber ) temp join Orders o on temp.orderNumber = o.orderNumber join customers c on o.customerNumber = c.customerNumber group by c.customerNumber, c.customerName order by c.customerName; #2 select c.customerName, count(o.orderNumber) as 주문수, count(distinct o.orderNumber) as 주문수, round(avg(temp.OrderAmount),2) as 평균주문금액, round(max(temp.OrderAmount),2) as 최대주문금액 from ( select od.orderNumber, sum(od.quantityOrdered * od.priceEach) as OrderAmount from orderdetails od group by od.orderNumber ) temp natural join Orders o natural join customers c group by c.customerNumber, c.customerName order by c.customerName;
    • 가장 많은 주문 금액의 주문의 고객회사 명, 주문 날짜, 주문금액 출력
      • solution
        # 변수 사용 방법 set @OrderNo = (select od.orderNumber from OrderDetails od group by od.orderNumber Order By sum(od.priceEach *od.quantityOrdered) desc limit 1); set @OrderTotal = (select sum(od.priceEach *od.quantityOrdered) from orderDetails od where od.orderNumber = @OrderNo ); select @OrderNo, @OrderTotal; select concat(E.FirstName, ' ', E.LastName) as 직원이름, @OrderTotal as 주문금액, O.OrderDate as 주문날짜, C.CustomerName as 고객회사 from (Orders O join Customers C on O.customerNumber = C.customerNumber) join Employees E on C.salesRepEmployeeNumber = E.EmployeeNumber where O.OrderNumber = @OrderNo ; # 중첩 SQL 사용 select concat(E.FirstName, ' ', E.LastName) as 직원이름, (select sum(od2.quantityOrdered * od2.priceEach) from orderDetails od2 where od2.OrderNumber = o.orderNumber) as 주문금액, O.OrderDate as 주문날짜, C.CustomerName as 고객회사 from (Orders O join Customers C on O.customerNumber = C.customerNumber) join Employees E on C.salesRepEmployeeNumber = E.EmployeeNumber where o.orderNumber = ( select od1.OrderNumber from orderDetails OD1 group by Od1.OrderNumber Order by sum(od1.quantityOrdered * od1.priceEach) desc limit 1) ; # 가상테이블 사용 select concat(E.FirstName, ' ', E.LastName) as 직원이름, temp.OrderAmount as 주문금액, O.OrderDate as 주문날짜, C.CustomerName as 고객회사 from ( select od.orderNumber, sum(od.priceEach * od.quantityOrdered) as OrderAmount from OrderDetails od group by od.OrderNumber) temp join Orders o on temp.orderNumber = o.orderNumber join Customers c on o.customerNumber = c.customerNumber join Employees e on c.salesRepEmployeeNumber = e.employeeNumber order by temp.OrderAmount DESC limit 1 ; # 반환 결과가 1이상인 경우 select concat(E.FirstName, ' ', E.LastName) as 직원이름, sum(od.quantityOrdered * od.priceEach) as 주문금액, O.OrderDate as 주문날짜, C.CustomerName as 고객회사 from Orders O, Employees E, Customers C, orderDetails od where O.OrderNumber = od.OrderNumber and C.SalesRepEmployeeNumber = E.EmployeeNumber and O.CustomerNumber = C.CustomerNumber group by O.OrderNumber, E.FirstName, E.LastName, O.OrderDate, C.CustomerName having sum(od.quantityOrdered * od.priceEach) >= all ( select sum(Od.priceEach * Od.quantityOrdered) from OrderDetails OD group by Od.OrderNumber ) ;
  • 현실적으로, 위와 같은 JOIN을 작성해놨는데 변경할 일이 생긴다면 정상적으로 빠르게 작동하는 쿼리로 만들 수 있을까?

Transaction

ACID
  • Atomicity
    • 원자성
    • 트랜잭션과 관련된 일은 모두 실행되던지 모두 실행되지 않도록 하던지를 보장하는 특성이다.
  • Consistency
    • 일관성
    • 트랜잭션이 성공했다면, 데이터베이스는 그 일관성을 유지해야 한다. 일관성은 특정한 조건을 두고, 그 조건을 만족하는지를 확인하는 방식으로 검사할 수 있다.
  • Isolation
    • 독립성
    • 트랜잭션을 수행하는 도중에 다른 연산작업이 끼어들지 못하도록 한다. 임계영역을 두는 것으로 달성할 수 있다.
  • Durability
    • 성공적으로 트랜잭션이 수행되었다면, 그 결과는 완전히 반영이 되어야 한다.
    • 완전히 반영되면 로그를 남기게 되는데, 후에 이 로그를 이용해서 트랜잭션 수행전 상태로 되돌릴 수 있어야 한다. 때문에 트랜잭션은 로그저장이 완료된 시점에서 종료가 되어야 한다.

정규화

  • 어느 수준까지 정규화를 해야 할까?
  • 역정규화가 필요한 순간은?

ERD

  • 캠퍼들이 작성한 ERD 피드백

CloudERD

  • 나중에 협업할 때 써먹으면 좋다.
 

성능 관련

  • 클러스터링
    • 읽기
    • 쓰기
    • main(master)
    • sub(slave)
    • 동기화
  • 샤딩

Caching

  • 관점을 다르게 해야 한다.
  • DB를 사용하지 않는게, 접근하지 않는게 제일 좋은게 아닐까?
  • 실시간으로 데이터가 필요한 경우는 어떤 경우일까?
    • 결제 서비스
    • 주문 서비스
    • 채팅 서비스
    • 차트 서비스
  • 반대로, 실시간 데이터가 필요하지 않은 경우는 어떤 경우일까?
    • 포털 서비스
  • airbnb는 어떨까?
  • 가계부는 어떨까?