문서 목록을 자동으로 모으는 DocsQuery
DocsQuery는 현재 Binder index에서 조건에 맞는 문서를 찾아 문서 안의 살아 있는 목록으로 보여 주는 기능이다. SQL이나 JavaScript 대신 preset, folder·section·tag 조건, 정렬, 개수와 표시 필드를 조합한다. 원본 문서가 바뀌고 index가 갱신되면 같은 query가 새 결과를 만든다.
Markdown에서는 glif-query fenced block으로 작성하고, Desk에서는 DocsQuery component와 inspector로 같은 구조화 query 의미를 사용한다. 두 표면의 배치 UI는 다르지만 query의 정본은 실행 코드나 숨은 database view가 아니라 사용자가 확인할 수 있는 구조화 조건이다.
실습 파일을 연다
완성된 실증 묶음은 다음 다섯 파일로 구성된다.
다섯 파일을 같은 Binder의 docs-query/ 폴더에 둔다. 대시보드를 제외한 세 데이터 문서는 모두 query-item tag를 갖고, 그중 두 문서는 release tag도 갖는다. 이 구분 덕분에 list 3건, cards 2건, 의도한 empty 0건을 같은 문서 집합으로 재현할 수 있다.
Query record의 created, updated, summary는 front matter의 date, lastmod, description에서 만들어진다. 날짜 정렬을 검증하려면 2026-08-01T09:00:00Z처럼 timezone을 포함한 RFC 3339 값을 사용한다. created:·updated:·summary:를 임의의 front matter key로 추가해도 이 세 record field를 대신하지 않는다.
1. 첫 query를 만든다
```glif-query
preset: sectionDocs
section: docs-query
tags: query-item
sort: updated_desc
limit: 4
layout: list
show: title, summary, updated, tags
heading: 최근 수정된 가이드 자산
emptyMessage: docs-query 문서를 찾지 못했습니다.
```- 여는 fence의 언어를 정확히
glif-query로 쓴다. key: value를 한 줄에 하나씩 쓴다.- 닫는 fence까지 입력한다.
- 커서를 block 밖으로 옮긴다.
- index가 준비되면 source 대신 collection projection이 나타나는지 확인한다.

실증에서는 index에 총 5개 문서가 있었지만 section: docs-query와 tags: query-item을 함께 적용해 데이터 문서 3개만 남았다. updated_desc 결과는 lastmod가 8월 1일인 릴리즈 체크리스트, 7월 31일인 실증 자산 검토, 7월 30일인 게시 메모 순서였다. query 대시보드 자체가 결과에 포함되지 않은 이유는 대시보드에 query-item tag를 주지 않았기 때문이다.
query가 들어 있는 문서도 일반 index 문서다. section만 조건으로 사용하면 대시보드 자체가 결과에 포함될 수 있다. 결과 전용 tag를 두면 query 문서와 데이터 문서를 명확히 분리할 수 있다.
2. source와 projection을 오간다
projection 오른쪽의 Reveal source를 누르면 해당 glif-query 원문이 다시 열린다. 값을 고친 뒤 block 밖을 클릭하면 같은 source에서 projection을 다시 계산한다.

영상은 4.4초 동안 다음 동작을 실제 앱에서 수행한다.
query-item문서 3건이 list projection으로 표시된다.- Reveal source를 클릭해 fence 원문으로 돌아간다.
- block 밖을 클릭해 같은 query projection을 다시 표시한다.
projection은 편집 가능한 원문을 대체하지 않는다. source가 파일에 남는 정본이고, 결과 카드는 현재 Binder index에서 파생한 화면이다.
3. cards로 같은 문서를 다시 본다
release tag가 있는 문서만 카드로 보려면 두 필드를 바꾼다.
```glif-query
preset: tagDocs
section: docs-query
tags: release
sort: updated_desc
limit: 4
layout: cards
show: title, summary, updated, tags
heading: 릴리즈 태그 카드
emptyMessage: release 태그 문서가 없습니다.
```
실증 결과는 릴리즈 체크리스트와 실증 자산 검토 2건이다. tags에 여러 값을 적으면 모든 tag를 동시에 요구하는 AND가 아니라 그중 하나 이상이 일치하는 문서를 찾는다. 모든 문서가 같은 범주를 공유해야 한다면 예제처럼 별도의 공통 tag를 둔다.
4. preset을 선택한다
Preset은 자주 쓰는 filter·sort·layout·show 기본값을 한 번에 정한다. 뒤에 적은 field는 필요한 부분만 덮어쓴다.
| preset | 기본 목적 | 기본 정렬·표현 |
|---|---|---|
recentCreated |
최근 생성된 일반 문서 | created_desc, list, 생성일 표시 |
recentUpdated |
최근 수정된 일반 문서 | updated_desc, list, 수정일 표시 |
folderDocs |
지정 folder의 일반 문서 | weight_asc, list |
sectionDocs |
지정 section의 일반 문서 | updated_desc, list |
tagDocs |
tag로 모은 일반 문서 | updated_desc, cards, tag 표시 |
featuredDocs |
featured: true 문서 |
weight_asc, cards, tag·thumbnail 표시 |
sectionCards |
section record 둘러보기 | weight_asc, cards, 날짜 숨김 |
custom |
모든 값을 직접 조합 | updated_desc, list |
처음에는 preset 하나와 limit만 넣어 결과를 확인한다. 이후 folder, section, tags를 하나씩 추가하면 어떤 조건 때문에 결과가 사라졌는지 찾기 쉽다.
5. filter를 정확히 사용한다
| field | 입력 | 실제 의미 |
|---|---|---|
folder |
Binder 상대 folder 경로 | 정규화된 folder가 정확히 같은 record만 선택 |
section |
top-level section 이름 | 정규화된 section이 정확히 같은 record만 선택 |
tags |
release, featured 또는 [release, featured] |
대소문자를 무시하고 하나 이상 일치 |
featured |
true, yes, on 또는 false 계열 값 |
true 계열은 featured 문서만 선택하고 false 계열은 제한을 두지 않음 |
type |
doc, section 또는 빈 값 |
일반 문서, section record 또는 전체 |
여러 filter field는 함께 적용된다. 예를 들어 section: docs-query와 tags: release는 docs-query section 안에서 release tag가 하나라도 있는 문서만 남긴다. folder와 section은 부분 문자열 검색이 아니다. 결과가 없다면 실제 index의 상대 경로와 section 값을 먼저 확인한다.
6. 정렬·개수·표현을 조절한다
정렬
| sort | 순서 |
|---|---|
created_desc |
생성일 최신순 |
updated_desc |
수정일 최신순 |
title_asc |
제목 오름차순 |
weight_asc |
작은 weight 우선; weight가 없는 문서는 뒤로 |
backlinks_desc |
backlink 수가 많은 문서 우선 |
날짜나 숫자가 같으면 제목, 경로, record id 순서로 안정적인 tie-break를 적용한다. limit 기본값은 5이고 입력 범위는 1–50으로 제한된다. 0이나 음수를 써서 결과를 숨기는 용도로 사용하지 않는다.
layout
| layout | 적합한 용도 |
|---|---|
list |
제목·요약·metadata를 행 단위로 비교 |
cards |
추천 문서나 시각적 탐색 |
compact |
좁은 공간의 짧은 링크 모음 |
timeline |
생성·수정 흐름을 날짜 중심으로 탐색 |
표시 field
show에는 title, summary, created, updated, tags, thumbnail을 comma 목록 또는 대괄호 목록으로 적는다. 적지 않은 항목은 숨긴다. source 문서에 해당 metadata가 없으면 field를 요청해도 빈 값을 만들어 내지 않는다.
7. 빈 결과를 설계하고 복구한다
유효한 query라도 일치하는 문서가 없을 수 있다. 이 상태는 syntax error가 아니다.
```glif-query
preset: tagDocs
section: docs-query
tags: never-match
layout: compact
show: title, updated
heading: 의도한 빈 결과
emptyMessage: never-match 태그를 지우면 결과가 다시 나타납니다.
```
복구할 때는 다음 순서로 조건을 완화한다.
tags를 잠시 제거한다.- 결과가 나타나면 front matter의 tag 철자와 대소문자를 확인한다.
- 여전히 0건이면
section또는folder를 제거한다. type이 preset 기본값과 맞는지 확인한다.- 문서를 저장한 뒤 index 갱신을 기다린다.
독자가 다음 행동을 알 수 있도록 emptyMessage에는 “조건과 일치하는 문서가 없습니다”보다 구체적인 복구 힌트를 적는 편이 좋다.
8. 잘못된 입력 경고를 읽는다
DocsQuery는 지원하지 않는 field나 enum 값을 정상 조건처럼 조용히 실행하지 않는다.
```glif-query
preset: sectionDocs
section: docs-query
layout: mosaic
unknownField: ignored
limit: 4
heading: 지원하지 않는 입력 경고
```
실증 화면에는 다음 두 진단이 동시에 표시됐다.
Unsupported value for layout: mosaicUnsupported query field ignored: unknownField
잘못된 layout은 preset의 유효한 기본 layout으로 돌아가고, 알 수 없는 field는 무시된다. 화면에 결과가 보인다는 이유만으로 잘못된 입력이 적용됐다고 판단하면 안 된다. 경고를 모두 없앤 뒤 결과를 확정한다.
9. Desk에서 DocsQuery를 사용한다
- Desk를 열고 component palette에서 DocsQuery를 추가한다.
- inspector의 preset group에서 목적에 맞는 preset을 고른다.
- filter group에서 folder, section, tags, featured, type을 설정한다.
- query group에서 sort, limit, layout을 정한다.
- display group에서 title, summary, 날짜, tags, thumbnail 표시 여부를 고른다.
- content group에서 heading과 empty message를 작성한다.
- 결과 항목을 열어 원본 문서로 이동한다.
Desk component와 Markdown block은 같은 query model을 사용하지만 저장 표면과 배치 방식은 다르다. Markdown fence를 raw SQL로 해석하거나 Desk component가 임의 script를 실행한다고 가정하지 않는다.
10. index와 공개 결과의 책임을 구분한다
DocsQuery source만 다른 Binder로 복사하면 같은 결과가 보장되지 않는다. 결과에는 현재 Binder의 문서 집합, front matter, 상대 경로, index revision이 함께 영향을 준다.
| 상태 | 의미 | 다음 행동 |
|---|---|---|
| loading | Binder index snapshot을 준비 중 | 잠시 기다리고 Scope 상태 확인 |
| empty | query는 유효하지만 결과가 없음 | 조건을 하나씩 완화 |
| warning | 지원하지 않는 field나 값 | field 이름과 enum 값 수정 |
| stale | 문서 변경과 index revision이 아직 맞지 않음 | index 갱신 뒤 다시 실행 |
| index error | Binder index를 읽지 못함 | Scope와 index 상태 복구 |
Markdown source를 공개했다고 desktop의 현재 query 결과가 모든 정적 사이트에 자동 materialize되는 것은 아니다. 배포 대상이 query를 실행하는지, build 시점에 결과를 고정하는지, source block만 보여 주는지는 출판 경로의 별도 계약을 따른다.
내부 SQLite schema, planner cost, revision token은 사용자 입력 surface가 아니다. 가이드에서는 source 조건, 보이는 결과, 상태와 복구 절차를 정본으로 다룬다.
실패와 복구
| 증상 | 확인 | 복구 |
|---|---|---|
| projection이 안 보임 | fence 언어와 닫는 backtick | glif-query 철자와 fence 쌍 수정 |
| query 원문을 고칠 수 없음 | 현재 selection이 projection 밖인지 | Reveal source 클릭 |
| 결과가 0개 | section·folder·tags·type 조합 | 조건을 역순으로 하나씩 제거 |
| query 문서가 자기 결과에 포함됨 | 전용 결과 tag가 없는지 | 데이터 문서에 공통 tag를 추가하고 filter 적용 |
| field warning이 남음 | 지원 field·enum 목록 | 경고에 나온 field 삭제 또는 값 교체 |
| 최근 문서가 빠짐 | 파일 저장과 index revision | 저장 후 index 갱신 기다리기 |
| 다른 Binder에서 결과가 다름 | fixture·상대 경로·front matter | 같은 문서 집합과 폴더 구조 사용 |
| 공개 사이트에서 결과가 다름 | 배포 경로의 materialization 계약 | 출판 미리보기에서 별도 검증 |
완료 체크
- 다섯 fixture 파일을 같은
docs-query/폴더에 배치했다. - source와 projection을 Reveal source와 block 밖 클릭으로 오갔다.
- 같은 index에서 list 3건과 cards 2건을 재현했다.
- 유효한 empty 0건과 지원하지 않는 field·layout 경고를 구분했다.
- preset, filter, sort, limit, layout, show의 지원 값을 확인했다.
- query source, Binder index, 공개 결과의 책임을 구분했다.