분석 엔진 만들기 — 용신 판단과 신살 22종

 


기둥은 세워졌다, 이제 읽어야 한다

6편에서 8편까지 만세력과 시간 보정을 다뤘다. 사주 네 기둥(연주, 월주, 일주, 시주)이 정확하게 계산되는 상태가 됐다. 하지만 네 기둥은 그 자체로는 "데이터"일 뿐이다. 이 데이터를 "의미"로 바꾸는 것이 분석 엔진의 역할이다.

분석 엔진이 수행하는 작업은 크게 네 가지다. 오행 비율 분석, 십신 관계 파악, 용신 판단, 그리고 합충형파해 검출. 여기에 12운성 배치와 신살 판정, 대운/세운 계산이 추가된다. 이번 편에서는 이 중 가장 핵심적인 용신 판단과, 가장 많은 논의를 거친 신살 구현을 중심으로 이야기한다.

용신(用神): 사주의 처방전

용신은 사주 해석의 핵심 개념이다. 한 마디로 말하면, 사주에서 가장 필요로 하는 오행(또는 십신)이 무엇인가를 판단하는 것이다. 의학에 비유하면 진단 후 처방을 내리는 과정과 같다. 사주의 오행 구성을 진단하고, 균형을 맞추기 위해 무엇이 필요한지를 처방하는 것이다.

용신 판단법은 크게 세 가지 학파가 있다. 억부법(抑扶法)은 일간(日干, "나 자신")이 강한지 약한지를 판단하고, 강하면 억제하고 약하면 도와주는 오행을 용신으로 삼는다. 조후법(調候法)은 태어난 계절을 중시하여, 추운 계절에 태어났으면 따뜻한 오행을, 더운 계절에 태어났으면 시원한 오행을 용신으로 삼는다. 통변법(通變法)은 사주 전체의 흐름과 구조를 종합적으로 읽어 용신을 판단한다.

우리 앱에서는 억부법을 기본으로 채택했다. 이유는 세 가지다. 첫째, 가장 체계적으로 규칙화되어 있어 코드로 구현하기에 적합하다. 둘째, 현대 명리학에서 가장 널리 사용되는 방법이다. 셋째, 벤치마킹한 전문 앱들도 대부분 억부법을 기본으로 채택하고 있었다.

억부법의 알고리즘화

억부법을 코드로 구현하는 과정을 간략히 설명하면 이렇다.

첫 번째 단계는 일간의 강약 판단이다. 일간과 같은 오행(비견, 겁재)이 사주에 얼마나 있는지, 일간을 생해주는 오행(편인, 정인)이 얼마나 있는지를 합산한다. 이것이 일간의 "힘"이다. 반대로 일간을 극하는 오행(편관, 정관), 일간이 극하는 오행(편재, 정재), 일간이 생하는 오행(식신, 상관)의 합이 일간에 대한 "저항"이다.

이 판단에는 단순한 개수 세기 이상의 로직이 필요하다. 월지(月支)의 영향력이 가장 크다. 월지가 일간과 같은 오행이면 "득령(得令)"이라 하여 일간이 크게 강해진다. 일간이 지지에 뿌리를 두고 있으면 "통근(通根)"이라 하여 역시 강해진다. 이런 부가 조건들을 가중치로 반영해야 정확한 강약 판단이 가능하다.

두 번째 단계는 용신 결정이다. 일간이 강하면 일간을 약하게 만드는 오행이 용신이 된다. 일간이 약하면 일간을 강하게 만드는 오행이 용신이 된다. 이 로직 자체는 단순해 보이지만, "얼마나 강해야 강한 것인가"의 임계값 설정이 미묘하다. 수치적으로 정확한 경계가 존재하지 않기 때문이다.

설계 문서에서 정한 원칙은, 점수화 방식을 사용하되 절대적 기준이 아닌 상대적 비율로 판단하는 것이었다. 일간 측의 점수가 전체의 50%를 넘으면 "신강(身強)", 50% 미만이면 "신약(身弱)"으로 분류한다. 이 50%라는 기준도 학파마다 다르지만, 가장 보편적으로 사용되는 수치를 채택했다.

AI와의 협업에서 특히 유용했던 부분은 점수 가중치 설정이었다. 월지의 가중치를 얼마로 할 것인가, 통근의 가중치는 얼마인가 — 이런 세부 수치를 Claude가 명리학 이론을 참조하여 제안했고, 전문 앱의 결과와 비교하여 조정했다.

신살 22종: P3에서 필수로 격상된 이유

프로젝트 초기 설계에서 신살(神煞) 기능은 P3(향후 확장)로 분류했다. 오행 분석, 십신, 용신이 핵심이고, 신살은 부가 기능이라고 판단했기 때문이다.

이 판단이 바뀐 것은 벤치마킹 과정에서였다. 전문 사주 앱들을 하나하나 살펴보니, 예외 없이 20종 이상의 신살을 표시하고 있었다. 그리고 사주에 관심 있는 사용자들이 가장 자주 검색하는 키워드를 조사해보니, "내 사주 역마살", "도화살 있는 사주", "천을귀인 뜻" 같은 신살 관련 검색이 상위를 차지하고 있었다.

사용자 관점에서 생각해보면 당연한 일이다. "오행 비율이 木 30%, 火 20%"라는 정보보다 "당신의 사주에 역마살이 있습니다"라는 정보가 훨씬 직관적이고 관심을 끈다. 전문 용어지만 이름만으로도 의미가 짐작되는 신살은, 사주 초심자에게 진입점 역할을 한다.

결국 신살을 P3에서 P1(필수)으로 격상했다. 총 22종의 신살을 구현했는데, 크게 세 가지 카테고리로 나뉜다.

길신(吉神)은 긍정적 의미의 신살이다. 천을귀인(天乙貴人)은 귀인의 도움을 받는 기운, 문창귀인(文昌貴人)은 학문과 시험에 유리한 기운, 천덕귀인(天德貴人)과 월덕귀인(月德貴人)은 하늘과 달의 덕을 받는 기운이다.

흉신(凶神)은 주의가 필요한 신살이다. 양인(羊刃)은 강렬하고 날카로운 기운, 공망(空亡)은 비어 있는 기운, 백호살(白虎煞)은 사고나 질병에 주의가 필요한 기운이다.

그리고 상황에 따라 길흉이 달라지는 신살도 있다. 역마살(驛馬煞)은 이동과 변화의 기운인데, 긍정적이면 해외 진출이나 활발한 활동을, 부정적이면 안정하지 못하는 방황을 의미한다. 도화살(桃花煞)은 매력과 이성 관계의 기운인데, 긍정적이면 인기와 매력을, 부정적이면 색정 문제를 의미한다.

신살 구현의 실제

신살의 구현 자체는 기술적으로 단순하다. 대부분 "일주(또는 연주)의 지지가 X일 때, 사주에 Y 지지가 있으면 Z살이 있다"라는 조건 테이블이다. 천을귀인의 경우, 일간이 甲이면 丑과 未에 천을귀인이 있고, 일간이 乙이면 子와 申에 있다. 이런 매핑을 10개 일간 각각에 대해 정의하면 된다.

Claude가 22종 신살 각각의 판정 조건을 정확하게 테이블로 정리해준 것이 구현 시간을 크게 단축했다. 다만 여기서도 학파별 차이가 있었다. 천을귀인의 매핑에서 일간 庚의 경우, 丑과 未로 보는 학파와 艮과 坤으로 보는 학파가 있다. 이런 차이를 AI가 미리 알려줬고, 설계 문서에 기록된 원칙("가장 보편적인 기준을 기본값으로")에 따라 선택했다.

22종의 신살 테이블을 한꺼번에 구현하면서 느낀 것은, 이 작업이 AI 없이는 상당히 고통스러웠을 것이라는 점이다. 22개 신살 각각의 판정 조건을 명리학 서적에서 일일이 찾아서 정리하는 것은, 도메인 전문가가 아닌 개발자에게는 수일이 걸릴 작업이다. AI가 이 데이터를 한 번에 구조화해서 제공해준 덕분에, 구현과 검증에 집중할 수 있었다.

대운(大運)과 세운(歲運): 시간 축의 분석

사주 네 기둥이 "타고난 운명의 지도"라면, 대운과 세운은 "시간에 따라 변하는 환경"이다. 사주 상담에서 사용자가 가장 많이 묻는 질문이 "올해 운은 어떤가요"인데, 이 질문에 답하는 것이 바로 대운과 세운이다.

대운은 10년 단위의 큰 운이다. 월주를 기준으로 60갑자를 순행 또는 역행하며, 각 대운이 10년간 지속된다. 순행인지 역행인지는 성별과 연간의 음양에 따라 결정된다. 남자이면서 연간이 양간이면 순행, 남자이면서 연간이 음간이면 역행. 여자는 그 반대다.

대운의 시작 나이를 계산하는 것도 독특한 로직이다. 출생일로부터 다음 절기(순행) 또는 이전 절기(역행)까지의 날수를 세고, 그 날수를 3으로 나눈 값이 대운 시작 나이가 된다. 예를 들어 출생일부터 다음 절기까지 21일이면, 대운 시작 나이는 7세다.

세운은 매년의 운이다. 해당 연도의 간지(천간+지지)가 사주와 어떤 관계를 맺는지를 분석한다. 2025년은 을사년(乙巳年)이므로, 사주에 乙과 巳가 미치는 영향을 해석한다. 세운은 대운과 겹쳐서 작용하므로, "대운 + 세운 + 원국(사주)"의 삼중 구조를 종합적으로 봐야 한다.

구현에서 가장 까다로웠던 부분은 대운 시작 나이 계산이다. 출생일로부터 절기까지의 날수를 정확히 세려면, 앞서 확보한 KASI 절기 데이터가 다시 필요하다. 만세력 모듈과 분석 엔진이 같은 절기 데이터를 공유하는 구조가 자연스럽게 만들어졌고, 이것이 6편에서 세운 "단계별 독립 함수 + 공유 데이터" 아키텍처의 강점을 보여주는 사례가 됐다.

단위 테스트: 만세력과 사주는 반드시 테스트해야 한다

분석 엔진을 구현하면서 단위 테스트의 중요성을 절실히 느꼈다. 일반적인 웹 앱에서 단위 테스트는 "있으면 좋은 것"인 경우가 많다. 사주 앱에서는 "없으면 안 되는 것"이다.

이유는 간단하다. 만세력 계산이나 십신 판정에서 하나가 틀리면, 그 위에 쌓인 모든 분석과 해석이 무너진다. 그런데 이 오류는 눈에 잘 보이지 않는다. "甲木 일간의 편재는 戊土"라는 결과가 나왔을 때, 이것이 맞는지 틀린지를 육안으로 확인하려면 명리학 지식이 필요하다.

Vitest로 작성한 테스트는 크게 세 가지 영역을 커버한다. 첫째, 기초 데이터 테스트. 천간-지지의 오행 매핑이 정확한지, 60갑자 순서가 맞는지, 지장간 테이블이 올바른지를 검증한다. 둘째, 사주 기둥 계산 테스트. 특정 생년월일시를 입력했을 때 네 기둥이 정확히 나오는지를 검증한다. 이때 전문 만세력 사이트의 결과를 기대값으로 사용한다. 셋째, 분석 결과 테스트. 특정 사주의 오행 비율, 십신 배치, 용신이 기대값과 일치하는지를 검증한다.

테스트 케이스를 작성할 때 가장 유용했던 것은, 절기 경계에 해당하는 출생일을 집중적으로 테스트하는 것이었다. 입춘 당일, 경칩 당일, 야자시 시간대, 서머타임 기간 등 엣지 케이스에서 결과가 정확한지를 확인하면, 일반적인 케이스는 자연스럽게 커버된다.

Claude가 테스트 케이스 생성에서도 큰 도움을 줬다. "입춘 경계, 야자시, 서머타임 기간에 해당하는 테스트 케이스를 만들어줘"라고 요청하면, 각 상황에 맞는 구체적인 생년월일시와 기대 결과를 제시해줬다. 물론 이 기대값은 전문 만세력 사이트로 직접 검증한 후에 테스트에 반영했다.

이 과정에서 배운 것

첫째, 용신 판단은 "규칙의 명확한 부분"과 "해석이 필요한 부분"의 경계에 있다. 강약 판단의 큰 틀은 코드로 구현 가능하지만, 미세한 가중치와 임계값은 경험적 판단이 필요하다.

둘째, 사용자가 실제로 원하는 기능과 개발자가 중요하다고 생각하는 기능은 다를 수 있다. 신살이 P3에서 P1으로 격상된 것은 벤치마킹 덕분이다. "만들기 전에 쓰기"의 가치를 다시 한번 확인했다.

셋째, 대운/세운 계산은 만세력 모듈과 분석 엔진이 같은 데이터를 공유해야 하므로, 아키텍처의 데이터 흐름 설계가 올바르지 않으면 나중에 큰 리팩토링이 필요하다.

넷째, 사주 도메인에서 단위 테스트는 선택이 아니라 필수다. 눈에 보이지 않는 계산 오류가 전체 앱의 신뢰도를 무너뜨릴 수 있기 때문이다.

다섯째, AI는 대량의 도메인 데이터 테이블(신살 22종의 판정 조건 등)을 한 번에 구조화하는 데 탁월하다. 하지만 그 데이터의 정확성은 반드시 외부 소스로 검증해야 한다.

다음 편 예고

분석 엔진이 완성됐다. 사주 네 기둥이 계산되고, 오행 비율이 나오고, 십신이 판정되고, 용신이 결정되고, 신살이 검출된다. 이제 이 결과가 정말로 맞는지 검증해야 한다. 전문 앱들과 교차 검증하면서 발견한 차이, "정답이 여러 개"일 때의 테스트 전략, 그리고 만세력 정확도가 모든 것을 좌우하는 현실을 10편에서 다룬다.

댓글

이 블로그의 인기 게시물

사랑을 직접 올리지 않는 설계

감정을 변수로 옮기다 — 3계층 감정 모델

시작의 충동 — "타로 웹앱을 만들어볼까?"