사전이 멈춘 것은 사전이 모자라서가 아니라, 사전에 들어갈 수 없는 것들이 사전 문 앞에 줄을 섰기 때문이다. 낱말·목록·방향은 서로 다른 재료이고, 우벨에는 이미 세 재료의 집이 각각 있다.
각 답의 첫 줄이 규칙이고, 나머지는 그 규칙이 실전(방금 고친 버그·경고문 사고)에서 어떻게 작동하는지다.
Q1 · 사전의 경계는 어디인가?
문장 틀 자체가 달라지면(청원 올림 ↔ 심의) 그건 낱말이 아니라 역할 — 약속 층으로. 빈칸에 들어갈 값이 여러 개면(당회·제직회·공동의회…) 그건 낱말이 아니라 목록 — 등록부 층으로. 이 한 줄이면 사전은 화면이 늘어도 자라지 않는다. 새 화면은 새 문장을 가져올 뿐이고, 그 문장의 빈칸은 대개 이미 사전에 있는 낱말이다. 유형×화면 곱셈은 규칙 위반의 증상이지 사전의 숙명이 아니다.
Q2 · 회의·증명서처럼 "목록"인 낱말은?
신설 org_kind_presets(kind_key, domain, label, sort, enabled) 한 테이블에 domain = 'meeting_kind' | 'cert_type' | 'petition_type' 로 담는다. 배열을 사전에 넣지 않는 이유 셋. ① 조직마다 다르게 쓰고 싶어질 축이 맞다 — 같은 kind='school' 안에서도 초·중·고는 학부모회, 호남신학대는 교수회의다. 뒤에 org 단위 덮어쓰기 한 층만 얹으면 되는 구조는 등록부뿐이다. ② 켜고 끄기·순서 바꾸기가 필요한데 TS 상수는 배포 없이는 못 한다. ③ 결정타 — 청원 안건은 심의자(노회)가 정의하고 청원자(교회) 화면이 그걸 읽어야 한다. 코드 상수로는 아예 표현이 안 되는 소유 관계다.
Q3 · 청원처럼 방향이 뒤집히는 것은?
"약속에 적힌 것만 흐른다." 청원도 흐르는 것이므로 약속을 따른다. 나가는 심의 약속이 있으면 청원자 얼굴, 들어오는 심의 약속이 있으면 심의자 얼굴, 둘 다면 두 탭(협의회가 교회에게 받으며 교단에 올리는 경우), 둘 다 없으면 화면 자체가 없다(학교 — 방금 고친 버그가 구조적으로 재발 불가능해진다). audienceIsOrgs 는 겸직을 해고하고 본업(문장의 단위 낱말 고르기)으로 복귀시킨다. kind 로 방향을 추측하는 isUpperOrg 분기는 약속 조회로 대체될 과도기 장치로 격하한다.
Q4 · 유형 8종을 다 채울 것인가?
사전의 낱말 15개는 전부 보편 개념이다 — 알림·구성원·명부·회의록 없는 조직은 없으므로 관공서·기타도 중립어로 다 채운다(지금 GENERIC 그대로). 반대로 당회·안수는 보편이 아니고, 보편이 아니라는 사실 자체가 그것이 사전이 아니라 등록부에 있어야 한다는 증거다. 관공서에 청원 화면을 "빈 값"으로 두면 깨진 화면이 되고 "중립어"로 두면 거짓 화면이 된다. 감추는 게 답인데, 감추는 판단을 코드 분기로 하면 원칙이 무너진다 — 등록부에 행이 없으면 안 뜬다. _default 폴백(회의·재정·증명)이 이미 그 관행이다.
Q5 · 낱말이 이 조직 것인지 하위 조직 것인지, 사전이 스스로 말하게 할 수 있나?
unitMember · unitRoster · unitLeader 를 신설한다. 노회의 roster는 "소속 교회 명단", unitRoster는 "각 교회의 명부" — 사고가 났던 그 경고문이 쓸 낱말은 처음부터 후자였다. audienceIsOrgs=false 인 조직은 두 층이 겹치므로 unit* 가 자기 낱말과 같은 값이다(교회의 unitRoster = 명부). 화면 코드 금칙 하나를 함께 세운다 — vocab 낱말 앞에 "각·소속·하위"를 붙여 합성하는 순간이 버그다. 그 합성어가 필요하면 사전 필드로 승격하라. 층을 문장이 아니라 타입이 지게 하는 것이다.
기존 11개는 전부 유지(기존 규칙 — 권한·수신자 판정 금지 — 도 유지). 더해지는 것은 4개뿐이고, 각각 "같은 문장, 빈칸 하나" 검사를 통과한 낱말이다. 행정이 요구하는 나머지는 전부 다른 층으로 보낸다.
| 필드 | 구분 | 무엇을 담나 | 왜 사전에 있어야 하나 |
|---|---|---|---|
| 유지 — 기존 11개 | |||
| kind | 유지 | 유형 이름 — 교회·학교·노회 | 모든 문장의 주어 자리. 빈칸 하나. |
| post · postVerb | 유지 | 전원 발신물과 그 서술어 — 광고를 보냅니다 / 공문을 내려보냅니다 | 같은 문장 틀, 빈칸 둘이지만 각각 하나짜리. |
| member · roster | 유지 | 이 조직 자신의 구성원과 그 표 — 성도/명부, 소속 교회/소속 교회 명단 | Q5 규칙에 따라 의미가 "자기 층"으로 좁게 못박힌다. |
| followUp · followUpTarget | 유지 | 못 본 이에게 하는 일 — 심방 / 개별 연락 | 확인 현황 화면의 핵심 문장. |
| leader · care | 유지 | 맡은 사람·돌봄 축 — 목사님/목양, 선생님/생활지도 | 호칭과 축 이름은 낱말 하나. |
| audienceIsOrgs | 유지 ·감직 | 수신자가 사람이 아니라 하위 조직인가 | 본업 복귀 — 문장 단위 고르기 표시로만. 청원 방향 판정 겸직은 약속 층이 가져간다. |
| audienceUnit | 유지 | 세는 단위 — 명·교회·조직 ("분" 금지 규칙 포함) | 숫자 옆 낱말 하나. |
| 신설 — 4개 | |||
| minutes | 신설 | 회의의 기록물 — 회의록 · 노회록 · 총회록 | "{…}을 남깁니다" — 같은 문장, 빈칸 하나. 지금은 meetings 화면 설명문에 하드코딩돼 있다. |
| unitMember | 신설 | 하위 조직 안의 사람 — 노회에서 "성도" | Q5. 상위 조직 화면이 두 층을 한 문장에 같이 쓴다("교회가 수락하면 성도에게…"). |
| unitRoster | 신설 | 하위 조직 안의 명부 — 노회에서 "각 교회의 명부" | 사고 재발 방지 필드. 경고문이 정반대가 됐던 자리에 들어갈 바로 그 낱말. |
| unitLeader | 신설 | 하위 조직을 맡은 사람 — 노회에서 "담임 목사님" | 개통·초대 문장이 이미 쓰고 있는 말인데 지금은 하드코딩("담임 목사님 번호를 적으면…"). |
| 일부러 빠지는 것 — 다른 층의 재료 (상세는 E) | |||
| meetingKinds[] certTypes[] petitionTypes[] | 등록부 | 당회·제직회… / 교인·재직·세례… / 청빙·임직… | 값이 여러 개 + 조직별 커스텀 축 + 청원 안건은 심의자 소유. 셋 다 사전 실격 사유. |
| 화면 제목·부제·섹션 | 등록부 | "회의 관리"·"인사·고시"·묶음 라벨 | org_kind_sections 가 이미 소유. 머리말은 `${kind} 행정` 합성으로 충분. |
| 청원 방향·역할 | 약속 | 올리는 쪽 / 심의하는 쪽 / 양쪽 / 없음 | 낱말이 아니라 관계의 성질. 그래프에서 도출. |
unitMember=member · unitRoster=roster · unitLeader=leader.
교회·학교·일반 조직에서 unit* 는 그냥 자기 낱말이다. 화면은 층을 따지지 않고 항상 올바른 필드를 골라 쓰면 되고, 값이 갈리는 것은 상위 조직에서뿐이다.
위 블록은 사전(코드), 아래 블록은 등록부(DB 시드)와 약속(그래프) — 같은 표에 두되 층 표시를 단다. 빈 칸은 빈 채로 두고 이유를 적었다. 노회 열은 교단·협의회·종교가 이름만 갈아 끼우는 자리다.
| 낱말 | 교회 광주양림교회 |
학교 호남신학대학교 |
노회 (교단·협의회) 전남노회 |
일반 조직 other · gov_office |
|---|---|---|---|---|
| ① 사전 층 — orgVocab.ts | ||||
| kind | 교회 | 학교 | 노회 · 교단 · 협의회 | 조직 · 관공서 |
| post | 광고 | 공지 | 공문 | 알림 |
| member | 성도 | 학생·학부모 | 소속 교회 | 구성원 · 직원 |
| roster | 명부 | 명부 | 소속 교회 명단 | 명부 |
| leader | 목사님 | 선생님 | 노회장님 · 총회장님 · 회장님 | 담당자 |
| care | 목양 | 생활지도 | 돌봄 | 케어 |
| minutes 신설 | 회의록 | 회의록 | 노회록 · 총회록 · 회의록 | 회의록 |
| unitMember 신설 | = 성도 (겹침) | = 학생·학부모 (겹침) | 성도 | = 구성원 (겹침) |
| unitRoster 신설 | = 명부 (겹침) | = 명부 (겹침) | 각 교회의 명부 | = 명부 (겹침) |
| unitLeader 신설 | = 목사님 (겹침) | = 선생님 (겹침) | 담임 목사님 | = 담당자 (겹침) |
| audienceUnit | 명 | 명 | 교회 · 조직 | 명 |
| ② 등록부 층 — org_kind_presets 시드 (조직이 덮어쓸 수 있다) | ||||
| 회의 종류 | 당회 · 제직회 · 공동의회 · 임원회 | 교무회의 · 운영위원회 · 이사회 시드는 초·중·고 기준. 호남신학대는 org 덮어쓰기로 교수회의·처장회의 — 같은 kind 안에서 갈리는 첫 실물이자, 이 축이 등록부여야 하는 증거. |
정기회 · 임시회 · 상비부 · 임원회 | 정기 모임 · 운영진 회의 · 총회 |
| 증명서 종류 | 교인 · 재직 · 세례 · 출석 증명서 | 재직 확인서(교직원) · 활동 확인서 · 수료증 ⚠재학·성적·졸업 증명은 넣지 않는다 — NEIS·정부24가 발급하는 법정 증명. 우벨이 흉내 내면 가짜 서류 제조기가 된다. 비법정 확인서만. |
소속 · 재직 · 안수 증명서 | 회원(소속) 확인서 · 활동 확인서 관공서 시드는 이것도 없음 — 관공서는 증명을 받는 곳이 아니라 떼 주는 곳이라 우벨 발급이 성립 안 함. 행 없음 = 화면 없음. |
| 청원 안건 | 안건은 심의자의 것. 교회 화면은 소속 노회가 등록한 안건(청빙 승인·임직·이명…)을 읽는다 | 심의 약속이 없으므로 읽을 안건도 없다 | 담임목사 청빙 승인 · 부목사 청빙 · 장로 임직 승인 · 목사 이명 · 목사 사임 · 교회 설립·변경 | 없음 |
| ③ 약속 층 — 그래프에서 도출 (사전·등록부 어디에도 저장하지 않는다) | ||||
| 청원 역할 | 올리는 쪽 전남노회로 나가는 심의 약속 |
역할 없음 → 화면 없음. 이사회 결재는 청원이 아니라 회의(이사회)의 일 | 심의하는 쪽 교단에 올리는 약속이 있으면 양쪽 — 두 탭 |
역할 없음 → 화면 없음 |
각 화면의 문장 틀은 하나다. 틀 위에 사전 낱말(금색 밑줄)과 등록부 목록(칩)이 얹히고, 청원만 약속이 얼굴을 고른다. 목업의 데이터는 파일럿 실물 — 지어낸 활기는 없다.
isChurch 분기와 CHURCH_KINDS/TREE_KINDS 상수는 사라진다.
회의 관리
당회·제직회·공동의회를 열고 회의록을 남깁니다.
회의 관리
교수회의·처장회의를 열고 회의록을 남깁니다.
칩이 학부모회가 아닌 교수회의인 것은 org 덮어쓰기 — kind 시드(교무회의·운영위원회·이사회) 위에 대학이 자기 목록을 얹었다.
노회 회의
정기회·임시회를 열고 노회록을 남깁니다.
"회의록" 자리가 전부 minutes="노회록"으로 갈린다 — 목록 라벨·상세 화면까지.
회의 관리
모임을 열고 회의록을 남깁니다.
청원·인가
소속 노회에 청빙·임직·이명 등을 청원하고 결과를 받습니다.
안건 칩은 전남노회가 등록한 목록을 읽어온 것.
인사·고시
소속 교회가 올린 청원을 심의해 가결·부결합니다.
교단으로 올리는 약속이 생기면 이 화면에 "교단에 청원" 탭이 하나 더 붙는다 — 얼굴 둘, 화면 하나.
이 화면은 없다
학교에는 심의 약속이 걸려 있지 않다 — 청원 역할이 없으므로 등록부에 행이 없고, 행이 없으므로 행정 목록에 아예 나타나지 않는다. 이사회 결재가 필요하면 그것은 회의(이사회)의 일이다.
이 화면은 없다
중립어로 때운 "청원" 화면은 거짓 화면이다. 훗날 어떤 조직이 실제로 상급 단체와 심의 약속을 맺으면, 그 약속이 생기는 순간 화면이 나타난다 — 코드 수정 없이.
서무·증명
증명서를 발급하고 인쇄합니다. 발행번호가 자동으로 매겨집니다.
확인서 발급
우벨이 떼 줄 수 있는 것만 뗀다 — 비법정 확인서.
공문·증명
안수·소속·재직 증명을 발급합니다.
확인서 발급
회원(소속)·활동 확인서를 발급합니다.
관공서(gov_office)는 이 화면도 없다 — 증명을 떼 주는 기관이 우벨로 확인서를 만들 일이 없으므로 등록부에 행을 심지 않는다.
각 항목의 초록 글씨가 그것이 대신 가야 할 층이다. 거절의 공통 근거는 하나 — Q1의 한 줄 규칙을 통과하지 못한다.
빈칸 하나가 아니라 여러 개다. 유형×항목으로 곱해 부풀고, "우리 교회는 운영위원회"라는 조직별 취향이 반드시 붙는 축이라 켜고 끄고 덮어쓸 수 있는 DB 행이어야 한다.
사전은 전 유형이 전 필드를 채우는 완주형이라 "없음"을 표현할 수 없고, 표현하려 드는 순간 빈 값·중립어 같은 거짓말이 생긴다. 부재는 행이 없다는 사실로 말한다.
"교회 행정/노회 행정" 하드코딩의 답은 사전 필드 추가가 아니라 `${vocab.kind} 행정` 합성이다. 섹션 제목은 000120부터 이미 DB가 소유한다.
낱말이 아니라 관계의 성질이고, 같은 kind 라도 걸린 약속에 따라 다르다(협의회는 양쪽일 수 있다). 사전에 넣으면 audienceIsOrgs 겸직 사고를 하나 더 만드는 것이다.
orgVocab.ts 머리말이 이미 세운 금지. 실수신자는 org_announcement_recipients(000175)가, 접근은 RLS 가 정한다. 사전은 문장을 고를 뿐 문을 열지 않는다.
사전이 문장을 갖는 순간 화면 수만큼 자란다. 화면이 문장 틀을 소유하고 사전은 빈칸만 메운다. 단, 화면이 낱말 앞에 "각·소속·하위"를 붙여 합성하면 그것이 Q5 사고다 — 합성어가 필요하면 unit* 필드로 승격.
증명서의 본문 문구·서식은 낱말이 아니라 문서다. 그리고 재학·성적처럼 법이 발급 주체를 정한 서류는 어느 층에도 넣지 않는다 — 만들지 않는 것이 설계다.
사전은 유형의 것이다. "우리는 교수회의라고 부른다"는 kind='school' 의 사전을 고칠 일이 아니라 호남신학대 한 조직의 등록부 행을 덮어쓸 일이다. 취향이 사전에 스미면 유형이 조직 수만큼 쪼개진다.