SQL: DML

김기현·2025년 6월 10일

Database

목록 보기
5/24

SQL에서 DML(Data Manipulation Language)은 데이터 조작 언어를 의미하며, 데이터베이스에 저장된 데이터를 조회, 삽입, 수정, 삭제하는데 사용하는 SQL 명령어들의 집합이다. 즉, 테이블
구조가 아니라 데이블 안의 데이터를 다루는 명령어들이다.

주요 DML 명령어

  • SELECT: 테이블에서 데이터를 조회
  • INSERT: 테이블에 새로운 데이터 삽입
  • UPDATE: 테이블의 기존 데이터를 수정
  • DELETE: 테이블의 기존 데이터를 삭제

예제

SELECT

SELECT *
FROM users;
SELECT name
FROM users
WHERE age = 20; -- 이처럼 조건을 붙여 조회할 수도 있다.

INSERT

-- users 테이블에 한 명의 데이터를 추가한다
INSERT INTO users (name, age)
VALUES ('김기현', 24);

UPDATE

UPDATE users
SET age = age + 1;

모든 유저의 나이를 1 더한다.

DELETE

DELETE
FROM users
WHERE name = '김기현';

이름이 김기현인 유저를 삭제한다.


특징

특징설명
트랜잭션 가능DML문은 COMMIT / ROLEBACK으로 작업을 확정하거나 취소할 수 있다
WHERE 절이 중요하다UPDATEDELETE에서 WHERE 절을 빼면 전체 데이터가 수정 또는 삭제될 수 있으므로 주의해야 한다.
테이블 구조를 변경하지 않는다테이블의 구조를 변경하는 것은 DDL이다.

SELECT

SELECT문이 SQL에서 가장 중요하다고 여겨진다. 그 이유는 다음과 같은 이유가 있다.

1. 데이터 분석·조회의 중심

  • 대부분의 실무에서 가장 자주 쓰이는 SQL문은 데이터를 읽는 SQL이다.
  • 데이터를 수정, 삽입, 삭제하기 전에 항상 어떤 데이터가 있는지 SELECT로 먼저 확인해야 한다.

SELECT는 읽기 전용 작업의 핵심 도구이며, 데이터 기반 의사결정의 시작점이다.

2. 복잡한 데이터 추출 가능

SELECT는 단순 조회만 아니라 조건검색, 정렬, 집계, 그룹화, 조인, 서브쿼리, 윈도우 함수 등 다양한 기능을 제공한다.

SELECT t.name, COUNT(u.id) AS team_count
FROM team t
         JOIN users u ON t.id = u.team_id
GROUP BY t.name
ORDER BY team_count DESC;

위처럼 여러 테이블을 연결하고, 통계를 내고, 정렬하는 복잡한 분석도 모두 SELECT에서 수행한다.

3. 비파괴적이고 안전하다

  • SELECT는 데이터를 변경하지 않기 때문에 실수로 데이터를 잃을 위험이 없다.
  • 반면 DELETE, UPDATE는 잘못 사용하면 복구 불가능한 실수를 할 수 있다.

4. 백앤드와 프론트앤드의 연결고리

  • 웹 또는 앱에서 사용자의 요청에 따라 DB에서 정보를 가져와 보여주는 경우가 대부분이다.
  • 사용자의 로그인 정보, 게시글 목록, 상품 검색 결과 등은 모두 SELECT로 조회된다.

5. 쿼리 최적화

  • DB 성능 최적화의 대부분은 SELECT 쿼리 튜닝이다.
  • 잘못된 SELECT는 성능 저하를 일으키고, 애플리케이션에 영향을 준다.

INSERT

데이터베이스에 새로운 데이터를 추가할 때 사용되는 언어이며, 실무와 시스템 설계에서 INSERT문이 중요한 점은 단순히 데이터를 넣는 것 이상으로 다양한 측면에서 영향을 주기 때문이다.

1. 데이터 흐름의 시작점

  • 데이터베이스에서 어떤 분석, 검색, 수정, 삭제 작업도 먼저 데이터가 있어야 의미가 있다.
  • 이 데이터를 만드는 최초의 시점이 바로 INSERT이다.

삽입이 없으면 그 이후의 작업도 없다는 점에서 매우 중요하다.

2. 부결성과 제약조건을 처음으로 적용

데이터 삽입 시 아래와 같은 제약조건들이 처름으로 검증된다.

  • NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY
  • 데이터 타입, 기본 값

잘못된 데이터가 삽입되지 않도록 첫 관문 역할을 한다.

-- 만약 중복된 값이 있다면 에러가 발생한다.
INSERT INTO users (email)
VALUES ('rlarlgus0206@naver.com');

3. 보안과 권한 관리의 시작점

  • 어떤 데이터를 누가, 언제, 어떻게 넣었는지는 시스템 보안/감시의 핵심이다.
  • 로그 테이블이나 이력 테이블에 INSERT로 기록을 남겨야 추척이 가능해진다.
INSERT INTO login_logs (user_id, login_time)
VALUES (1, NOW());

4. 대랭 삽입(Bulk Insert)과 성능

시스템 초기화, 마이그래이션, 외부 데이터 수집 등에서 수십만 건의 대량 INSERT가 발생한다. 그리고 아래와 같은 부분에서 문제가 발생할 수 있다.

성능 부하: 성능 설계

수만 건의 데이터를 한 번에 삽입할 때 CPU, 메모리, 디스크, I/O 부하가 급격히 올라간다.
예를 들어 100만 건을 삽입하면 DB 서버가 느려지거나 애플리케이션 타임 아웃 그리고 다른 쿼리들이 느려지는 문제가 발생할 수 있다.
이를 해결하게 위해 삽입을 batch로 나누거나 비동기 큐, 백그라운드 작업 처리 시스템을 도입해야 한다.

트랜잭션 처리: 데이터 일관성

많은 INSERT를 하나의 트랜잭션으로 처리하면 중간에 실패시 롤백 비용이 크고, 장시간 트랜잭션은 락을 오래 점유해서 다른 작업을 방해한다.
따라서 적절한 단위로 나눠서 커밋하거나, 중간 실패 대비 부분 커밋/재시도 로직이 필요하다.

인덱스 부하: DB 구조 설계

INSERT를 할 때마다 인덱스를 동시에 업데이트 해야하기 때문에 대량으로 삽입할 시 인덱스가 많으면 속도가 급감할 수 있다.
따라서 대량 삽입 전 인덱스를 일시 비활성화 하거나, 데이터 입력 후 인덱스를 다시 생성해야 한다.

무결성 제약 조건: 데이터 정확성

FOREIGN KEY, UNIQUE, NOT NULL같은 제약조건이 대량 데이터에 동시에 검사되며 제약 조건 출돌로 삽입 실패 가능성이 올라간다. 이를 해결하려면 입력 전 데이터를 정제하거나, 임시
staging 테이블에 넣고 검증 후 본 테이블로 이동하는 작업이 필요하다.

로그/트리거 과다 발생: 리소스/운영

DB마다 십입 시 로그 기록, 트리거 실행이 있는데 대량으로 삽입할 때 로그가 폭발적으로 늘어나고 이느 디스크 공간 부족으로 이어지며 마스터-슬레이브 구조의 데이터베이스 복제를 지연시킨다.
이를 해결하려면 트리거를 최소화하거나 외부 처리 시스템으로 옮겨야 하고, 심도있게 고민하고 취할 수 있는 방법은 트리거/로그를 비활성화 하는 것이다(어지간하면 할 일은 없을 것이다).

시스템 전체 설계 관점

대량 삽입은 단순 쿼리 한 줄 문제가 아니라, 시스템 전체 구조를 고려한 설계가 필요하다.

  • 데이터 흐름을 어떻게 처리할 것인가
  • 백업과 복구 전략
  • 삽입 중 실패한 경우 어떻게 되돌릴 것인가
  • 삽입 후 어떤 비즈니스 로직이 연동되는가

UPDATE

기존에 저장된 데이터를 수정하는데 사용되는 DML이며, 실무와 시스템 설계 측면에서 UPDATE는 데이터 무결성, 시스템 신뢰성, 성능, 보안 등에 배우 중요한 영향을 준다.

1. 실시간 데이터의 정확성과 무결성 유지

  • 시스템의 상태 변과, 비즈니스 흐름을 반영할 때 반드시 UPDATE가 필요하다.
    • ex) 사용자 로그인 시간 기록 -> UPDATE users SET last_login = NOW();

시스테므이 상태가 정확하게 유지되기 위해 UPDATE는 중요한 도구이다.

2. 실수 시 시스템 전체에 영향을 줄 수 있다

WHERE 조건 없이 UPDATE를 사용하면 전체 데이터가 잘못 수정될 위험이 있다.

UPDATE users
SET name = '김기현'

데이터 보호 및 정확성 유지를 위해 UPDATE신중하게 조건절을 사용해야 한다.

3. 트랜잭션 처리와 데이터 일관성에 필수

  • 여러 테이블의 상태를 동기화할 때 원자성이 필요하다.
  • UPDATE는 트랜잭션 내에서 자주 사용되며, 일관된 상태를 만들기 위해 꼭 필요하다.
BEGIN;
UPDATE users SET age = age + 1 WHERE id = 1;
UPDATE users SET age = age - 1 WHERE id = 2;
COMMIT;

이런 방식으로 시스템은 절대 중간 상태를 남기지 않고 일관성을 보장한다.

4. 비즈니스 로직의 핵심 수행 수단

많은 시스템 로직이 단순 조회 뿐만 아니라 상태 변경에 집중된다. 이때 상태 변화를 수행하는 주요 수단이 UPDATE이다.

5. 감시 및 변경 이력 관리 필요

  • 중요한 데이터를 변경할 때 무엇이 어떻게 바뀌었는지 추적할 수 있어야 한다.
  • 예를 들어 유저 등급, 상품 가격 등 민감한 정보가 바뀔 경우, UPDATE로 인해 시스템이 오작동할 수 있다.
    • 따라서 BEFORE UPDATE트리거로 변경 전 데이터를 백업한다.
    • 또는 변경 이력 테이블을 사용한다.(update_logs 등)

6. 성능에 영향을 미칠 수 있는 연산

UPDATE는 단순한 값 수정 이상의 비용을 가질 수 있다. 따라서 성능이 중요한 시스템에서는 UPDATE도 반드시 쿼리 튜닝 대상이 된다.

  • 인덱스가 걸린 컬럼을 변경하려면 인덱스를 재작성해야 한다.
  • 트리거가 실행된다.
  • 복제 로그가 기록된다.
  • 대량 업데이트는 락과 I/O를 유발한다.

7. 조건 분기 처리나 복잡한 계산 가능

단순한 값 변경 뿐만 아니라 계산이나 조건에 따라 값을 수정할 수도 있다.

UPDATE users
SET age = age * 2
WHERE name = '김기현';

계산, 조건 분기, 날짜 변경 등 복잡한 비즈니스 로직을 처리하는 데 필수적이다.

실무 팁

설명
WHERE절 확인UPDATE에 적용하기 전에 SELECT로 먼저 조건을 검증한다.
트랜잭션 사용여러 건 변경 시 BEGIN ~ COMMIT 사용
백업 또는 이력 기록중요한 컬럼은 변경 전 기록 남기기
인덱스 고려WHERE조건이나 SET컬럼에 인덱스가 있으면 성능 영향이 크다
트리거 확인자동 실행되는 트리거나 제약 조건이 있는지 사전에 확인한다

DELETE

데이터베이스에서 기존의 데이터를 삭제할 때 사용된다. 데이터 무결성, 보안, 시스템 안정성에 매우 깊이 연관되어 있으며, 실무에서 가장 조심스럽게 다뤄야하는 명령어 중 하나이다.

1. 데이터를 영구히 제거하는 명령어

  • DELETE는 실제 데이터 행을 제거한다.
  • 삽입, 수정과 달리 한 번 실행하면 되돌릴 수 없다.
  • 실수로 잘못 사용하면 중요한 데이터를 완전히 잃어버릴 수 있다.

실무에서는 DELETE명령을 바로 실행하기보다는 백업, 트랜잭션, 보안 점검 후 실행해야 한다.

2. WHERE 절 없이 사용하면 전부 삭제된다

DELETE FROM users; -- 끔찍한 결과를 초래할 것
  • DELETE에서 WHERE 절을 생략하면 테이블 전체가 삭제되며, 재앙을 불러올 것이다.
  • 실수 방지를 위해 많은 기업은 DELETE 금지 정책이나 논리 삭제 방식을 사용한다.

3. 데이터 무결성에 중대한 영향을 준다

  • 왜래 키가 걸린 데이터를 삭제하면 연관 테이블이 깨질 수 있다.
    • ex) team을 삭제했는데 user에게 team_id가 남아있으면 무결성 오류가 발생한다.
  • 이를 해결하기 위해서 ON DELETE CASCAGE 또는 ON DELETE SET NULL 등을 명확하게 명시해 영향을 제어해야 한다.

4. 논리 삭제와 물리 삭제의 분기점

설명논리 삭제물리 삭제
특징is_deleted = true같은 플래그만 설정한다실제 행을 DELETE로 제거한다
장점복구 가능하며 이력 관리가 쉽다공간이 절약되며, 쿼리가 간단하다
단점DB 용량이 증가하고, 쿼리 복잡도가 증가한다복구가 불가능하고, 감시/추적이 어렵다

이러한 전략 선택이 DELETE핵심 설계 포인트이다.

5. 보안 및 개인 정보 보호에 직결

  • 개인정보 보호법, GDPR 등 규제에 따라 사용자 요청 시 완전 삭제가 요구되기도 한다.
  • 이때 DELETE는 법적 책임을 완수하는 핵심 역할을 한다.
DELETE FROM users WHERE id = 1 AND consent_to_date_storage = false;

잘못된 삭제는 법적 리스크로 이어질 수 있다.

6. 성능 및 트랜잭션 측면 고려 필요

  • 대량의 DELETE는 테이블 락, 인덱스 업데이트, 복제 지연 등을 유발한다.
  • MySQL(InnoDB)에서는 DELETE가 undo log에 기록되어 롤백 가능하긴 하지만, 성능에 큰 부담을 줄 수 있다.
  • 따라서 DELETE를 조건을 나눠서 여러 번 실행하거나 TRUNCATE, PARTITION DROP등 더 효율적인 대안을 사용한다.

7. 트리거 또는 감시 로그와 연동 가능

중요 테이블에서 DELETE가 일어날 경우 아래와 같은 후처리를 해주면 좋다.

  • 감시 로그 남기기
  • 다른 테이블에서 관련 데이터 정리
  • 사용자에게 알림 전송
-- 트리거
CREATE TRIGGER log_delete
BEFORE DELETE ON users
FOR EACH ROW 
INSERT INTO delete_logs(user_id, deleted_at) VALUES (OLD.id, NOW());
profile
백엔드 개발자를 목표로 공부하는 대학생

0개의 댓글