C++로 처음부터 SQL 유사 관계형 데이터베이스 엔진 만들기
Source: Dev.to
하지만 어느 순간부터 나는 궁금해지기 시작했다.
SQL은 실제로 내부에서 어떻게 동작할까?
쿼리는 어떻게 파싱되는가?
조인은 어떻게 구현되는가?
SELECT 문이 실행된 뒤에는 무엇이 일어나는가?
영속성(persistence)은 어떻게 구현되는가?
그래서 데이터베이스에 관한 글만 읽는 대신 직접 하나를 만들어 보기로 했다.
그 프로젝트가 바로 Ark — C++로 처음부터 손수 구현한 SQL‑유사 관계형 데이터베이스 엔진이다.
기존 엔진이나 파서 생성기에 의존하지 않고 직접 각 요소를 구현함으로써 데이터베이스 시스템 내부를 이해하고 싶었다.
목표는 상용 데이터베이스와 경쟁하는 것이 아니라, 다음을 배우는 것이었다.
- 파싱
- 쿼리 실행
- 관계 연산
- 스키마 관리
- 영속성 시스템
- 소프트웨어 아키텍처
Ark가 현재 지원하는 기능은 다음과 같다.
- Handwritten tokenizer
- Recursive descent parser
- CRUD operations
- INNER / LEFT / RIGHT / FULL joins
- Aggregate functions (COUNT, SUM, AVG, MIN, MAX)
- ALTER TABLE
- LIKE pattern matching
- ORDER BY
- DISTINCT
- File persistence (SAVE / LOAD)
- 정확한 행/열 위치를 알려주는 3단계 진단 시스템
모든 것이 직접 구현되었다.
- 외부 데이터베이스 라이브러리 사용 금지
- 파서 생성기 사용 금지
실행 파이프라인은 대략 다음과 같다.
Query
↓
Tokenizer
↓
Parser
↓
Command Objects
↓
Execution Engine
↓
Storage Layer
↓
Persistence
프로젝트는 모듈형 컴포넌트로 나뉜다.
- tokenizer
- parser
- execution engine
- diagnostics
- storage/persistence
CREATE TABLE employees (
id INT,
name STRING,
salary DOUBLE
);
INSERT INTO employees VALUES
(1, "Alice", 95000.0),
(2, "Bob", 72000.0);
SELECT * FROM employees
WHERE salary > 80000.0;
가장 흥미로웠던 도전 과제 중 하나는 조인과 스키마 진화 구현이었다.
다음 작업들을 처리하면서 예상보다 훨씬 복잡해졌다.
- ALTER TABLE
- 컬럼 추가/삭제
- 영속성 일관성 유지
- 조인 실행
파서의 정확성 및 진단 기능 구현에도 생각보다 많은 노력이 들어갔다.
Ark를 만들면서 얻은 교훈
- 파서는 실제로 어떻게 동작하는가
- 쿼리 실행 파이프라인 구조
- 관계형 데이터베이스 개념
- 소프트웨어 아키텍처 설계
- 복잡한 상태 시스템 디버깅
- 진단·오류 보고 설계
또한 실제 데이터베이스 엔진에 대해 훨씬 깊은 감사를 느끼게 되었다.
GitHub Repository:
https://github.com/kashyap-devansh/Ark
데이터베이스, 시스템 프로그래밍, 파서, 컴파일러, C++에 관심 있는 분들의 피드백을 진심으로 환영한다.
특히 아키텍처나 쿼리 엔진 개선에 대한 제안이 있으면 좋겠다.