콘텐츠로 이동

관계형 데이터베이스는 어떤 문제를 맡는가

데이터를 저장하는 방법은 많은데, 주문·결제·회원 정보에 관계형 데이터베이스를 먼저 쓰는 이유는 무엇일까요?

예상 읽기 시간 6분 · 핵심 질문: 파일 저장으로 충분하지 않은 순간은 언제인가

파일에도 데이터를 남길 수 있다. 한 프로그램이 설정을 한 번 쓰고 다시 읽는 정도라면 파일이 더 단순하다. 그런데 두 사용자가 마지막 재고를 동시에 주문하고, 저장 도중 서버가 꺼지고, 잘못 삭제한 값을 어제 상태로 되돌려야 하는 순간부터 문제가 달라진다. 이제 필요한 것은 바이트를 남기는 기능이 아니라 여러 요청이 같은 상태를 안전하게 공유하는 규칙이다.

관계형 데이터베이스는 이 규칙을 애플리케이션마다 다시 만들지 않도록 묶은 실행 엔진이다. 그래서 데이터베이스를 선택할 때 “얼마나 많이 저장하는가”만 보면 안 된다. 동시에 누가 바꾸는지, 함께 성공해야 하는 변경은 무엇인지, 어떤 규칙이 절대 깨지면 안 되는지를 먼저 본다.

파일 저장이 어려워지는 네 순간

첫째는 동시 수정이다. 재고가 10개일 때 두 요청이 모두 10을 읽고 각각 1을 빼서 9를 저장하면, 주문은 두 건인데 재고는 한 개만 줄어든다. 마지막에 저장한 값이 앞선 변경을 덮은 것이다. 애플리케이션에서 잠금을 직접 구현할 수도 있지만 프로세스가 여러 대로 늘어나면 잠금의 소유권과 장애 복구까지 해결해야 한다.

둘째는 부분 실패다. 계좌 A에서 돈을 뺀 뒤 계좌 B에 더하기 전에 서버가 꺼질 수 있다. 두 파일을 순서대로 수정하면 중간 상태가 남는다. 데이터베이스의 트랜잭션은 여러 변경을 하나의 업무 단위로 묶어 전부 반영하거나 전부 취소한다.

셋째는 검색 경로다. 파일이 커질수록 주문 하나를 찾을 때마다 전체 파일을 처음부터 훑는 방식은 버티기 어렵다. 데이터베이스는 인덱스와 통계를 관리하고, SQL로 제시한 조건에 맞춰 어떤 순서로 표와 인덱스를 조회할지 결정한다.

넷째는 복구와 접근 통제다. 성공했다고 응답한 변경을 장애 뒤 복원하고, 특정 사용자는 조회만 허용하며, 백업에서 원하는 시점으로 돌아갈 수 있어야 한다. 이 기능을 서비스마다 따로 구현하는 비용이 데이터베이스 운영 비용보다 커지는 지점에서 데이터베이스가 필요해진다.

flowchart TB
  A["여러 요청이 같은 상태를 변경"] --> B["트랜잭션과 동시성 제어"]
  C["원하는 데이터를 빠르게 검색"] --> D["질의 최적화와 인덱스"]
  E["저장 도중 서버 장애"] --> F["로그 기록과 장애 복구"]
  G["업무 규칙을 모든 서비스가 공유"] --> H["제약 조건과 권한"]
  B --> R["관계형 데이터베이스"]
  D --> R
  F --> R
  H --> R

관계형이라는 말은 표 모양보다 규칙에 가깝다

RDB(Relational Database, 관계형 데이터베이스)의 핵심은 엑셀처럼 표가 보인다는 사실이 아니다. 관계 모델에서는 데이터를 행과 열로 표현하고, 여러 관계를 조건에 따라 결합한다. 주문의 customer_id가 실제 회원을 가리켜야 하고 주문 번호는 중복될 수 없다는 규칙을 외래 키와 고유 제약으로 데이터 가까이에 둘 수 있다.

SQL(Structured Query Language, 구조화 질의 언어)은 데이터를 찾는 물리적 순서보다 원하는 결과를 선언한다. 개발자가 “주문 표를 먼저 읽고 이 인덱스의 세 번째 페이지를 확인하라”고 지시하지 않아도 된다. 조건과 결합 관계를 적으면 데이터베이스의 최적화기가 통계와 사용 가능한 인덱스를 바탕으로 실행 경로를 고른다. 이 분리 덕분에 데이터가 늘거나 인덱스가 바뀌어도 애플리케이션의 업무 질문은 비교적 유지된다.

NoSQL(Not Only SQL)은 관계형이 아닌 하나의 데이터베이스 종류가 아니다. 키로 값을 찾는 저장소, 객체를 문서 단위로 보관하는 저장소, 여러 노드에 넓은 키 공간을 나누는 저장소처럼 비용 구조가 다른 제품군을 묶어 부르는 이름이다. 따라서 “SQL과 NoSQL 중 무엇이 더 좋은가”라는 질문은 너무 크다.

실제 질문은 업무 관계와 트랜잭션을 저장소가 직접 지켜야 하는가, 아니면 미리 정한 키 접근과 분산 방식이 더 중요한가이다. 주문·결제처럼 규칙이 여러 행과 표에 걸치고 조회 방식이 계속 달라진다면 관계형 데이터베이스가 자연스럽다. 세션이나 캐시처럼 알려진 키로 값을 찾고 손실 시 원본에서 다시 만들 수 있다면 키-값 저장소가 단순할 수 있다.

관계형 데이터베이스를 기본값으로 두기 좋은 경우

다음 상황에서는 PostgreSQL, MySQL, Oracle 같은 관계형 제품에서 시작하는 편이 보통 안전하다.

  • 주문과 결제처럼 여러 변경이 함께 성공해야 한다.
  • 중복 금지, 참조 무결성, 금액 범위 같은 규칙을 데이터 가까이에서 강제해야 한다.
  • 조회 조건과 조인 방식이 제품 성장에 따라 달라질 가능성이 크다.
  • 장애 뒤 복구할 데이터가 서비스의 원본이다.
  • 팀이 백업, 복제, 스키마 변경 절차를 이미 운영하고 있다.

반대로 빌드 결과물이나 변경이 드문 설정처럼 한 프로세스가 읽고 다시 만들 수 있는 데이터라면 파일로 충분할 수 있다. 캐시와 검색 인덱스처럼 원본에서 재구축할 수 있는 표현도 관계형 데이터베이스가 항상 맡을 필요는 없다.

핵심은 모든 데이터를 관계형 제품 하나에 넣는 것이 아니다. 먼저 업무의 원본과 불변식을 가장 단순하게 지키고, 다른 저장소는 명확한 병목이나 접근 방식이 생긴 뒤 추가하는 것이다. 제품 선택은 그다음 질문이다.

다음에 읽을 글

참고 자료