News Feed

SQL의 귀환 : 50년 된 언어가 스스로 탈바꿈하는 방법

컨텐츠 정보

  • 조회 501

본문

브라우저에서 백엔드에 이르기까지, 한때 ‘지루한’ 것으로 치부되던 선택이 다시 사람들의 흥미를 끌고 있다. SQL을 다시 무대의 중심에 띄우고 있는 세 가지 트렌드를 살펴본다.

프로토타이핑은 프로그래밍에서 필자가 가장 좋아하는 부분이다. 새로운 것을 만들고 이것저것 움직이게 만드는 일을 좋아하는 만큼 몽고DB와 NoSQL의 열렬한 팬을 자처하는 것도 어떻게 보면 당연하다. 확실히 해 두자면 필자는 SQL 자체에 대해서도 항상 긍정적으로 평가해 왔다. 다만 자바스크립트에서 몽고DB를 사용할 때의 그 매끄러움에 빠져들었을 뿐이다.

최근 SQL은 포스트그레SQL 팀의 주도 하에 본격적인 재기를 알렸다. 애초에 SQL은 기업 데이터의 중심에서 한 번도 물러난 적이 없지만 이제는 전통적인 선택인 동시에 주목해야 할 흥미로운 기술로도 꼽힌다. 어떻게 이런 일이 일어났을까?

SQL의 컴백 과정

시작은 가벼운 관계형 데이터베이스인 SQLite가 브라우저로 SQL을 가져온 것이다. 브라우저의 SQL은 클라이언트 사이드 백엔드 동기화를 기반으로 하는 새로운 아키텍처를 가능하게 했는데, 이 아키텍처에서는 JSON이 아니라 SQL이 중심 축이 된다. 여러 언어 툴도 어떤 플랫폼에서든 더 편리하게 SQL을 사용할 수 있도록 하는 데 일조했다. 관계형 아키텍처의 익히 알려진 예측가능성은 오랫동안 조용히 사람들을 끌어왔고, 거기에 포스트그레SQL이 새로운 스키마리스 jsonb 타입을 추가했다.

이렇게 해서 죽은 줄 알았던 SQL이 멋진 기술로 되돌아온 것이다.

‘스키마리스’의 신화

자바스크립트에서 NoSQL이 그렇게 매력적인 이유는 데이터베이스 구조, 즉 스키마에 대해 생각하거나 이를 관리하기 위해 언어 패러다임에서 나올 필요가 없다는 점이다. 코딩 중에 새로운 타입을 하나 추가하고 싶다면 그냥 다음과 같이 하면 된다.

await db.collection('cats').insertOne({ name: 'Fluffy', mood: 'Judgmental' });

db.cats가 존재하지 않더라도 저장소가 알아서 만들어 준다. 데이터 “형태”(namemood)도 마찬가지다. 무엇보다 좋은 점은 JSON 객체를 그대로 집어넣을 수 있다는 것이다.

이는 모두가 추구하는 궁극의 마찰 없는 데이터처럼 보인다. 데이터베이스와 코드가 모두 JSON으로 소통한다. CREATE TABLE 문을 작성하기 위해 멈출 필요도 없다. 마이그레이션 스크립트를 실행할 필요도 없다. 데이터에 대해 생각할 필요도 없다. 필요한 것을 그때그때 만들면 데이터 저장소가 알아서 받아들인다.

그러나 프로토타입이 발전해 프로덕션 시스템이 되면 불편한 진실이 드러난다. 스키마는 이제 코드 안에 들어가 있을 뿐 여전히 존재한다는 사실이다. 다음과 같이 암묵적인 형태가 된다.

if (cat && cat.mood && typeof cat.mood === 'string')

또는 이런 경우도 있다.

const mood = cat?.mood ?? 'neutral';

이제 코드가 스키마를 강제한다. 이것이 스키마리스 세계에서 지속되는 구조적인 현실이다. 물론 엄격한 스키마에서도 검증을 위해 이와 같은 종류의 일을 하지만(코드에서 하든 검증 프레임워크를 사용하든) 공식적인 진정한 일관성은 데이터베이스 자체에 보존된다.

강력한 일관성 없이 대규모 시스템을 구축해야 한다는 압박은 실제 불안감으로 이어진다. 개발자들이 정말 원하는 것은 낮은 마찰로 강력한 데이터 무결성을 얻는 것이다. 이제 SQL로 다음 세 가지 트렌드가 융합되면서 그 희망이 실현 가능해지고 있다.

  • 동기화가 적용되는 프론트엔드의 SQL
  • 더 나은 SQL 클라이언트
  • 스키마리스 타입(JSONB)이 있는 SQL

첫 번째는 과감하고 새로운 트렌드이고 두 번째는 전통적인 엔지니어링이며 마지막은 진화적 적응이다.

더 자세히 살펴보자.

프론트엔드의 SQL

첫 번째 솔루션에는 데이터베이스의 위치에 대한 급진적인 사고의 전환이 수반된다. 지난 30년 동안 데이터베이스가 서버룸에 갇힌 거대한 괴물이었다면 브라우저는 API로부터 데이터를 구걸하는 조용한 터미널에 불과했다.

그러나 웹어셈블리(WASM) 덕분에 이제는 브라우저 내에서 실제 데이터베이스 엔진을 실행할 수 있게 됐다. PGlite(WASM에서 실행되는 포스트그레SQL)나 SQLite(표준화된 브라우저 빌드를 통함)와 같은 기술은 데이터베이스를 클라이언트 사이드 기술로 바꿔 놓았다.

프론트엔드로의 이동은 분석과 엣지 컴퓨팅을 위한 서버리스 SQL의 부상도 촉발했다. DuckDB와 같은 툴이 나오면서 개발자는 거대한 클라우드 웨어하우스 없이도 사용자 디바이스 또는 엣지에서 수백만 행의 분석 데이터를 처리할 수 있게 됐다.

이 발전 자체는 흥미롭지만 지각 변동을 일으킬 정도는 아니다. 다만 일렉트릭SQL(ElectricSQL)과 같은 동기화 기술의 등장은 예외다. 동기화는 NoSQL 세계의 PouchDB와 같은 프로젝트에 예전부터 있던 아이디어지만, 이제 SQL을 통해 탄력을 받고 있다. 동기화는 브라우저(또는 그 일부)와 서버에서 같은 데이터스토어를 사용할 수 있게 해주며, 동기화 엔진이 협상을 자동으로 처리한다.

또한 동기화는 또한 로컬 우선 데이터베이스 아키텍처의 가능성도 열어준다. 복잡한 API 엔드포인트(GET /cats, POST /cats) 작성과 로딩 스피너 없이 그냥 프론트엔드 코드가 로컬 데이터베이스에 직접 말한다.

로컬에서 레코드 INSERT 작업은 즉시 실행된다. 그 데이터를 서버로 보내는 번거로운 작업은 일렉트릭SQL, 레플리캐시(Replicache)와 같은 백그라운드 동기화 엔진이 처리한다. API 계층은 완전히 사라진다.

물론 로컬 우선으로의 전환에는 상당한 사고의 전환이 필요하고, 아키텍처 관련 영향도 있다. 그러나 관계형 데이터베이스를 브라우저에 직접 배치하면 SQL이 새로운 보편적 데이터 언어가 될 가능성이 열린다.

더 나은 SQL 클라이언트

두 번째 요소를 이끈 힘은 엔지니어링 측면의 부단한 노력, 즉 데이터베이스 클라이언트에 대해 오랜 기간 지속된 반복 개선이다.

SQL이 투박하고 오래된 기술이라는 평판의 상당부분은 실제로는 불충분한 툴에서 비롯된 문제였다. 어느 언어를 사용하든 SQL을 작성한다는 것은 문자열을 이어 붙이거나 무겁고 난해한 ORM과 씨름해야 한다는 것을 의미했다.

하이버네이트(Hibernate)/JPA 같은 ORM 툴은 개발자가 선택한 언어(여기서는 자바) 안에서 데이터를 관리할 수 있게 해주지만 어떤 일어나고 있는지 파악하기가 어려운 수준으로 메커니즘을 추상화한다. 데이터 흐름에 대한 추론이 혼란스러워지고 실수도 많아진다.

그러나 새로운 세대의 ORM-lite 툴이 그 간극을 메우고 있다. 타입스크립트용 드리즐(Drizzle), 코틀린을 위한 익스포즈드(Exposed), 자바용 jOOQ와 같은 툴은 개발자 경험에 초점을 맞추며 SQL의 엄격함을 프로그래밍 언어의 관용적 표현에 매핑한다. 예를 들어 드리즐은 다음과 같이 테이블 쿼리를 타입스크립트로 JSON 배열을 필터링하는 것처럼 느껴지게 만들면서도 완전한 타입 안전성을 유지한다.

const grumpyCats = await db  .select()  .from(cats)  .where(eq(cats.mood, 'Judgmental'));

이와 같은 여러 툴 덕분에 개발자는 더 이상 코드가 데이터와 일치하는지 여부에 대해 추측할 필요가 없다. 이러한 툴은 코드와 데이터가 같은 언어를 사용하는 몽고DB와 비슷한 감각을 제공하면서도 스키마의 무결성을 희생하지 않는다.

스키마리스 타입(JSONB)이 있는 SQL

포스트그레스 팀은 ‘관계형 데이터베이스가 스키마리스 JSON을 사용할 수 있다면?’이라는 질문을 던졌다. 그 답은 jsonb 타입이다.

포스트그레SQL이 길을 개척하자 다른 여러 데이터베이스도 뒤를 따랐다. 개발자가 필요할 때 스키마리스 문서를 사용할 수 있게 하면서 관계형 구조의 맥락 안에 머물도록 한, 매우 영리한 전략적 선택이었다.

이렇게 되자 다중 저장소 지속성(polyglot persistence) 아키텍처의 필요성이 줄어들었다. (다중 저장소 지속성은 2015년에 인기를 끈 개념으로, 트랜잭션에는 포스트그레SQL이 필요하고 카탈로그에는 몽고DB가 필요했다.)

JSONB는 금융 거래, PID와 같은 중요한 데이터에 대해서는 엄격한 ACID 준수를 제공하고 설정이나 로그 같은 복잡하게 얽힌 데이터에는 유연한 JSON 블롭을 제공한다. 또한 이 모든 것을 하나의 행으로 처리한다. 사람들은 유연성을 얻기 위해 SQL을 버릴 필요가 없음을 알게 됐다. SQL이 약간 더 유연해지기만 하면 된다.

JSONB는 인덱싱도 지원하므로 표준 필드와 JSON이 모두 포함된 혼합 문을 사용할 때도 인덱싱된 테이블의 성능을 얻을 수 있다.

하나의 데이터스토어를 사용한다는 약속은 무시하기에는 너무나 큰 아키텍처 측면의 이점이다.

기능으로서의 마찰

물론 과거의 경험에서 배웠듯이 지나치게 앞선 기대는 금물이다. 업계가 조만간 REST API를 폐기할 일은 없다(그럴 상황이면 그냥 HTMX를 사용했을 것). 현재 스택의 관성은 매우 크고, 그럴 만한 이유도 있다. 클라이언트를 데이터베이스에서 분리하는 방식은 실제 현장에서 검증된 패턴이기 때문이다.

SQL 역시 나름의 짐을 안고 있다. 여전히 커넥션 풀을 관리해야 하고 여전히 마이그레이션 스크립트를 작성해야 한다(툴 덕분에 쉬워지긴 했지만). 또한 관계형 데이터베이스 확장은 여전히 문서 저장소 확장보다 어렵다.

이 추세의 핵심은 SQL이 하루아침에 모든 것을 대체한다는 것이 아니라, 한쪽으로 가 있던 추가 다시 가운데로 돌아온다는 것이다. 사람들은 SQL의 마찰, 즉 타입과 관계를 정의해야 하는 필요성이 버그가 아니라 기능이었음을 깨닫고 있다. 이 기능은 시스템을 빌드하기 전에 설계부터 하도록 강제한다.

SQL과 린디 효과

린디 효과는 어떤 기술이 지금까지 생존한 기간이 길수록 앞으로의 기대 수명도 길어진다는 개념이다. SQL은 메인프레임, PC 혁명, 웹, 모바일을 거쳐 AI 시대로 들어선 지금까지 생존했다. SQL이 살아남은 이유는 완고해서가 아니라 환경에 적응했기 때문이다. 지금까지 SQL은 JSON을 흡수했고 웹 브라우저에 맞춰 몸집을 줄였고 현대 프로그래밍 언어와 통합됐다. 그러나 SQL의 복수에서 핵심은 다른 대안을 파괴하는 것이 아니라, 본질적인 부분에 계속 집중하면서 때로는 지루한 방식이 사실 근본적인 요소임을 증명하는 데 있다.
dl-itworldkorea@foundryco.com

관련자료

댓글 0
등록된 댓글이 없습니다.