이 글은 ORM 관리자의 관점에서 관계형 데이터베이스(MySQL, PostgreSQL)의 클라이언트 프로토콜이 개선될 수 있는 영역에 대해 논합니다. SQL 자체는 실용적이지만, 클라이언트 프로토콜은 인간이 CLI 인터페이스에서 명령을 입력하는 것 외의 사용 시나리오를 충분히 고려하지 않은 것처럼 보입니다. 이 글은 Redis 프로토콜의 일부 기능과 비교하며 기존 프로토콜의 문제점을 분석하고 개선 방안을 제시합니다.
첫째, 데이터베이스 연결의 가변 상태(Mutable State)가 문제입니다. Active Record가 연결 시 실행하는 ‘prelude’ 쿼리처럼 세션 수준 설정은 연결의 동작을 변경합니다. 문제는 이러한 설정이 초기 인증/구성 단계에 국한되지 않고 언제든지 변경될 수 있어, 프레임워크나 라이브러리가 사용자 코드에 연결을 넘겼다가 돌려받을 때 상태를 확신할 수 없다는 점입니다. 이는 연결 관리 코드를 복잡하게 만들며, 오류 발생 시 연결의 상태를 알기 어렵게 하여 연결을 닫고 다시 시작하는 것이 유일한 안전한 복구 방법이 됩니다. 명시적인 초기 구성 단계나 ‘reset state’ 메시지가 있다면 이러한 문제를 해결할 수 있습니다.
둘째, 안전한 재시도(Safe Retries)의 어려움입니다. 네트워크 오류는 피할 수 없으며, 클라이언트는 오류 발생 시 쿼리 재시도를 시도해야 합니다. 그러나 쓰기 또는 읽기 작업 실패 시 서버에서 쿼리가 실행되었는지 알 수 없는 경우가 많습니다. HTTP의 PUT, DELETE처럼 멱등성(Idempotency)이 명시된 동사는 안전하게 재시도할 수 있지만, SQL 쿼리는 멱등성 여부를 판단하기 어렵습니다. 예를 들어 DELETE WHERE id = 42
는 멱등성이지만, DELETE WHERE id IN (SELECT ... LIMIT ...)
는 그렇지 않습니다. 따라서 데이터베이스 클라이언트는 호출자가 안전하다고 알려주지 않는 한 안전하게 재시도하기 어렵습니다. Stripe API의 Idempotency Keys와 같이, 비멱등성 작업에 고유 키를 부여하여 서버가 중복 요청을 식별하고 처리하도록 하는 방식은 안전한 재시도를 가능하게 합니다. 저자는 ValKey(Redis 포크)에 이 기능을 제안하여 수용되었으며, 관계형 데이터베이스에서도 이와 유사한 메커니즘을 프로토콜 수준에서 도입할 수 있다고 생각합니다.
셋째, 준비된 구문(Prepared Statements) 관리의 복잡성입니다. 준비된 구문은 SQL 인젝션 방지 및 성능 개선(구문 분석 및 쿼리 계획 캐싱)에 사용됩니다. MySQL 프로토콜에서는 COM_STMT_PREPARE
로 구문을 준비하고 statement_id
를 받아 COM_STMT_EXECUTE
로 실행합니다. 문제는 이 statement_id
가 세션 범위라는 것입니다. 연결 풀 환경에서는 동일한 구문에 대해 여러 연결에서 각각 준비해야 하며, 오류 복구를 위해 연결을 재설정하면 준비된 구문도 손실됩니다. 또한 서버 측 자원을 소모하므로 무한정 생성되지 않도록 주의해야 합니다. Active Record와 같은 라이브러리는 이러한 준비된 구문의 수명 주기를 관리하기 위한 복잡한 로직이 필요합니다. MySQL 프로토콜은 준비된 구문 없이 매개변수화된 쿼리를 지원하지 않아, 매개변수 삽입 방식(안전하지 않음)을 사용하거나 준비된 구문을 사용해야 하며 이는 추가 왕복을 야기할 수 있습니다. 개선 방안으로는 준비된 구문 없이 매개변수화된 쿼리를 지원하거나, Redis의 EVALSHA처럼 연결에 독립적인 예측 가능한 식별자(예: 해시 값)를 사용하여 준비된 구문을 공유하고 서버가 비활성 구문을 가비지 컬렉션하도록 하는 방식이 고려될 수 있습니다.
결론적으로, 관계형 데이터베이스는 매우 훌륭한 기술이지만, 프로토콜 측면에서는 개발자 경험이 우선순위가 낮은 것처럼 느껴집니다. SQL 쿼리 언어를 변경하지 않더라도 프로토콜 수준에서 가변 상태 관리, 안전한 재시도 지원, 준비된 구문 관리 방식 등을 개선한다면 유용성을 크게 높일 수 있습니다. Redis와 같은 다른 프로토콜에서 영감을 얻어 Idempotency Keys나 해시 기반 식별자 같은 개념을 도입하는 것이 효과적인 개선 방향이 될 수 있습니다.