# 048 — 저장 쓰기 중에도 기존 문서를 읽는 선택형 호스트 [046](046-optional-async-document-http.md)의 선택형 HTTP 호스트는 파일 효과를 작업자 하나에 넘겨 이벤트 루프를 보호했다. 다만 쓰기가 `fsync`에서 멈추면 다른 문서 읽기도 그 작업자 뒤에서 대기했다. 저장소 코드를 확인하면 읽기는 파일 버전을 열어 불변 `mmap`으로 유지하고, 쓰기만 임시 파일 번호와 `.writer.lock`을 사용한다. 따라서 **읽기 작업자 하나와 쓰기 작업자 하나**를 두되, 기존의 쓰기 직렬화는 유지하는 경계가 가능하다. 선택형 `PURE_HTTP_ASYNC` 호스트에서 두 작업자는 입력 종류에 따라 공유된 최대 8개 작업 슬롯을 탐색한다. 각 작업자의 스택 크기는 128 KiB로 설정했다. HTTP 연결과 `pure_runtime_complete()`는 기존처럼 소유 스레드에서 처리한다. 기본 코어·CLI·HTTP에는 이 작업자들이 링크되지 않는다. 새 앱 모델이나 공용 코어 연산은 추가하지 않았다. [결정적 HTTP 검사](../../prototypes/connections/results/2026-09-24-async-read-write/gated.json)는 실제 CLI로 `gated=old` 버전 1을 만든 뒤, HTTP 수정 `oldafter`를 파일 동기화 직전에 멈춘다. 쓰기를 풀기 **전에** 같은 문서의 GET이 `old`, ETag `"1"`을 반환한다. 이때 잘못된 다른 HTTP 요청도 400으로 답하고, 쓰기를 기다린 연결은 기한에 닫힌다. 쓰기를 풀면 GET이 `oldafter`, ETag `"2"`를 반환한다. 종료 중인 별도 실행에서도 진행 중인 쓰기 완료를 기다리고 종료 시 보유 본문은 0 B다. 이 검사는 한 작업자로 모든 파일 효과를 실행하던 호스트에서는 통과하지 않는다. [ASan·UBSan 실행](../../prototypes/connections/results/2026-09-24-async-read-write/sanitized.json)과 [기존 HTTP 정확성 전체 검사](../../prototypes/connections/results/2026-09-24-async-read-write/full-check.json)도 통과했다. [서비스 작업 원자료](../../prototypes/connections/results/2026-09-24-async-read-write/service-scale.json)는 고정 정의·소스 정의·선택형 비동기 소스 정의로 각각 8 KiB 문서 1,024개를 만들고 8개 클라이언트가 4,096개 요청을 처리한 결과다. 세 호스트의 최종 문서 해시와 저장 파일 수가 같고, 모두 보유 본문 0 B로 종료했다. 이 실행의 비용은 다음과 같다. | Linux AArch64 / GCC 14 | 기본 소스 HTTP | 선택형 읽기+쓰기 HTTP | |---|---:|---:| | 링크된 `text` | 43,778 B | 48,401 B | | 서버 구조체 | 41,528 B | 43,320 B | | 유휴 RSS | 1,520 KiB | 1,552 KiB | | 피크 RSS | 1,696 KiB | 1,728 KiB | | 유휴 가상주소 공간 | 2,464 KiB | 2,848 KiB | | 피크 가상주소 공간 | 2,528 KiB | 2,928 KiB | | 프로세스 스레드 | 1 | 3 | 선택형 호스트는 기본 호스트보다 코드 4,623 B, 구조체 1,792 B, 이 작업의 피크 RSS 32 KiB가 더 든다. [이전 단일 작업자 기록](046-optional-async-document-http.md)과 비교하면 `text` 504 B와 구조체 96 B가 늘었다. 두 128 KiB 스택은 코드 섹션 크기에 포함되지 않는다. [크기 상한](../../prototypes/connections/results/2026-09-24-async-read-write/profile.json)은 기존 선택형 48 KiB 상한을 올리지 않고 통과했다. `make check-release`에서도 기본 코어 `text` 5,932 B, 기본 소스 HTTP `text` 43,778 B를 유지했다. 이는 **느린 쓰기와 기존 버전 읽기의 독립성 및 스냅샷 정확성**에 대한 결과다. 읽기끼리, 쓰기끼리는 각각 직렬이며, 기한이 지난 쓰기도 취소되지 않고 커밋될 수 있다. 매핑되지 않은 파일 캐시와 커널 소켓 버퍼는 프로세스 RSS 표에 포함되지 않는다. 이 작업은 처리량이나 Kitex급 RPC 성능을 측정하지 않는다. 일반 네트워크·UI 효과까지 같은 완료 모델에 연결하려면 저장소형 `READ/WRITE/SPLICE` 계약에서 벗어나는 별도 설계와 앱 검증이 필요하다.