NoSQL
Nosql and my project · MD
NoSQL은 왜 나왔고, 내 프로젝트엔 어디에 쓸까
CS 공부하다가 데이터베이스 역사를 훑어봤다. NoSQL이 왜 나왔는지 알고 나니까 내 프로젝트에 필요한지 아닌지도 좀 정리가 됐다.
왜 나왔나
1970년에 Codd가 관계형 모델을 제안했다. 데이터를 테이블로 표현하고, 어떻게 찾을지는 DB가 알아서 하게 만든 게 핵심이다. 여기서 SQL이 나왔고 30년 넘게 사실상 유일한 선택지였다.
문제는 2000년대에 터졌다. 구글이나 아마존 규모가 되면 아무리 좋은 서버를 사도 한 대로는 감당이 안 된다. 값싼 서버 수천 대에 데이터를 쪼개야 하는데, 그러면 조인이랑 트랜잭션이 갑자기 비싸진다. 서로 다른 기계에 있는 테이블을 붙이려면 네트워크를 타야 하고, 모든 노드가 같은 값을 보게 하려면 매번 서로를 기다려야 하니까.
그래서 조인이랑 강한 일관성을 포기하고 확장성을 가져가기로 한다. 구글 BigTable(2006), 아마존 Dynamo(2007) 논문이 그 결과물이고, 여기 영향받은 오픈소스들이 쏟아지면서 2009년쯤 NoSQL이라는 이름이 붙었다. SQL 반대가 아니라 Not Only SQL이다.
뭐가 다른가
스키마를 미리 안 정해도 된다. 같은 컬렉션 안 문서들이 서로 다른 필드를 가져도 된다. 대신 데이터 형태를 지키는 책임이 DB에서 애플리케이션 코드로 넘어온다. 스키마가 없어진 게 아니라 관리하는 쪽이 바뀐 거에 가깝다.
정규화 대신 비정규화를 한다. 관계형은 테이블을 잘게 나눠놓고 필요할 때 조인하는데, NoSQL은 같이 읽는 데이터를 한 문서에 통째로 넣어둔다. 게시글 안에 댓글을 중첩시키는 식이다. 읽기는 빨라지고 대신 중복이 생겨서 하나 고칠 때 흩어진 사본을 다 찾아야 한다.
값이 잠깐 다를 수 있다. 분산 환경에서는 일관성과 가용성을 동시에 완벽히 못 지킨다는 게 CAP 정리인데, 많은 NoSQL은 가용성을 골랐다. 지금은 노드마다 값이 달라도 시간이 지나면 같아진다는 결과적 일관성이다. 좋아요 숫자가 잠깐 틀린 건 괜찮지만 계좌 잔액은 그러면 안 된다. 기술의 우열 문제가 아니라 도메인 문제다.
쿼리 방식도 반대다. SQL은 설계할 때 생각 못 한 질문도 나중에 던질 수 있는데, NoSQL은 어떻게 읽을지 먼저 정하고 거기 맞춰 저장한다. 접근 패턴이 곧 설계다.
그리고 NoSQL은 하나가 아니다. 키-값(Redis), 문서(MongoDB), 와이드 컬럼(Cassandra), 그래프(Neo4j)가 다 다른 물건이라 "NoSQL 쓴다"는 말만으로는 정보가 거의 없다.
요즘은 경계도 흐릿하다. Postgres는 JSONB로 스키마리스 문서를 저장하고 그 안에 인덱스까지 건다. 유연한 스키마가 필요하다고 무조건 MongoDB로 갈 이유가 예전만큼 없다.
내 프로젝트
Next.js + Supabase로 만든 포트폴리오 사이트다. 프로젝트, 학력, 경력 같은 이력 데이터를 저장하고 관리자 인증이랑 RLS로 권한을 나눈다.
이 데이터는 옮길 이유가 없다. 프로젝트랑 산출물이 1:N, 이력서 프리셋이랑 항목이 N:M으로 얽혀 있어서 조인이 계속 필요하고, 인가가 미들웨어·서버 액션·RLS 세 층으로 되어 있는데 DB를 옮기면 RLS가 통째로 날아간다. 데이터도 몇 백 건이라 수평 확장을 걱정할 일이 없다. NoSQL이 대가를 치르고 산 이점을 내가 쓸 일이 없다.
굳이 쓴다면 조회수 쪽이다. 지금은 Postgres RPC로 원자적 증가를 돌리는데, 조회 한 번마다 DB 쓰기가 생기고 같은 행에 락이 걸린다. Redis면 INCR이 단일 원자 명령이라 락 경합이 없고, TTL 걸어서 중복 카운트 방지 같은 것도 별도 테이블 없이 된다. 실시간 값은 메모리에서 읽고 몇 분마다 Postgres에 반영하면 된다. 조회수는 잠깐 어긋나도 아무도 안 다치는 데이터라 이게 가능하다.
GitHub API 응답 캐시도 비슷하다. 원본이 밖에 있어서 날아가도 다시 받으면 그만이라 TTL 건 키-값 저장소가 맞다.
같은 프로젝트 안에서도 데이터마다 맞는 저장소가 다르다는 게 이번에 제일 와닿았다.