[CS/데이터베이스] SQL 핸들링 및 현대적 데이터 전략

선우·2025년 12월 25일

CS

목록 보기
10/20

[CS/데이터베이스] 02. SQL 핸들링 및 현대적 데이터 전략

⚡ 한 줄 요약: SQL의 정밀한 CRUD 연산과 조인(JOIN), 페이징 기법을 통해 대규모 데이터를 효율적으로 제어하고, 서비스 성격에 맞는 NoSQL 도입 기준을 확립합니다.

1. 👋 들어가며: 쿼리는 단순한 명령어가 아니라 '전략'입니다.

지난 포스팅에서 데이터베이스의 설계를 다뤘다면, 이제는 그 설계된 데이터에 생명력을 불어넣을 차례입니다.

  • 🧐 Why:

    • SELECT 같은 기초 문법은 쉽지만, 이를 대규모 트래픽 환경에서 안전하고 성능 지향적으로 사용하는 법을 알아야 하기 때문입니다.
  • 🎯 Goal:

    • 실무 SQL의 디테일(정밀 삭제, 서브쿼리, 조인)을 마스터하고,
      페이징 성능 최적화와 NoSQL의 적재적소 활용법을 익힙니다.

📂 2. SQL 다루기

📌 2-1. SQL의 기본 정의와 조회 (SELECT)

SQL(Structured Query Language)은 관계형 데이터베이스에서 데이터를 조작하고 관리하기 위해 사용하는 표준 언어입니다.

개발자가 DB와 대화하기 위한 '공통 언어'라고 이해하면 됩니다.

가장 많이 사용하는 조회(SELECT) 기능의 핵심 포인트는 다음과 같습니다:

  • 전체 컬럼 조회:

    • 테이블의 모든 데이터를 한눈에 확인하고 싶을 때는 * (Asterisk) 키워드를 사용합니다.
    • 예:
      SELECT * FROM users;
  • 특정 컬럼 필터링:

    • 필요한 데이터(예: 이름, 이메일)만 콕 집어서 가져올 수 있습니다.
    • 예:
      SELECT name, email FROM users;
  • 조건 및 정렬:

    • WHERE 절로 특정 조건의 데이터만 필터링하거나, ORDER BY를 통해 오름차순(ASC) 또는 내림차순(DESC)으로 정렬할 수 있습니다.

📌 2-2. 데이터 조작의 핵심: INSERT, UPDATE, DELETE

데이터베이스의 상태를 변화시키는 작업들로, 실무에서는 CRUD라고 부르는 연산의 핵심입니다.

  • INSERT (Create): 새로운 데이터를 추가합니다.

    • 예:
      INSERT INTO users (name, email) VALUES ('가나다', 'abcd@example.com');
  • UPDATE (Update): 기존 데이터를 수정합니다.

    • 반드시 WHERE 절과 함께 사용하여 엉뚱한 데이터가 수정되지 않도록 주의해야 합니다.
  • DELETE (Delete): 데이터를 삭제합니다.

    • 전체 삭제: DELETE FROM users;
    • 정밀 삭제:
      • ORDER BYLIMIT 키워드를 조합하면 특정 기준에 부합하는 데이터 일부만 삭제할 수 있습니다.
    • 예: (가장 오래된 주문 1개만 삭제)
      DELETE FROM orders ORDER BY order_date ASC LIMIT 1;

📌 2-3. 헷갈리기 쉬운 포인트 / 오해 정리

  • GROUP BY의 제약

    • WHEREORDER BY는 수정/삭제/조회 등 다양한 상황에서 쓰이지만, 데이터를 그룹화하는 GROUP BY는 오직 조회(SELECT) 상황에서만 사용됩니다.
  • WHERE절의 중요성

    • UPDATEDELETE 실행 시 WHERE 절을 빠뜨리면 테이블 전체 데이터가 변경되거나 삭제되는 대참사가 일어날 수 있으니 항상 확인이 필요합니다.

📌 2-4. 한 줄 정리

  • SQL은 데이터의 CRUD를 위한 언어로, 특히 ORDER BYLIMIT을 활용하면 정밀한 데이터 타겟팅이 가능해집니다.

📂 3. SQL 고급

📌 3-1. 집계 함수 (COUNT, SUM, AVG, MAX, MIN)

집계 함수는 말 그대로 여러 행의 데이터를 모아 하나의 결과(통계치)를 만들어내는 함수입니다.
데이터를 집계하기 위해 사용되므로 주로 SELECT 키워드와 함께 사용됩니다.

  • COUNT() - 데이터 개수 구하기

    • 특정 컬럼이나 테이블의 총 데이터 개수를 구합니다.
    • NULL 값은 자동으로 제외됩니다.
  • SUM() - 합계 구하기

    • 특정 컬럼의 총합을 계산하며, NULL 값은 제외됩니다.
  • AVG() - 평균 구하기

    • 산술 평균을 구합니다.
    • 이때도, NULL 값은 계산에서 빠집니다.
  • MAX() / MIN() - 최댓값/최솟값 구하기

    • 특정 컬럼의 가장 큰 값 혹은 작은 값을 찾을 때 유용합니다.

집계 함수를 단독으로 쓰면 결과가 숫자 하나로 딱 떨어지지만,
뒤에 나올 GROUP BY와 섞어 쓰면 멋진 테이블 형태로 결과를 얻을 수 있습니다.

💡 비유로 이해하기

전교생의 성적표가 쌓여 있을 때, "전체 평균은?"이라고 물으면 숫자 하나가 나옵니다. (단독 사용)
하지만 "반별로 평균은?"이라고 물으면 각 반과 그에 맞는 숫자가 나열된 표가 필요하게 됩니다. (GROUP BY 사용)

📌 3-2. 헷갈리기 쉬운 포인트 / 오해 정리

  • NULL의 마법

    • 대부분의 집계 함수는 NULL을 무시합니다.
    • 하지만 AVG() 계산 시 NULL 행 자체를 모수(나누는 수)에서 제외할지, 아니면 0으로 치환해서 계산할지에 따라 결괏값이 달라질 수 있다는 점을 유의해야 합니다.
  • GROUP BY의 위치

    • 집계 함수는 GROUP BY와 함께 쓸 때 비로소 강력해집니다.
    • 그룹화하지 않고 특정 컬럼과 집계 함수를 동시에 SELECT하면 에러가 발생하거나 의도치 않은 행이 조회될 수 있습니다.

📌 3-3. 한 줄 정리

  • 집계 함수는 통계를 내기 위해 SELECT와 함께 쓰이며, GROUP BY 사용 시 그룹 기준 컬럼은 반드시 SELECT 절에 명시해야 합니다.

📂 4. 서브쿼리

📌 4-1. 서브쿼리

서브쿼리는 SQL문 내부에 포함된 또 다른 SQL문을 의미합니다.

메인 쿼리에서 필요한 값을 동적으로 가져와야 할 때 주로 사용하며, 실행 결과에 따라 메인 쿼리의 조건이나 데이터가 결정됩니다.

서브쿼리는 위치에 따라 크게 세 가지 용도로 나뉩니다:

  1. WHERE 절에서 사용: 특정 값을 동적으로 조건 설정할 때 씁니다.

    • 예: 급여가 가장 높은 직원을 찾을 때, 먼저 SELECT MAX(salary)로 최고 급여액을 구한 뒤 이를 조건으로 사용합니다.
  2. FROM 절에서 사용: 서브쿼리 자체를 하나의 임시 테이블처럼 사용합니다.

    • 이때 가장 중요한 원칙은 서브쿼리에 반드시 별칭(Alias)를 붙여 테이블 이름을 정의해야 한다는 점입니다.
    • 만약 이름을 붙이지 않고 생략하면 대부분의 데이터베이스에서 문법 오류를 뱉어내니 주의하세요.
  3. SELECT 절에서 사용: 특정 컬럼 값을 동적으로 계산하여 가져올 때 사용합니다.

    • 예:
      SELECT NAME
           , SALARY
           , (
                  SELECT	AVG(SALARY)
                    FROM	EMPLOYEES
                   WHERE	DEPARTMENT = E.DEPARTMENT
             ) AS DEPT_AVG_SALARY
        FROM EMPLOYEES E;

📌 4-2. 헷갈리기 쉬운 포인트 / 오해 정리

  • 서브쿼리 vs JOIN
    • 둘 다 여러 데이터를 결합하지만 결이 다릅니다.
    • 서브쿼리는 '결과를 필터링하거나 계산하기 위한 도구'에 가깝고,
      JOIN은 '테이블 간의 관계를 맺어 수평적으로 확장하는 것'에 가깝습니다.

📌 4-3. 한 줄 정리

  • 서브쿼리는 SQL 내의 SQL로 동적 값을 만들 때 사용하며, 특히 FROM 절 사용 시 별칭부여는 문법상 필수입니다.

📂 5. 조인(JOIN)

📌 5-1. 조인(JOIN)의 정의와 필요성

조인은 두 개 이상의 테이블을 결합하여 데이터를 조회하는 방법입니다.

실제 실무에서는 데이터 중복을 최소화하고 효율적으로 관리하기 위해 정보를 여러 테이블에 나누어 저장하는데, 이를 다시 연결해서 보고 싶을 때 조인을 사용합니다.

  • 연결 고리: 일반적으로 두 테이블 사이의 기본 키(PK)외래 키(FK)를 이용해 연결합니다.
  • 효율성: 중복 데이터를 줄이면서도 필요한 시점에 데이터를 합쳐볼 수 있게 해줍니다.

📌 5-2. 조인의 종류와 특징

조인 종류설명데이터 포함 범위
INNER JOIN두 테이블에서 공통된 데이터만 반환합니다.교집합
LEFT JOIN왼쪽 테이블의 모든 데이터와 오른쪽의 일치하는 데이터를 반환합니다.왼쪽 기준(없으면 NULL)
RIGHT JOIN오른쪽 테이블의 모든 데이터와 왼쪽의 일치하는 데이터를 반환합니다.오른쪽 기준(없으면 NULL)
FULL JOIN두 테이블의 모든 데이터를 포함합니다.합집합

1) INNER JOIN (교집합)
가장 기본이 되는 조인으로, 양쪽 테이블에 모두 값이 존재하는 데이터만 가져옵니다.

  • 특징: 조건에 일치하지 않는 행은 결과에서 완전히 제외됩니다.
  • 예시:
    • 주문 내역에 있는 회원만 보고 싶을 때 사용합니다.
    • 주문하지 않은 회원은 목록에 나오지 않습니다.

2) LEFT JOIN (왼쪽 기준)
왼쪽 테이블(주로 기준이 되는 테이블)의 데이터는 무조건 다 보여주고, 오른쪽 테이블에 매칭되는 값이 없으면 NULL로 표시합니다.


  • 특징: LEFT OUTER JOIN 이라고도 부릅니다.
  • 예시:
    • 전체 회원 목록과 각 회원의 주문 내역을 함께 보고 싶을 때 씁니다.
    • 주문을 한 번도 안한 '이영희' 회원도 목록에 나오되, 주문 정보만 NULL로 표시됩니다.

3) RIGHT JOIN (오른쪽 기준)
LEFT JOIN과 반대로 오른쪽 테이블을 기준으로 데이터를 가져옵니다.

  • 특징: 실무에서는 가독성을 위해 테이블 순서를 바꾸어 LEFT JOIN으로 쓰는 경우가 더많습니다.
  • 예시:
    • 모든 주문 내역을 보여주되, 해당 주문을 한 회원 정보를 붙입니다.
    • 회원 정보가 없는 주문(그럴일은 드물겠지만)도 주문 데이터는 살아남습니다.

📌 5-3. 헷갈리기 쉬운 포인트 / 오해 정리

  • OUTER 키워드

    • LEFT JOIN은 사실 LEFT OUTER JOIN의 줄임말입니다.
    • OUTER를 생략해도 결과는 같습니다.
  • NULL의 의미

    • LEFT JOIN 결과에서 NULL이 보인다면, 그것은 "데이터가 잘못된 것"이 아니라 "기준 테이블에는 데이터가 있지만 연결된 테이블에는 해당 값이 없음"을 의미하는 정상적인 결과입니다.

📌 5-4. 한 줄 정리

  • 조인은 테이블 간의 관계를 이용해 데이터를 합치는 기술로, 공통 데이터만 뽑는 INNER JOIN과 기준 테이블 전체를 살리는 OUTER JOIN이 핵심입니다.

📂 6. 페이징

📌 6-1. 페이징

페이징이란 대량의 데이터를 한꺼번에 불러오는 것이 아니라, 사용자가 보기 편하도록 일정한 단위(페이지)로 나누어 조회하는 기법을 말합니다.

우리가 인터넷 쇼핑을 할 때 수만 개의 상품이 한 페이지에 다 나오는 것이 아니라 1페이지, 2페이지로 나누어 보이는 것이나, 블로그의 게시글 목록이 정해진 개수만큼 노출되는 것이 모두 이 페이징 기술을 사용한 사례입니다.

  • 핵심 목적:

    • 데이터가 너무 많을 때 한꺼번에 띄우면 시스템이 느려지거나 화면이 복잡해지기 때문에,
      필요한 만큼만 적당히 나눠 보여줌으로써 성능을 최적화하는 데 있습니다.
  • 구현 키워드:

    • SQL에서는 보통 LIMITOFFSET을 조합하여 특정 범위의 데이터를 가져옵니다.
      • OFFSET: 조회를 시작할 위치를 지정합니다. (0부터 시작)
      • LIMIT: 조회할 데이터의 개수를 지정합니다.

페이징 쿼리 예시

  • 1페이지 (1 ~ 10번째)

    SELECT * FROM users LIMIT 10 OFFSET 0;
  • 3페이지 (21 ~ 30번째)

    SELECT * FROM users LIMIT 10 OFFSET 20;

📌 6-2. 페이징 성능 이슈와 최적화

단순히 OFFSET을 쓰면 다 해결될 것 같지만, 실무에서는 아주 큰 함정이 하나 있습니다.
바로 데이터베이스가 데이터를 읽는 방식 때문입니다.

데이터베이스는 OFFSET으로 지정한 위치까지의 데이터를 내부적으로 모두 읽고 나서 그 다음 LIMIT만큼을 반환합니다.

예를 들어 1,000번째 데이터를 보려면 DB는 내부적으로 0번째부터 999번째 데이터까지 쭉 스캔하는 과정을 거쳐야만 합니다.

결국 데이터 양이 많아질수록 OFFSET 값이 커지면 조회 속도는 눈에 띄게 느려질 수 밖에 없습니다.

💻 참고

실무에서는 이런 성능 저하를 막기 위해 OFFSET 대신 인덱스 기반 방식(No-offset)을 더 선호합니다.

마지막으로 읽은 데이터의 ID 값을 기준으로 다음 데이터를 조회하는 방식인데, 특히 프론트엔드에서 '무한 스크롤'을 구현할 때 백엔드와 이 방식을 논의하며 훨씬 전문적인 인상을 줄 수 있습니다.

📌 6-3. 헷갈리기 쉬운 포인트 / 오해 정리

  • 사용자 편의 vs 시스템 성능

    • 페이징은 사용자에게 정보를 잘 보여주기 위한 도구이기도 하지만, 본질적으로는 DB 서버와 네트워크의 부하를 줄이기 위한 생존 전략에 가깝습니다.
  • LIMIT과 OFFSET의 순서

    • SQL 문법상 LIMIT을 먼저 쓰고 OFFSET을 나중에 씁니다.
    • 헷갈리기 쉽지만, "몇 개(LIMIT)를 가져올 건데, 어디서부터(OFFSET)?"라고 기억하면 편합니다.

📌 6-4. 한 줄 정리

  • 페이징은 시스템 부하를 줄이기 위해 데이터를 나누어 조회하는 기법이며,
    대규모 서비스에서는 성능을 위해 OFFSET보다 인덱스 기반 조회를 권장합니다.

📂 7. NoSQL

📌 7-1. NoSQL (Not Only SQL)의 정의와 등장 배경

NoSQL은 'Not Only SQL'의 약자로, 정해진 테이블 구조(스키마) 없이 데이터를 자유로운 형태로 저장하고 관리하는 방식입니다.

과거에는 데이터의 정합성이 최우선이었지만, 이제는 빅데이터 처리, 높은 확장성, 빠른 데이터 접근이 더 중요한 시대가 되었죠.

특히 다음과 같은 대규모 트래픽 환경에서 NoSQL은 진가를 발휘합니다:

  • 실시간 채팅 및 SNS:

    • 빠르게 양산되는 이미지와 텍스트 데이터를 처리할 때 유리합니다.
  • 로그 저장:

    • 방대한 양의 비정형 데이터를 실시간으로 쌓아야 하는 경우에 적합합니다.
  • 캐시 서버:

    • 빠른 응답 속도가 생명인 시스템에서 데이터를 임시 저장하는 용도로 쓰입니다.

중요한 점은 NoSQL이 RDBMS를 대체하는 것이 아니라는 겁니다.
RDBMS의 강력한 정합성 장점은 여전히 유효하기 때문에,
실무에서는 두 시스템의 장점을 결합한 혼합 구조를 선택하는 경우가 더 많습니다.

💻 참고

흔히 접하는 Firebase나 캐싱을 위한 Redis가 대표적인 NoSQL입니다.

실무에서는 정형화된 유저 정보는 MySQL에, 실시간 알림이나 복잡한 게시글 메타데이터는 NoSQL에 나누어 담는 전략을 자주 사용하니 이 '조합'의 이유를 아는 것이 중요합니다.

📌 7-2. NoSQL의 다양한 데이터 모델

NoSQL은 데이터의 형태에 따라 여러 가지 모델을 지원합니다.

  1. Key-Value 모델

    • 가장 단순한 형태로, 하나의 키(Key)에 하나의 값(Value)을 저장합니다.
    • 대표 기술: Redis, DynamoDB
  2. Document 모델

    • 키-값 모델을 확장하여 키 하나에 JSON 같은 구조화된 문서를 통째로 저장합니다.
    • 대표 기술: MongoDB, CouchDB
  3. Column 모델

    • 하나의 키에 여러 개의 컬럼 이름과 값의 쌍을 저장하는 구조입니다.
    • 대표 기술: BigTable, HBase, Cassandra

💡 비유로 이해하기

RDBMS가 칸이 딱딱 나누어진 '서류 보관함'이라면, NoSQL은 내용물을 자유롭게 담을 수 있는 '커다란 바구니'와 같습니다.

보관함은 찾기엔 정확하지만 담을 때 형식을 맞춰야 하고, 바구니는 아무거나 빠르게 던져 놓기 좋습니다.

📌 7-3. 헷갈리기 쉬운 포인트 / 오해 정리

  • NoSQL은 SQL을 안 쓴다?

    • 이름 그대로 `Not Only'입니다.
    • 요즘은 NoSQL에서도 SQL과 유사한 쿼리 언어를 지원하는 경우가 많아지고 있습니다.
  • NoSQL이 무조건 빠르다?

    • 단순 조회는 빠를 수 있지만, 여러 데이터를 조합하거나 복잡한 연산이 필요한 경우에는 RDBMS가 더 효율적일 때도 있습니다.

📌 7-4. 한 줄 정리

  • NoSQL은 고정된 스키마 없이 비정형 데이터를 빠르게 처리하며 대규모 시스템의 성능과 확장성을 책임지는 데이터베이스입니다.

🎁 8. 정리

🔑 요약

  • 안전한 데이터 제어

    • 모든 컬럼을 확인할 때는 SELECT *를 활용하되, UPDATEDELETE 시에는 WHERE 만으로 안심하지 마세요.
  • 데이터 결합의 미학

    • 수평적 확장을 원할 때는 JOIN을, 동적인 필터링이나 개선이 필요할 때는 서브쿼리를 선택하세요.
  • 성능 최적화의 핵심, 페이징

    • 단순한 OFFSET 방식은 데이터가 많아질수록 읽기 속도가 기하급수적으로 느려집니다.
    • 실무, 특히 무한 스크롤 환경에서는 마지막 조회 ID를 기준으로 조회하는 인덱스 기반 전략을 고려해 봐야 합니다.
  • NoSQL

    • 모든 데이터를 억지로 칸이 나누어진 RDBMS에 넣을 필요는 없습니다.
    • 실시간 알림이나 로그처럼 빠른 확장이 필요한 데이터는 NoSQL에 담는 하이브리드 전략이 현대적 아키텍처의 정석입니다.

0개의 댓글