문서 목록을 자동으로 모으는 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 문서를 찾지 못했습니다.
```
  1. 여는 fence의 언어를 정확히 glif-query로 쓴다.
  2. key: value를 한 줄에 하나씩 쓴다.
  3. 닫는 fence까지 입력한다.
  4. 커서를 block 밖으로 옮긴다.
  5. index가 준비되면 source 대신 collection projection이 나타나는지 확인한다.

query-item tag가 있는 최근 수정 문서 3개를 list로 표시한 DocsQuery projection

실증에서는 index에 총 5개 문서가 있었지만 section: docs-querytags: 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을 다시 계산한다.

Reveal source를 눌러 편집 가능한 glif-query fenced block으로 돌아온 화면

영상은 4.4초 동안 다음 동작을 실제 앱에서 수행한다.

  1. query-item 문서 3건이 list projection으로 표시된다.
  2. Reveal source를 클릭해 fence 원문으로 돌아간다.
  3. 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 태그 문서가 없습니다.
```

release tag가 있는 릴리즈 체크리스트와 실증 자산 검토를 cards로 표시한 화면

실증 결과는 릴리즈 체크리스트와 실증 자산 검토 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-querytags: release는 docs-query section 안에서 release tag가 하나라도 있는 문서만 남긴다. foldersection은 부분 문자열 검색이 아니다. 결과가 없다면 실제 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 태그를 지우면 결과가 다시 나타납니다.
```

유효한 query가 0건을 반환하고 사용자 정의 emptyMessage를 표시한 화면

복구할 때는 다음 순서로 조건을 완화한다.

  1. tags를 잠시 제거한다.
  2. 결과가 나타나면 front matter의 tag 철자와 대소문자를 확인한다.
  3. 여전히 0건이면 section 또는 folder를 제거한다.
  4. type이 preset 기본값과 맞는지 확인한다.
  5. 문서를 저장한 뒤 index 갱신을 기다린다.

독자가 다음 행동을 알 수 있도록 emptyMessage에는 “조건과 일치하는 문서가 없습니다”보다 구체적인 복구 힌트를 적는 편이 좋다.

8. 잘못된 입력 경고를 읽는다

DocsQuery는 지원하지 않는 field나 enum 값을 정상 조건처럼 조용히 실행하지 않는다.

```glif-query
preset: sectionDocs
section: docs-query
layout: mosaic
unknownField: ignored
limit: 4
heading: 지원하지 않는 입력 경고
```

지원하지 않는 mosaic layout과 unknownField를 각각 경고로 표시한 화면

실증 화면에는 다음 두 진단이 동시에 표시됐다.

  • Unsupported value for layout: mosaic
  • Unsupported query field ignored: unknownField

잘못된 layout은 preset의 유효한 기본 layout으로 돌아가고, 알 수 없는 field는 무시된다. 화면에 결과가 보인다는 이유만으로 잘못된 입력이 적용됐다고 판단하면 안 된다. 경고를 모두 없앤 뒤 결과를 확정한다.

9. Desk에서 DocsQuery를 사용한다

  1. Desk를 열고 component palette에서 DocsQuery를 추가한다.
  2. inspector의 preset group에서 목적에 맞는 preset을 고른다.
  3. filter group에서 folder, section, tags, featured, type을 설정한다.
  4. query group에서 sort, limit, layout을 정한다.
  5. display group에서 title, summary, 날짜, tags, thumbnail 표시 여부를 고른다.
  6. content group에서 heading과 empty message를 작성한다.
  7. 결과 항목을 열어 원본 문서로 이동한다.

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, 공개 결과의 책임을 구분했다.