WEB-BE-04 · 데이터 무결성·성능·보안

데이터 저장은 값 하나를 파일에 쓰는 일보다 넓습니다. 관련된 변경이 함께 성공해야 하고, 여러 요청이 동시에 들어와도 규칙이 깨지지 않아야 하며, 필요한 데이터를 적절한 시간 안에 찾고 실패 뒤 복구할 수 있어야 합니다.

트랜잭션과 동시성

트랜잭션은 관련된 여러 데이터 변경을 하나의 작업 단위로 묶습니다. 모든 변경이 성공하면 COMMIT하고 중간에 실패하면 ROLLBACK해 일부 변경만 남는 일을 막습니다.

함께 성공하거나 함께 취소할 변경
BEGIN;
UPDATE review_cases SET status = 'completed' WHERE id = ?;
INSERT INTO review_events (case_id, action) VALUES (?, 'completed');
COMMIT;

두 사용자가 같은 데이터를 동시에 바꿀 수 있으면 마지막 저장이 앞선 변경을 덮거나 중복 처리가 생길 수 있습니다. 데이터베이스의 잠금, 고유 제약, 현재 상태를 포함한 조건부 변경과 요청 ID 중 필요한 가장 작은 방법을 선택합니다. 모든 수정 화면이 장시간 독점 잠금을 잡아야 하는 것은 아닙니다.

조회 성능과 데이터 보존

개념역할주의할 점
인덱스특정 열의 값을 빠르게 찾도록 도움저장 비용과 공간이 늘므로 실제 조회 조건에 맞춰 추가
캐시자주 쓰는 결과를 더 가까운 곳에 임시 보관오래된 값, 만료와 무효화 기준 필요
백업장애·오작동 뒤 데이터를 복구할 사본백업 생성뿐 아니라 실제 복원 시험 필요

느리다는 추측만으로 인덱스나 캐시를 추가하지 않습니다. 먼저 어떤 요청과 SQL이 느린지 측정하고 쿼리 계획을 확인합니다. 캐시는 데이터베이스를 대신하는 영구 저장소로 취급하지 않습니다.

SQL 인젝션 막기

사용자 입력을 SQL 문자열에 직접 이어 붙이면 입력이 데이터가 아니라 SQL 코드로 실행될 수 있습니다. 입력에서 위험해 보이는 글자를 지우는 방식에 의존하지 않고 매개변수화 쿼리로 코드와 값을 분리합니다.

Python sqlite3 매개변수화 쿼리
cursor.execute(
    "SELECT id, content FROM memos WHERE user_id = ?",
    (user_id,),
)

테이블명이나 정렬 방향처럼 매개변수로 전달할 수 없는 구조는 서버가 정한 허용 목록에서 선택합니다. 데이터베이스 계정과 애플리케이션 권한도 필요한 범위로 제한해 문제가 생겼을 때의 영향을 줄입니다.

변경 전에 확인할 내용

  • 여러 변경 중 하나가 실패하면 이전 변경도 취소되는가
  • 중복 요청과 동시 변경에도 고유값과 업무 상태가 유지되는가
  • SQL 값이 문자열 결합이 아니라 매개변수로 전달되는가
  • 인덱스와 캐시는 측정한 병목을 해결하는가
  • 백업에서 필요한 데이터를 실제로 복원할 수 있는가

3-01 · 담당자 검토 이력과 권한 저장하기에서는 이전 기록을 덮어쓰지 않고 요청 ID로 중복 저장을 막습니다.

공식 근거