선언형 쿼리란?
무엇(What)을 가져올지만 명시하는 질의 방식으로 가장 대표적인 예시가 바로 SQL이다. 선언형 쿼리(SQL)는 '관계해석'을 기반으로 하며, 이를 실행하기 위해 내부적으로 '관계대수'로 변환된다.
[선언형 쿼리 예시]
SELECT name FROM employees WHERE department = 'Planning';
선언형 쿼리의 특징
- 결과 중심: 데이터의 저장 위치나 탐색 경로를 사용자가 고민하지 않는다.
- 최적화 위임: 구체적인 처리 절차는 데이터베이스 관리시스템(DBMS)의 옵티마이저가 결정한다.
- 사용자 친화적: 절차형 언어에 비해 코드가 직관적이고 가독성이 높다. 문장으로 읽힘.
관계대수와의 핵심 관계성
관계대수와 선언형 쿼리는 관계형 데이터베이스(RDB)의 근간을 이루는 두 축.
- 이론적 뿌리
- 관계대수(Relational Algebra)
- 절차적(Procedural) 성격을 가진다.
- 데이터를 어떻게 유도할지 연산자(Select, Project, Join 등)를 순서대로 명시한다.
- 관계해석(Relational Calculus)
- 비절차적/선언적(Declarative) 성격을 가진다.
- 원하는 데이터의 조건만 명시한다.
- SQL이 바로 이 관계해석에 뿌리를 두고 있다.
- SQL의 WHERE 절이 바로 관계해석의 술어(Predicate)와 대응된다.
- 관계대수(Relational Algebra)
- 번역기와 실행 엔진의 관계
- 사용자가 SQL(선언형)로 쿼리를 작성하여 제출.
- DBMS 내부의 옵티마이저가 이 선언형 쿼리를 이해하고, 실제 실행이 가능한 관계대수식(절차적 명령)으로 변환한다.
- 즉, "선언형으로 요청하면(What), 시스템이 관계대수를 이용해 절차를 수립(How)하여 실행"하는 메커니즘.
선언형 쿼리의 장점
- 옵티마이저가 실행 계획을 고르므로 인덱스 사용, 조인 순서, 조인 알고리즘을 DBMS가 알아서 최적화한다.
- 병렬화에 유리한다. 어떻게 가져오라는 명령이 없으므로 시스템이 여러 코어/머신에 자유롭게 분산해서 질의할 수 있다. 이에 반해 명령형은 실행 순서를 강제하므로 병렬화가 어렵다.
- 세부 구현에 결합되지 않으므로 간결하다.
명령형 쿼리란?
'무엇(What)'을 원하는지뿐만 아니라, 데이터를 찾기 위해 '어떻게(How)' 해야 하는지 구체적인 단계와 절차를 직접 지시하는 질의 방식으로 대부분의 프로그래밍 언어 코드에 해당한다. 주로 NoSQL 데이터베이스나 프로그래밍 언어 내에서 데이터를 다룰 때 많이 사용된다.
명령형 쿼리의 특징
- 절차적 수행: 루프(Loop), 조건문(If), 변수 등을 사용하여 데이터 탐색 경로를 직접 제어한다.
- 최적화 책임: 시스템이 알아서 경로를 찾지 못하므로, 코드를 효율적으로 짜야 하는 책임이 개발자에게 있다.
[명령형 쿼리 예시]
let results = [];
let cursor = db.employees.find(); // 전체 데이터를 가져옴
while(cursor.hasNext()) {
let doc = cursor.next();
if (doc.department === 'Planning') { // 조건 검사
results.push(doc.name); // 결과 배열에 담기
}
}
return results;
- 특징
- <전체 데이터를 열어서 -> 하나씩 돌면서 -> 부서가 기획팀이면 -> 이름을 배열에 집어넣어라> 라고 모든 연산 과정을 순서대로 명령한다.
- 앞서 언급한 '관계대수'의 처리 방식이 바로 이 명령형(절차적) 구조에 해당합니다.
- 선언형 쿼리에서 "관계대수를 이용해 절차를 수립(How)하여..."에 해당
대표적인 명령형 데이터 처리 기술
- Graph Database (Gremlin): 그래프 DB에서 노드와 간선을 "A노드에서 출발해 B간선을 타고 C로 이동하라"며 직접 순회(Traversal) 경로를 지정한다.
- MapReduce: 빅데이터를 처리할 때 데이터를 쪼개고(Map), 모으는(Reduce) 로직을 개발자가 직접 함수로 구현한다.
선언형 쿼리가 명령형 쿼리보다 유리한 점
선언형은 '무엇을'만 선언하고 '어떻게'는 명령하지 않으므로, 시스템이 실행 순서·분산을 자유롭게 정할 수 있어 여러 코어/머신에서 병렬화하기 쉽다. 또한 옵티마이저가 인덱스, 조인 순서, 알고리즘을 알아서 고르고, 내부 구현(새 인덱스 추가)이 바뀌어도 코드 수정 없이(방법 명령 수정 등) 최적의 명령을 얻을 수 있다. 이에 반해 명령형은 코드상 특정 실행 순서를 강제하므로 병렬화가 어렵다.
반응형