본문 바로가기
C.W.K.
Lesson 02 of 05 · published

형제 다섯, 원리는 하나

~15 min · worked-example, principle, roles, siblings

Level 0밑준비
0 XP0/43 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

뿌리 클래스 하나

설계 문서가 예로 드는 요리는 감바스 알 아히요야. 마늘 향을 낸 올리브유에 새우를 익힌 거. 이 요리의 뿌리 클래스는 한 문장이면 돼. 향을 기름에 먼저 옮기고, 그 기름에서 익힌다. 이게 Sizzle이 말하는 원리야. 요리 이름이 아니라 하는 일로 이름을 붙이고, 왜 되는지를 가스레인지 앞에서 말로 설명할 수 있어.

이유는 이래. 마늘, 고추, 파의 향 성분은 상당수가 물보다 기름에 훨씬 잘 녹아. 약한 불이 그 성분을 향채에서 기름으로 끌어내. 두 번째 단계에서 주재료를 그 기름에 넣으면, 기름이 닿는 겉면마다 향이 입혀져서 나와. 순서가 기법의 전부야. 마늘을 마지막에 넣으면 그냥 맨 기름에 마늘 조각이 떠 있을 뿐이야.

이 문장엔 인터페이스도 있어. 향을 낼 재료, 그 향을 받을 기름, 기름에서 익을 주재료, 그리고 열. Sizzle의 읽기 루브릭이 역할 이름 예시로 드는 게 딱 이 넷이야. 향채, 기름, 주재료, 열. 빈칸을 다르게 채우면 같은 클래스에서 다른 요리가 나와.

형제 다섯

아키텍처 문서는 형제 다섯을 꼽고, 이걸 다섯 나라 요리에 원리는 하나라고 정리해.

요리향채기름그 기름에서 익는 것
감바스 알 아히요(스페인), 뿌리 예시마늘, 말린 고추올리브유새우
알리오 올리오(이탈리아)마늘, 고춧가루올리브유스파게티, 기름에 버무려
버섯 아히요(또 스페인)마늘올리브유버섯
파기름 볶음밥(한국)대파향 없는 식용유지은 밥
중국식 향채 볶기, 爆香(바오샹)생강, 마늘, 파뜨거운 웍 기름뒤에 들어가는 건 뭐든
소프리토, 파에야의 바탕(스페인)양파, 마늘, 토마토올리브유육수 붓기 전에 섞어 넣는 쌀

표를 세로로 한 칸씩 읽어 내려가 봐. 클래스가 저절로 보여. 기름은 거의 안 바뀌어. 향채는 나라마다 바뀌고, 주재료는 끼니마다 바뀌어. 두 단계는 절대 안 바뀌고.

원칙: 형제는 같은 역할을 다른 값으로 채운 요리야. 겉모습이 닮았는지는 상관없어.

데이터로 옮긴 예시

문서는 이 예시 하나로 Sizzle의 객체를 하나씩 다 거쳐 가. 지명만 빼고 옮겨볼게.

  1. 타파스 바에서 찍은 사진 한 장이 만남이 돼.
  2. 읽기는 감바스 알 아히요라고 높은 확신으로 이름 붙이고, 기니야 고추라고 중간 확신으로 적어. 빨간 조각이 피멘톤일 수도 있으니까. 그리고 향과 기름에 관한 원리를 제안해서 연결해.
  3. 요리하는 사람이 그 원리를 채택하고 고추 부분을 고쳐.
  4. 원리 페이지엔 알리오 올리오랑 파기름 볶음밥이 추론된 형제로 올라와.
  5. 나중에 집에서 들기름으로 이 요리를 해. 그 사진이 두 번째 만남이 되고, 종류는 집에서 해 먹은 거야. 이 만남은 기름을 오버라이드한 변형에 묶여. 계보는 이렇게 읽혀. 타파스 바 감바스 → 들기름 감바스.

이건 설계를 설명하려고 만든 이야기로 읽어. 객체가 전부 한 줄거리에 들어가 있어. 붙잡힌 인스턴스, 제안된 클래스, 모델보다 앞서는 정정, 접시가 이어지기 전까진 추론으로 남는 형제, 그리고 클래스는 그대로 두고 역할 하나만 바꾸는 오버라이드.

테스트도 같은 요리를 해

엔진 테스트도 이 예시를 그대로 써. 그래서 읽기가 실제로 돌려주는 데이터 모양을 볼 수 있어. backend/tests/conftest.py의 가짜 피파는 모든 읽기에 감바스 한 접시로 답해. 답에 든 건 바인딩 셋(향채는 마늘, 기름은 올리브유, 주재료는 새우), 하는 일로 이름 붙인 원리 하나, 형제 둘, 그리고 고추를 두고 솔직하게 품은 의심 하나야. 원리의 why엔 화학이 한 줄로 들어 있어. 마늘의 향 성분은 지용성이라서 기름에 잘 녹는다는 거.

첫 번째 트리 테스트는 설계가 약속한 걸 확인해. 읽기 한 번이 끝나면 트리엔 원리가 하나 있고, 아직 제안 상태야. 감바스는 만난 요리야. 찍어 둔 접시가 거기 이어져 있으니까. 문서는 이걸 아빠가 먹었다는 증거라고 풀어 쓰지만, 쿼리는 어떤 접시였는지 안 물어. 그래서 시장에서 본 접시도 쳐. 요리를 cooked로 만드는 건 집밥 접시뿐이고, 이 틈은 트랙 2에서 다시 봐. 알리오 올리오는 추론된 요리야. 피파가 끌어냈을 뿐 아직 이어진 접시가 없거든. 파기름 볶음밥은 한국어 이름 그대로 트리에 들어가 있어. 이 객체들은 트랙 2에서 열어보고, 트랙 4에서 자라는 과정을 따라가. 여기선 모양만 보면 돼. 사진 한 장, 클래스 하나, 나라를 넘나드는 형제들.

OO Quest의 트랙 4에도 나라를 넘나드는 다형성을 다루는 절이 있어. 거기서 공유되는 구조는 맛의 축이야. 짠맛을 어디서 얻는지, 기름은 뭘 쓰는지, 감칠맛은 뭘로 내는지. 여기서 공유되는 건 역할을 가진 기법이고. 둘 다 읽고 나면 같은 부엌을 두 방식으로 쪼개 볼 수 있어.

Code

cwkSizzle, backend/tests/conftest.py: 엔진 테스트가 전부 받는 가짜 읽기, 데이터로 옮긴 예시 (원문 그대로, 24-60행)·python
GAMBAS = {
    "summary": "마늘과 고추를 넣은 올리브유에 새우를 익힌 감바스 알 아히요 한 접시.",
    "dishes": [
        {
            "name_original": "Gambas al ajillo",
            "name_ko": "감바스 알 아히요",
            "cuisine": "스페인 안달루시아",
            "confidence": "high",
            "evidence": "토기 그릇의 기름, 마늘 조각, 새우",
            "dish_ref": "",
            "techniques": [{"name": "기름에 향 우리기", "confidence": "high"}],
            "bindings": [
                {"role": "향채", "value": "마늘", "confidence": "high"},
                {"role": "기름", "value": "올리브유", "confidence": "high"},
                {"role": "주재료", "value": "새우", "confidence": "high"},
            ],
            "principles": [
                {
                    "ref": "",
                    "name": "향을 기름에 먼저 옮기고 그 기름에서 익히기",
                    "summary": "향채의 향을 기름에 먼저 녹인 뒤 그 기름으로 주재료를 익힌다.",
                    "why": "마늘의 향 성분은 지용성이라 기름에 잘 녹는다.",
                    "roles": [{"role": "향채", "examples": ["마늘", "파"]}],
                    "method": ["약불에서 향채를 기름에 우린다", "주재료를 넣고 익힌다"],
                    "confidence": "high",
                }
            ],
            "siblings": [
                {"name_original": "Aglio e olio", "name_ko": "알리오 올리오", "cuisine": "이탈리아",
                 "principle": "향을 기름에 먼저 옮기고 그 기름에서 익히기", "why_same": "마늘 기름에 파스타를 버무린다"},
                {"name_original": "파기름 볶음밥", "name_ko": "파기름 볶음밥", "cuisine": "한국",
                 "principle": "향을 기름에 먼저 옮기고 그 기름에서 익히기", "why_same": "파 향을 낸 기름에 밥을 볶는다"},
            ],
        }
    ],
    "unsure": ["빨간 조각이 기닐라 고추인지 피멘톤인지 확실하지 않아."],
}
cwkSizzle, backend/tests/test_tree.py: 읽기 한 번이면 제안된 원리, 만난 요리, 추론된 형제가 생겨 (원문 그대로, 11-23행)·python
def test_a_reading_grows_the_tree_with_evidence(make_client, fake_pippa):
    client = make_client()
    encounter_id = capture(client, "req-tree-001")["encounter"]["id"]
    body = _read(client, encounter_id)
    assert body["view"]["unsure"], "doubts are carried, not hidden"
    tree = client.get("/api/tree").json()
    assert len(tree["principles"]) == 1
    principle = tree["principles"][0]
    assert principle["status"] == "proposed"
    by_name = {d["name"]: d for d in principle["dishes"]}
    assert by_name["Gambas al ajillo"]["evidence"]["status"] == "encountered"
    assert by_name["Aglio e olio"]["evidence"]["status"] == "inferred"
    assert "파기름 볶음밥" in by_name

External links

Exercise

이미 감으로 하는 기법 하나를 골라. 찜이든, 빠른 절임이든, 루든 좋아. 그걸 원리로 적어봐. 무엇을 하는지 한 문장, 왜 되는지 한 문장, 그리고 역할들. 이어서 서로 다른 세 나라에서 형제 셋을 찾아 표를 채워. 칸은 요리 이름, 역할마다 채운 값, 바뀌지 않는 것이야. 후보 중에 원리에 없는 역할이 필요한 게 있으면 판단해. 부모가 둘인 요리야, 아니면 아예 다른 클래스야?
Hint
역할은 바꿔 끼워 보면서 시험해. 값을 바꿔도 여전히 같은 집안 요리로 알아볼 수 있으면 역할을 제대로 짚은 거야. 바꿨더니 기법이 무너지면 방법의 일부를 짚은 거고. 요리는 원리 둘을 물려받을 수 있어. Sizzle 루브릭은 요리 하나에 뿌리 원리 하나, 많아야 둘까지 허락해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.