복잡한 관계형 로직의 데이터베이스 - 설계

Pt J·2026년 4월 29일
post-thumbnail

복잡한 관계형 로직의 데이터베이스 - 설계

데이터 사이의 복잡한 관계를 효율적으로 필터링하는 방법을 알아보자.
음양오행의 조화와 상호작용을 담는 데이터베이스를 만들어 보겠다.

60갑자는 10가지 천간과 12가지 지지가 조합되어 구성된다.
60개의 글자는 서로 상호작용하여 어떤 관계를 이룬다.
깊게 들어가면 너무 방대해지므로 여기선 간단한 관계만 살펴보겠다.

각 천간과 지지가 가진 음양오행 속성과
글자들간의 합/충/형/파 관계,
그리고 프로필 정보는 데이터베이스를 통해 관리하고
만세력 변환 및 분석은 Rust 로직으로 구현하겠다.
분석된 데이터는 다시 데이터베이스에 JSONB로 저장한다.

전반적인 흐름은 다음과 같다.

  1. 입력 (Input): 사용자가 생년월일시를 입력하면, Rust 엔진의 만세력 로직이 이를 8개의 간지 코드로 변환합니다.
  2. 저장 (Store): 변환된 간지 코드와 기본 정보를 saju_profiles에 저장합니다.
  3. 분석 (Analyze): Rust 엔진이 DB의 ganji_interactions(정적 관계)를 참고하여 이 사주의 특징(오행 균형, 합충 등)을 계산합니다.
  4. 캐싱 (Cache): 계산된 복잡한 결과물을 JSON 객체로 만들어 analysis_result 필드에 UPDATE 합니다.
  5. 조회 (Query): 이후 사용자가 프로필을 볼 때는 다시 계산할 필요 없이 JSONB 필드만 읽어서 보여줍니다. 만약 "목(Wood) 기운이 30점 이상인 사람"을 찾는다면 GIN 인덱스를 통해 빠르게 필터링합니다.

작업공간 생성 및 구조 확인

기존에 만든 데이터베이스 템플릿을 복제해서 사용해 보겠다.

~/workspace$ cp -r db-template saju-analysis
~/workspace$ cd saju-analysis
~/workspace/saju-analysis$ tree -a -I .venv
.
├── .env				# 우리 프로젝트의 DB로 연결되게 수정 필요
├── .github
│   └── workflows
│       └── CI.yml
├── .gitignore
├── app
│   └── main.py			# 우리 프로젝트의 라우트 함수 추가 필요
├── Cargo.toml			# 우리 프로젝트의 정보로 수정 필요
├── docker-compose.yml	# 우리 프로젝트의 DB로 연결되게 수정 필요
├── pyproject.toml		# 우리 프로젝트의 정보로 수정 필요
└── src
    ├── db.rs			# 우리 프로젝트에 필요한 함수 추가 필요
    ├── lib.rs			# 우리 프로젝트에 필요한 함수 추가 필요
    └── logger.rs		# 그대로 유지해도 무방

pyproject.toml 파일을 열어 프로젝트 이름을 수정해 주겠다.
나머지 의존성 부분은 이번 프로젝트에서도 사용하는 것들이니 가만히 둔다.

~/workspace/saju-analysis$ vi pyproject.toml

pyproject.toml

[build-system]
requires = ["maturin>=1.12,<2.0"]
build-backend = "maturin"

[project]
name = "saju-analysis"
requires-python = ">=3.12"
classifiers = [
    "Programming Language :: Rust",
    "Programming Language :: Python :: Implementation :: CPython",
    "Programming Language :: Python :: Implementation :: PyPy",
]
dynamic = ["version"]
dependencies = [
    "fastapi>=0.124.4",
    "orjson>=3.10.15",
    "uvicorn>=0.33.0",
]

[dependency-groups]
dev = [
    "maturin>=1.12.6",
]

다음과 같이 uv 를 통해 pyproject.toml 파일의
모든 의존성을 설치할 수 있다.

~/workspace/saju-analysis$ uv sync

마찬가지로 Cargo.toml 파일도 수정해 준다.
이 때, 필요한 크레이트도 추가해 주도록 하자.

Cargo.toml

[package]
name = "saju-analysis"
version = "0.1.0"
edition = "2024"

[lib]
name = "rust_engine"
crate-type = ["cdylib"]

[dependencies]
# Python 연결
pyo3 = "0.28.0"
pythonize = "0.28"
# 비동기 엔진
tokio = { version = "1.43", features = ["full"] }
# 데이터베이스 연결
dotenvy = "0.15"
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls", "postgres", "macros", "uuid", "chrono", "json"] }
# 데이터베이스 호환
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "1.23", features = ["v7", "serde"] }
# 로그 수집
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
tracing-appender = "0.2"

템플릿 프로젝트의 DB 정보를 그대로 사용하면 DB가 꼬이게 될 테니
DB 정보도 수정해 준다.

docker-compose.yml 의 변경 필요한 부분은 전부 환경변수로 되어 있으니
.env 파일만 편집하면 된다.

계정 정보는 그대로 사용해도 무방하지만
COMPOSE_PROJECT_NAMEPOSTGRES_DB 는 수정해 주어야 한다.

~/workspace/saju-analysis$ vi .env

.env

# Docker Compose Project
COMPOSE_PROJECT_NAME=saju-analysis

# PostgreSQL
POSTGRES_USER=peter
POSTGRES_PASSWORD=ku201711424
POSTGRES_DB=saju_db
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432

# pgAdmin
PGADMIN_EMAIL=admin@pjos.dev
PGADMIN_PASSWORD=admin201711424

# SQLX
DATABASE_URL=postgres://peter:ku201711424@127.0.0.1:5432/saju_db?sslmode=disable

재차 말하지만 학습 기록용이니까 업로드하지 .env 파일의 내용은 유출하는 거 아니다. 보안 이슈!

DB 설정

스키마

이번 실습에서는 여러 개의 데이터베이스 테이블을 사용할 것이다.

기본적인 간지 정보를 담은 테이블의 스키마는 다음과 같다.

변수명자료형설명
codeSMALLINT문자열로 관리하면 느리므로 천간(0~9), 지지(10~21)를 숫자로 관리하는 기본키
name_koCHAR(1)천간 혹은 지지의 이름 (한글)
name_haniCHAR(1)천간 혹은 지지의 이름 (한자)
typeTEXT이 글자가 천간인지 지지인지 여부
elementelement_type열거형 타입 element_type 을 정의하여 오행 표기
yin_yangyin_yang_type열거형 타입 yin_yang_type 을 정의하여 음양 표기

각 글자의 고정적인 상호작용을 담은 테이블의 스키마는 다음과 같다.

(부모)

변수명자료형설명
idINTEGER상호작용을 식별하기 위한 기본키로, 유형에 따라 백의 자리 값 다르게 설정할 것이다.
categoryVARCHAR(20)상호작용 유형

(자식1: 글자를 기준으로 그것이 가질 수 있는 상호작용 및 설명을 담고 있다.)

변수명자료형설명
idSERIAL1씩 증가하는 값으로 임의 설정된 기본키
codeSMALLINT간지 정보 테이블의 기본키를 참조하여 나타낸 기준 글자
group_idINTEGER부모 테이블의 기본키를 참조하여 기준 글자가 가질 수 있는 관계 식별
descriptionTEXT해당 상호작용에 대한 설명

(자식2: 상호작용의 해석을 담고 있다.)

변수명자료형설명
idSERIAL1씩 증가하는 값으로 임의 설정된 기본키
group_idINTEGER부모 테이블의 기본키를 참조하여 기준 글자가 가질 수 있는 관계 식별
titleVARCHAR(100)이 관계의 고유 명칭
keywordsTEXT[]이 관계가 상징하는 핵심 에너지 목록
interpretationTEXT이 관계에 대한 인문학적 해석

관계 식별 예시
사주 팔자의 여덟 글자를 중복 없이 나열하여 관계를 확인한다.
관계의 유형별로 천간합은 100번대, 천간충은 200번대 등의 그룹 ID를 지정한다.
'을'이 2개, '경'이 1개 있었어도 여기서는 '을'과 '경'을 하나씩 확인하고
(1, '합', 102, '을경합금'), (6, '합', 102, '을경합금') 과 같이
"2개가 만났을 때 합을 이루는 관계"에 대해 2개의 값이 있을 경우 이 관계가 있다고 본다.
1대1이 아닌 '을' 2개와 '경' 1개가 만나는 상황을 쟁합(爭合)이라고 하는데
이런 부분에 대한 처리는 데이터베이스가 아닌 Rust 엔진에서 하도록 하겠다.
데이터베이스에서는 단지 관계의 존재 여부만 확인한다.

개인의 사주 팔자가 담긴 사주 프로필 테이블의 스키마는 다음과 같다.

변수명자료형설명
idUUID자동으로 생성되는 고유 식별자로, 기본키로 사용된다.
nameTEXT사주 팔자 주인의 이름
genderCHAR(1)출생 시 성별에 따라 대운의 방향이 다르므로 이분법적인 성별을 사용한다.
birth_dateTIMESTAMPTZ사용자로부터 입력받은 생년월일시
is_solarBOOLEAN양력인지 여부로, TRUE 를 기본값으로 한다.
year_ganSMALLINT간지 정보 테이블의 기본키 code 를 참조하여 나타낸 연주의 천간
year_jiSMALLINT간지 정보 테이블의 기본키 code 를 참조하여 나타낸 연주의 지지
month_ganSMALLINT간지 정보 테이블의 기본키 code 를 참조하여 나타낸 월주의 천간
month_jiSMALLINT간지 정보 테이블의 기본키 code 를 참조하여 나타낸 월주의 지지
day_ganSMALLINT간지 정보 테이블의 기본키 code 를 참조하여 나타낸 일주의 천간
day_jiSMALLINT간지 정보 테이블의 기본키 code 를 참조하여 나타낸 일주의 지지
hour_ganSMALLINT간지 정보 테이블의 기본키 code 를 참조하여 나타낸 시주의 천간
hour_jiSMALLINT간지 정보 테이블의 기본키 code 를 참조하여 나타낸 시주의 지지
analysis_resultJSONBRust 엔진으로부터 전달받은 사주 분석 결과
created_atTIMESTAMPTZ데이터를 저장한 시점에 자동으로 작성되는 타임스탬프
updated_d_atTIMESTAMPTZ데이터를 수정한 시점에 자동으로 변경되는 타임스탬프

이 데이터베이스 테이블들이 존재하지 않는 경우에만
새로 생성하는 코드를 작성해 보자.

~/workspace/saju-analysis$ mkdir scripts
~/workspace/saju-analysis$ vi scripts/init.sql

scripts/init.sql

-- 간지 정보

DO $$
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'element_type') THEN
        CREATE TYPE element_type AS ENUM ('목', '화', '토', '금', '수');
    END IF;
    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'yin_yang_type') THEN
        CREATE TYPE yin_yang_type AS ENUM ('음', '양');
    END IF;
END $$;

CREATE TABLE IF NOT EXISTS ganji_metadata (
	code SMALLINT PRIMARY KEY, -- 천간: 0~9, 지지: 10-21
	name_ko CHAR(1) NOT NULL,
	name_hani CHAR(1) NOT NULL,
	type TEXT CHECK (type IN ('천간', '지지')),
	element element_type NOT NULL,
	yin_yang yin_yang_type NOT NULL
);

-- 정적 관계

CREATE TABLE IF NOT EXISTS interaction_groups (
	id INTEGER PRIMARY KEY,
	category VARCHAR(20) NOT NULL
);

CREATE TABLE IF NOT EXISTS ganji_interaction (
	id SERIAL PRIMARY KEY,
	code SMALLINT REFERENCES ganji_metadata(code) ON DELETE CASCADE,
	group_id INTEGER REFERENCES interaction_groups(id) ON DELETE CASCADE,
	description TEXT
);

CREATE TABLE IF NOT EXISTS ganji_interaction (
	id SERIAL PRIMARY KEY,
	group_id INTEGER UNIQUE REFERENCES interaction_groups(id) ON DELETE CASCADE,
	title VARCHAR(100) NOT NULL,
	keyword TEXT[] DEFAULT '{}',
	interpretation TEXT NOT NULL
);

-- 사주 팔자

CREATE TABLE IF NOT EXISTS saju_profiles (
	id UUID PRIMARY KEY DEFAULT uuidv7(),
	name TEXT NOT NULL,
	gender CHAR(1) CHECK (gender IN ('M', 'F')),
	birth_date TIMESTAMPTZ NOT NULL,
	is_solar BOOLEAN DEFAULT TRUE,

	year_gan SMALLINT REFERENCES ganji_metadata(code),
	year_ji SMALLINT REFERENCES ganji_metadata(code),
	month_gan SMALLINT REFERENCES ganji_metadata(code),
	month_ji SMALLINT REFERENCES ganji_metadata(code),
	day_gan SMALLINT REFERENCES ganji_metadata(code),
	dayr_ji SMALLINT REFERENCES ganji_metadata(code),
	hour_gan SMALLINT REFERENCES ganji_metadata(code),
	hour_ji SMALLINT REFERENCES ganji_metadata(code),

	analysis_result JSONB DEFAULT '{}',

	created_at TIMESTAMPTZ DEFAULT NOW(),
	updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_saju_birth_date ON saju_profiles(birth_date);
CREATE INDEX IF NOT EXISTS idx_saju_analysis_result ON saju_profiles USING GIN (analysis_result);

파일을 생성하지 않고 터미널에서 직접 쿼리를 날려도 되지만
따로 파일을 작성하는 편이 유지보수 측면에서 효과적이다.

docker

PostgreSQL을 docker 서비스로 실행한다.

~/workspace/saju-analysis$ docker compose up -d
~/workspace/saju-analysis$ docker ps
CONTAINER ID   IMAGE                COMMAND                   CREATED         STATUS         PORTS                                         NAMES
0e23bd848f7a   dpage/pgadmin4       "/entrypoint.sh"          8 seconds ago   Up 8 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp       pgadmin_ui
42f80ebad4a1   postgres:18-alpine   "docker-entrypoint.s…"   8 seconds ago   Up 8 seconds   0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp   saju-analysis_postgres

작성해 놓은 데이터베이스 생성 쿼리 파일을 전달한다.

~/workspace/saju-analysis$ docker exec -i saju-analysis_postgres psql -U peter -d saju_db < scripts/init.sql

다음과 같이 데이터베이스 테이블이 생성된 것을 확인할 수 있다.

~/workspace/image-assets-management$ docker exec -it saju-analysis_postgres psql -U peter -d saju_db -c "\dt"

                List of tables
 Schema |         Name         | Type  | Owner 
--------+----------------------+-------+-------
 public | ganji_interaction    | table | peter
 public | ganji_metadata       | table | peter
 public | interaction_groups   | table | peter
 public | interaction_metadata | table | peter
 public | saju_profiles        | table | peter
(5 rows)

데이터 삽입

간지 정보는 변하지 않는 값이니 스크립트에 적어 미리 넣어둔다.

~/workspace/saju-analysis$ vi scripts/insert_saju_metadata.sql

scripts/insert_saju_metadata.sql

INSERT INTO ganji_metadata (code, name_ko, name_hani, type, element, yin_yang) VALUES
-- 천간 (0~9)
(0, '갑', '甲', '천간', '목', '양'),
(1, '을', '乙', '천간', '목', '음'),
(2, '병', '丙', '천간', '화', '양'),
(3, '정', '丁', '천간', '화', '음'),
(4, '무', '戊', '천간', '토', '양'),
(5, '기', '己', '천간', '토', '음'),
(6, '경', '庚', '천간', '금', '양'),
(7, '신', '辛', '천간', '금', '음'),
(8, '임', '壬', '천간', '수', '양'),
(9, '계', '癸', '천간', '수', '음'),
-- 지지 (10~21)
(10, '자', '子', '지지', '수', '양'),
(11, '축', '丑', '지지', '토', '음'),
(12, '인', '寅', '지지', '목', '양'),
(13, '묘', '卯', '지지', '목', '음'),
(14, '진', '辰', '지지', '토', '양'),
(15, '사', '巳', '지지', '화', '음'),
(16, '오', '午', '지지', '화', '양'),
(17, '미', '未', '지지', '토', '음'),
(18, '신', '申', '지지', '금', '양'),
(19, '유', '酉', '지지', '금', '음'),
(20, '술', '戌', '지지', '토', '양'),
(21, '해', '亥', '지지', '수', '음');
~/workspace/saju-analysis$ docker exec -i saju-analysis_postgres psql -U peter -d saju_db < scripts/insert_ganji_metadata.sql

관계에 대해서도 마찬가지로 스크립트로 넣어둔다.

~/workspace/saju-analysis$ vi scripts/insert_saju_interaction.sql

scripts/insert_saju_interaction.sql

INSERT INTO interaction_groups (id, category) VALUES
(100, '천간합'), (200, '천간충'),
(300, '지지육합'), (400, '지지삼합'), (500, '지지방합'),
(600, '지지육충'), (700, '지지형'), (800, '지지파'), (900, '지지해');

-- 세부 그룹 ID (상속 관계 시각화용)
INSERT INTO interaction_groups (id, category) VALUES
(101, '천간합'), (102, '천간합'), (103, '천간합'), (104, '천간합'), (105, '천간합'),
(201, '천간충'), (202, '천간충'), (203, '천간충'), (204, '천간충'),
(301, '지지육합'), (302, '지지육합'), (303, '지지육합'), (304, '지지육합'), (305, '지지육합'), (306, '지지육합'),
(401, '지지삼합'), (402, '지지삼합'), (403, '지지삼합'), (404, '지지삼합'),
(501, '지지방합'), (502, '지지방합'), (503, '지지방합'), (504, '지지방합'),
(601, '지지육충'), (602, '지지육충'), (603, '지지육충'), (604, '지지육충'), (605, '지지육충'), (606, '지지육충'),
(701, '지지형'), (702, '지지형'), (703, '지지형'),
(801, '지지파'), (802, '지지파'), (803, '지지파'), (804, '지지파'), (805, '지지파'), (806, '지지파'),
(901, '지지해'), (902, '지지해'), (903, '지지해'), (904, '지지해'), (905, '지지해'), (906, '지지해');

INSERT INTO ganji_interaction (code, group_id, description) VALUES
-- 천간합
(0, 101, '갑기합토'), (5, 101, '갑기합토'),
(1, 102, '을경합금'), (6, 102, '을경합금'),
(2, 103, '병신합수'), (7, 103, '병신합수'),
(3, 104, '정임합목'), (8, 104, '정임합목'),
(4, 105, '무계합화'), (9, 105, '무계합화'),
-- 천간충
(0, 201, '갑경충'), (6, 201, '갑경충'),
(1, 202, '을신충'), (7, 202, '을신충'),
(2, 203, '병임충'), (8, 203, '병임충'),
(3, 204, '정계충'), (9, 204, '정계충'),
-- 지지육합
(10, 301, '자축합토'), (11, 301, '자축합토'),
(12, 302, '인해합목'), (21, 302, '인해합목'),
(13, 303, '묘술합화'), (20, 303, '묘술합화'),
(14, 304, '진유합금'), (19, 304, '진유합금'),
(15, 305, '사신합수'), (18, 305, '사신합수'),
(16, 306, '오미합화'), (17, 306, '오미합화'),
-- 지지삼합
(21, 401, '해묘미'), (13, 401, '해묘미'), (17, 401, '해묘미'),
(12, 402, '인오술'), (16, 402, '인오술'), (20, 402, '인오술'),
(15, 403, '사유축'), (19, 403, '사유축'), (11, 403, '사유축'),
(18, 404, '신자진'), (10, 404, '신자진'), (14, 404, '신자진'),
-- 지지방합
(12, 501, '인묘진'), (13, 501, '인묘진'), (14, 501, '인묘진'),
(15, 502, '사오미'), (16, 502, '사오미'), (17, 502, '사오미'),
(18, 503, '신유술'), (19, 503, '신유술'), (20, 503, '신유술'),
(21, 504, '해자축'), (10, 504, '해자축'), (11, 504, '해자축'),
-- 지지육충
(10, 601, '자오충'), (16, 601, '자오충'),
(11, 602, '축미충'), (17, 602, '축미충'),
(12, 603, '인신충'), (18, 603, '인신충'),
(13, 604, '묘유충'), (19, 604, '묘유충'),
(14, 605, '진술충'), (20, 605, '진술충'),
(15, 606, '사해충'), (21, 606, '사해충'),
-- 지지형
(12, 701, '인사신 삼형'), (15, 701, '인사신 삼형'), (18, 701, '인사신 삼형'),
(11, 702, '축술미 삼형'), (20, 702, '축술미 삼형'), (17, 702, '축술미 삼형'),
(10, 703, '자묘형'), (13, 703, '자묘형'),
-- 지지파
(10, 801, '자유파'), (19, 801, '자유파'),
(11, 802, '축진파'), (14, 802, '축진파'),
(12, 803, '인해파'), (21, 803, '인해파'),
(13, 804, '묘오파'), (16, 804, '묘오파'),
(15, 805, '사신파'), (18, 805, '사신파'),
(20, 806, '술미파'), (17, 806, '술미파'),
-- 지지해
(10, 901, '자미해'), (17, 901, '자미해'),
(11, 902, '축오해'), (16, 902, '축오해'),
(12, 903, '인사해'), (15, 903, '인사해'),
(13, 904, '묘진해'), (14, 904, '묘진해'),
(18, 905, '신해해'), (21, 905, '신해해'),
(19, 906, '유술해'), (20, 906, '유술해');

INSERT INTO interaction_metadata (group_id, title, keyword, interpretation) VALUES
-- 천간합
(101, '갑기합(甲己合): 중정의 합', ARRAY['신뢰', '중심', '안정'], '강직한 갑목과 포용력 있는 기토가 만나 흔들림 없는 중심을 잡고 신뢰를 형성합니다.'),
(102, '을경합(乙庚合): 인의의 합', ARRAY['정의', '결속', '의리'], '유연한 을목과 강직한 경금이 만나 서로를 보완하며 강한 결속력과 의리를 발휘합니다.'),
(103, '병신합(丙辛합): 위제의 합', ARRAY['변화', '냉정', '권위'], '뜨거운 병화와 차가운 신금이 만나 매서운 위엄을 갖추며 새로운 기운으로 변화합니다.'),
(104, '정임합(丁壬合): 인수(淫)의 합', ARRAY['다정', '생산', '예술'], '따뜻한 정화와 넓은 임수가 만나 다정다감한 기운을 만들며 창의적인 생산력을 발휘합니다.'),
(105, '무계합(戊癸合): 무정의 합', ARRAY['냉정', '지혜', '현실'], '무게감 있는 무토와 흐르는 계수가 만나 감정보다는 현실적인 지혜와 효율을 추구합니다.'),
-- 천간충
(201, '갑경충(甲庚沖): 정면충돌', ARRAY['결단', '충격', '변화'], '시작의 기운과 결실의 기운이 부딪혀 삶의 큰 방향 전환과 결단이 필요한 상황을 만듭니다.'),
(202, '을신충(乙辛沖): 날카로운 대립', ARRAY['예민', '스트레스', '섬세'], '부드러운 초목이 날카로운 칼날을 만난 격으로, 신경이 예민해지기 쉬우나 섬세한 감각을 발휘합니다.'),
(203, '병임충(丙壬沖): 수화기제', ARRAY['폭발', '충돌', '창의'], '거대한 빛과 넓은 물이 부딪혀 역동적인 변화를 일으키며 강렬한 에너지를 분출합니다.'),
(204, '정계충(丁癸沖): 감정의 격변', ARRAY['민감', '변화', '갈등'], '작은 불씨와 빗물이 만나듯이 작은 자극에도 감정의 동요가 크고 세심한 조율이 필요합니다.'),
-- 지지육합
(301, '자축합(子丑合): 비밀스러운 결속', ARRAY['협력', '신중', '안정'], '추운 겨울의 기운들이 만나 겉으로 드러나지 않는 끈끈한 유대감과 안정감을 형성합니다.'),
(302, '인해합(寅亥合): 성장의 동력', ARRAY['생동', '시작', '활력'], '큰 물이 나무를 생하며 합하는 구조로, 끊임없는 생명력과 추진력을 만들어냅니다.'),
(303, '묘술합(卯戌合): 실리적인 결합', ARRAY['현실', '안정', '타협'], '부드러운 기운과 마른 땅이 만나 현실적인 이익을 추구하며 안정적인 관계를 맺습니다.'),
(304, '진유합(辰酉合): 견고한 결실', ARRAY['완성', '명예', '단단함'], '습한 기운이 금기를 생하여 더욱 단단하게 만드니 결과물이 명확하고 자부심이 강해집니다.'),
(305, '사신합(巳申合): 변화의 합', ARRAY['복합', '재주', '변동'], '불과 금이 만나 합을 이루나 속에는 형(刑)의 기운이 있어 복잡한 변화와 재주를 발휘합니다.'),
(306, '오미합(午未合): 열정의 결집', ARRAY['뜨거움', '집중', '팽창'], '여름의 절정 기운들이 만나 에너지의 밀도가 매우 높으며 열정적인 결과를 지향합니다.'),
-- 지지삼합
(401, '해묘미(亥卯未) 삼합: 목(木)의 국', ARRAY['성장', '창작', '협동'], '다른 성질의 기운들이 모여 거대한 성장의 기류를 형성하고 공동의 목적을 달성합니다.'),
(402, '인오술(寅午戌) 삼합: 화(火)의 국', ARRAY['발산', '열정', '화려'], '에너지가 외부로 강력하게 분출되며 화려한 성과와 강한 행동력을 보여줍니다.'),
(403, '사유축(巳酉丑) 삼합: 금(金)의 국', ARRAY['결실', '수렴', '엄격'], '단단하게 굳어지는 기운으로 목표 중심적이며 결과에 대한 집요함이 강합니다.'),
(404, '신자진(申子辰) 삼합: 수(水)의 국', ARRAY['지혜', '유연', '깊이'], '유연하게 흐르는 거대한 물줄기를 형성하여 지적 깊이와 탁월한 적응력을 발휘합니다.'),
-- 지지방합
(501, '인묘진(寅卯辰) 방합: 봄의 세력', ARRAY['생동', '추진', '동료'], '계절적 동질성을 가진 강력한 목기가 형성되어 거침없는 시작과 추진력을 보여줍니다.'),
(502, '사오미(巳午未) 방합: 여름의 세력', ARRAY['팽창', '강렬', '확산'], '극강의 화기가 형성되어 자신의 영역을 넓히고 중심에 서려는 욕구가 강해집니다.'),
(503, '신유술(申酉戌) 방합: 가을의 세력', ARRAY['견고', '냉철', '정리'], '날카로운 금기가 모여 불필요한 것을 정리하고 결과물의 밀도를 높이는 힘이 강력합니다.'),
(504, '해자축(亥子丑) 방합: 겨울의 세력', ARRAY['저장', '침잠', '지력'], '차가운 수기가 결집하여 내면의 세계를 탐구하고 지식을 저장하는 힘이 탁월합니다.'),
-- 지지육충
(601, '자오충(子午沖): 자존심의 충돌', ARRAY['폭발', '극단', '예민'], '정반대의 강한 에너지가 부딪혀 감정의 변화가 크고 환경의 변동이 잦을 수 있습니다.'),
(602, '축미충(丑未沖): 터전의 변동', ARRAY['조정', '불화', '이동'], '단단한 흙들이 부딪혀 기반이 흔들리는 형상으로, 환경적인 변화나 조정 과정을 겪습니다.'),
(603, '인신충(寅申沖): 역마의 정면충돌', ARRAY['활동', '변화', '속도'], '시작과 결실의 기운이 부딪혀 매우 활동적이며 거주지나 직업의 변동이 잦을 수 있습니다.'),
(604, '묘유충(卯酉沖): 상처와 대립', ARRAY['민감', '분리', '충격'], '부드러운 나무와 날카로운 칼날이 부딪혀 대인관계의 소외감이나 건강상 주의가 필요합니다.'),
(605, '진술충(辰戌沖): 영적인 충돌', ARRAY['복잡', '변화', '충돌'], '거대한 기운들이 부딪혀 정신적인 혼란이나 예기치 못한 환경 변화를 가져옵니다.'),
(606, '사해충(巳亥沖): 정보와 이동', ARRAY['변동', '마찰', '속도'], '지식과 활동의 기운이 부딪혀 소통 과정의 마찰이나 잦은 이동수가 발생합니다.'),
-- 지지형
(701, '인사신(寅巳申) 삼형: 권력의 제어', ARRAY['조절', '수술', '기술'], '강력한 세 기운이 얽혀 시시비비를 가려야 하니, 전문적인 제어 기술이나 리더십이 요구됩니다.'),
(702, '축술미(丑戌未) 삼형: 무은의 형', ARRAY['배신', '시비', '조율'], '가까운 관계에서의 시비나 배신수가 있을 수 있으니 철저한 문서 관리와 조율이 필요합니다.'),
(703, '자묘형(子卯刑): 무례의 형', ARRAY['구설', '불화', '무례'], '생(生)하는 관계임에도 예의에 어긋나는 상황이 생길 수 있어 대인관계의 주의가 필요합니다.'),
-- 지지파
(801, '자유파(子酉破): 조율의 마찰', ARRAY['분열', '파괴', '수정'], '서로 다른 목적이 부딪혀 진행 중인 일이 일시적으로 중단되거나 수정이 필요할 수 있습니다.'),
(802, '축진파(丑辰破): 내부적 균열', ARRAY['미묘', '불편', '조정'], '비슷한 흙들이 서로를 밀어내며 내부적인 갈등이나 건강상의 미묘한 문제를 일으킵니다.'),
(803, '인해파(寅亥破): 합 뒤의 균열', ARRAY['배신', '마찰', '변심'], '합을 이루었으나 내부에 균열이 있으니 다 된 밥에 코 빠뜨리는 격으로 마무리에 주의해야 합니다.'),
(804, '묘오파(卯午破): 열정의 과부하', ARRAY['손상', '충돌', '과열'], '목기가 화기를 너무 급하게 생하여 에너지가 소진되거나 마찰이 생길 수 있습니다.'),
(805, '사신파(巳申破): 기술적 수정', ARRAY['복잡', '수리', '변동'], '변화가 많은 합 속에서 마찰이 생겨 지속적인 수리와 조정이 필요한 구조입니다.'),
(806, '술미파(戌未破): 기반의 손상', ARRAY['조정', '불편', '변화'], '건조한 흙들이 부딪혀 실질적인 기반이 약해지거나 관계의 소외감이 발생합니다.'),
-- 지지해
(901, '자미해(子未害): 감정의 앙금', ARRAY['질투', '원망', '방해'], '서로의 합을 방해하는 관계라 예기치 못한 원망이나 질투로 인한 마찰이 생기기 쉽습니다.'),
(902, '축오해(丑午害): 열정의 동결', ARRAY['냉담', '방해', '불신'], '뜨거운 열정을 차가운 기운이 방해하니 의욕이 꺾이거나 주변의 시기 질투를 받습니다.'),
(903, '인사해(寅巳害): 소통의 단절', ARRAY['오해', '방해', '충격'], '강한 추진력들이 서로를 방해하여 소통 과정에서 오해가 생기고 진행이 더뎌집니다.'),
(904, '묘진해(卯辰害): 성장판의 위축', ARRAY['침해', '방해', '시기'], '부드러운 목기와 습한 토가 만나 자존심 대결을 벌이며 서로의 성장을 미묘하게 방해합니다.'),
(905, '신해해(申亥害): 결실의 훼손', ARRAY['방해', '변동', '마찰'], '결과를 맺으려는 금기와 시작하려는 수기가 부딪혀 마무리 단계에서 장애가 생길 수 있습니다.'),
(906, '유술해(酉戌해): 날카로운 대립', ARRAY['질투', '마찰', '분열'], '날카로운 결실들이 만나 서로를 시기하니 대인관계의 소외감이나 스트레스에 주의해야 합니다.');
~/workspace/saju-analysis$ docker exec -i saju-analysis_postgres psql -U peter -d saju_db < scripts/insert_ganji_interaction.sql

데이터 확인

데이터가 제대로 들어갔는지 확인한다.

~/workspace/saju-analysis$ docker exec -it saju-analysis_postgres psql -U peter -d saju_db -c "SELECT * FROM ganji_metadata;"             
 code | name_ko | name_hani | type | element | yin_yang 
------+---------+-----------+------+---------+----------
    0 ||| 천간 ||1 ||| 천간 ||2 ||| 천간 ||3 ||| 천간 ||4 ||| 천간 ||5 ||| 천간 ||6 ||| 천간 ||7 ||| 천간 ||8 ||| 천간 ||9 ||| 천간 ||10 ||| 지지 ||11 ||| 지지 ||12 ||| 지지 ||13 ||| 지지 ||14 ||| 지지 ||15 ||| 지지 ||16 ||| 지지 ||17 ||| 지지 ||18 ||| 지지 ||19 ||| 지지 ||20 ||| 지지 ||21 ||| 지지 ||(22 rows)
~/workspace/saju-analysis$ docker exec -it saju-analysis_postgres psql -U peter -d saju_db -c "SELECT * FROM interaction_groups;"
 id  | category 
-----+----------
 100 | 천간합
 200 | 천간충
 300 | 지지육합
 400 | 지지삼합
 500 | 지지방합
 600 | 지지육충
 700 | 지지형
 800 | 지지파
 900 | 지지해
 101 | 천간합
 102 | 천간합
 103 | 천간합
 104 | 천간합                                           
 105 | 천간합
 201 | 천간충
 202 | 천간충
 203 | 천간충
 204 | 천간충
 301 | 지지육합
 302 | 지지육합
 303 | 지지육합
 304 | 지지육합
 305 | 지지육합
 306 | 지지육합
 401 | 지지삼합
 402 | 지지삼합
 403 | 지지삼합
 404 | 지지삼합
 501 | 지지방합
 502 | 지지방합
 503 | 지지방합
 504 | 지지방합
 601 | 지지육충
 602 | 지지육충
 603 | 지지육충
 604 | 지지육충
 605 | 지지육충
 606 | 지지육충
 701 | 지지형
 702 | 지지형
 703 | 지지형
 801 | 지지파
 802 | 지지파
 803 | 지지파
 804 | 지지파
 805 | 지지파
 806 | 지지파
 901 | 지지해
 902 | 지지해
 903 | 지지해
 904 | 지지해
 905 | 지지해
 906 | 지지해
(53 rows)
~/workspace/saju-analysis$ docker exec -it saju-analysis_postgres psql -U peter -d saju_db -c "SELECT * FROM ganji_interaction;"
 id | code | group_id | description 
----+------+----------+-------------
  1 |    0 |      101 | 갑기합토
  2 |    5 |      101 | 갑기합토
  3 |    1 |      102 | 을경합금
  4 |    6 |      102 | 을경합금
  5 |    2 |      103 | 병신합수
  6 |    7 |      103 | 병신합수
  7 |    3 |      104 | 정임합목
  8 |    8 |      104 | 정임합목
  9 |    4 |      105 | 무계합화
 10 |    9 |      105 | 무계합화
 11 |    0 |      201 | 갑경충
 12 |    6 |      201 | 갑경충
 13 |    1 |      202 | 을신충
 14 |    7 |      202 | 을신충
 15 |    2 |      203 | 병임충
 16 |    8 |      203 | 병임충
 17 |    3 |      204 | 정계충
 18 |    9 |      204 | 정계충
 19 |   10 |      301 | 자축합토
 20 |   11 |      301 | 자축합토
 21 |   12 |      302 | 인해합목
 22 |   21 |      302 | 인해합목
 23 |   13 |      303 | 묘술합화
 24 |   20 |      303 | 묘술합화
 25 |   14 |      304 | 진유합금
 26 |   19 |      304 | 진유합금
 27 |   15 |      305 | 사신합수
 28 |   18 |      305 | 사신합수
 29 |   16 |      306 | 오미합화
 30 |   17 |      306 | 오미합화
 31 |   21 |      401 | 해묘미
 32 |   13 |      401 | 해묘미
 33 |   17 |      401 | 해묘미
 34 |   12 |      402 | 인오술
 35 |   16 |      402 | 인오술
 36 |   20 |      402 | 인오술
 37 |   15 |      403 | 사유축
 38 |   19 |      403 | 사유축
 39 |   11 |      403 | 사유축
 40 |   18 |      404 | 신자진
 41 |   10 |      404 | 신자진
 42 |   14 |      404 | 신자진
 43 |   12 |      501 | 인묘진
 44 |   13 |      501 | 인묘진
 45 |   14 |      501 | 인묘진
 46 |   15 |      502 | 사오미
 47 |   16 |      502 | 사오미
 48 |   17 |      502 | 사오미
 49 |   18 |      503 | 신유술
 50 |   19 |      503 | 신유술
 51 |   20 |      503 | 신유술
 52 |   21 |      504 | 해자축
 53 |   10 |      504 | 해자축
 54 |   11 |      504 | 해자축
 55 |   10 |      601 | 자오충
 56 |   16 |      601 | 자오충
 57 |   11 |      602 | 축미충
 58 |   17 |      602 | 축미충
 59 |   12 |      603 | 인신충
 60 |   18 |      603 | 인신충
 61 |   13 |      604 | 묘유충
 62 |   19 |      604 | 묘유충
 63 |   14 |      605 | 진술충
 64 |   20 |      605 | 진술충
 65 |   15 |      606 | 사해충
 66 |   21 |      606 | 사해충
 67 |   12 |      701 | 인사신 삼형
 68 |   15 |      701 | 인사신 삼형
 69 |   18 |      701 | 인사신 삼형
 70 |   11 |      702 | 축술미 삼형
 71 |   20 |      702 | 축술미 삼형
 72 |   17 |      702 | 축술미 삼형
 73 |   10 |      703 | 자묘형
 74 |   13 |      703 | 자묘형
 75 |   10 |      801 | 자유파
 76 |   19 |      801 | 자유파
 77 |   11 |      802 | 축진파
 78 |   14 |      802 | 축진파
 79 |   12 |      803 | 인해파
 80 |   21 |      803 | 인해파
 81 |   13 |      804 | 묘오파
 82 |   16 |      804 | 묘오파
 83 |   15 |      805 | 사신파
 84 |   18 |      805 | 사신파
 85 |   20 |      806 | 술미파
 86 |   17 |      806 | 술미파
 87 |   10 |      901 | 자미해
 88 |   17 |      901 | 자미해
 89 |   11 |      902 | 축오해
 90 |   16 |      902 | 축오해
 91 |   12 |      903 | 인사해
 92 |   15 |      903 | 인사해
 93 |   13 |      904 | 묘진해
 94 |   14 |      904 | 묘진해
 95 |   18 |      905 | 신해해
 96 |   21 |      905 | 신해해
 97 |   19 |      906 | 유술해
 98 |   20 |      906 | 유술해
(98 rows)
~/workspace/saju-analysis$ docker exec -it saju-analysis_postgres psql -U peter -d saju_db -c "SELECT * FROM interaction_metadata;"
 id | group_id |              title               |       keyword        |                                         interpretation                                          
----+----------+----------------------------------+----------------------+-------------------------------------------------------------------------------------------------
  1 |      101 | 갑기합(甲己合): 중정의 합        | {신뢰,중심,안정}     | 강직한 갑목과 포용력 있는 기토가 만나 흔들림 없는 중심을 잡고 신뢰를 형성합니다.
  2 |      102 | 을경합(乙庚合): 인의의 합        | {정의,결속,의리}     | 유연한 을목과 강직한 경금이 만나 서로를 보완하며 강한 결속력과 의리를 발휘합니다.
  3 |      103 | 병신합(丙辛합): 위제의 합        | {변화,냉정,권위}     | 뜨거운 병화와 차가운 신금이 만나 매서운 위엄을 갖추며 새로운 기운으로 변화합니다.
  4 |      104 | 정임합(丁壬合): 인수()의 합    | {다정,생산,예술}     | 따뜻한 정화와 넓은 임수가 만나 다정다감한 기운을 만들며 창의적인 생산력을 발휘합니다.
  5 |      105 | 무계합(戊癸合): 무정의 합        | {냉정,지혜,현실}     | 무게감 있는 무토와 흐르는 계수가 만나 감정보다는 현실적인 지혜와 효율을 추구합니다.
  6 |      201 | 갑경충(甲庚沖): 정면충돌         | {결단,충격,변화}     | 시작의 기운과 결실의 기운이 부딪혀 삶의 큰 방향 전환과 결단이 필요한 상황을 만듭니다.
  7 |      202 | 을신충(乙辛沖): 날카로운 대립    | {예민,스트레스,섬세} | 부드러운 초목이 날카로운 칼날을 만난 격으로, 신경이 예민해지기 쉬우나 섬세한 감각을 발휘합니다.
  8 |      203 | 병임충(丙壬沖): 수화기제         | {폭발,충돌,창의}     | 거대한 빛과 넓은 물이 부딪혀 역동적인 변화를 일으키며 강렬한 에너지를 분출합니다.
  9 |      204 | 정계충(丁癸沖): 감정의 격변      | {민감,변화,갈등}     | 작은 불씨와 빗물이 만나듯이 작은 자극에도 감정의 동요가 크고 세심한 조율이 필요합니다.
 10 |      301 | 자축합(子丑合): 비밀스러운 결속  | {협력,신중,안정}     | 추운 겨울의 기운들이 만나 겉으로 드러나지 않는 끈끈한 유대감과 안정감을 형성합니다.
 11 |      302 | 인해합(寅亥合): 성장의 동력      | {생동,시작,활력}     | 큰 물이 나무를 생하며 합하는 구조로, 끊임없는 생명력과 추진력을 만들어냅니다.
 12 |      303 | 묘술합(卯戌合): 실리적인 결합    | {현실,안정,타협}     | 부드러운 기운과 마른 땅이 만나 현실적인 이익을 추구하며 안정적인 관계를 맺습니다.
 13 |      304 | 진유합(辰酉合): 견고한 결실      | {완성,명예,단단함}   | 습한 기운이 금기를 생하여 더욱 단단하게 만드니 결과물이 명확하고 자부심이 강해집니다.
 14 |      305 | 사신합(巳申合): 변화의 합        | {복합,재주,변동}     | 불과 금이 만나 합을 이루나 속에는 형()의 기운이 있어 복잡한 변화와 재주를 발휘합니다.
 15 |      306 | 오미합(午未合): 열정의 결집      | {뜨거움,집중,팽창}   | 여름의 절정 기운들이 만나 에너지의 밀도가 매우 높으며 열정적인 결과를 지향합니다.
 16 |      401 | 해묘미(亥卯未) 삼합: 목()의 국 | {성장,창작,협동}     | 다른 성질의 기운들이 모여 거대한 성장의 기류를 형성하고 공동의 목적을 달성합니다.
 17 |      402 | 인오술(寅午戌) 삼합: 화()의 국 | {발산,열정,화려}     | 에너지가 외부로 강력하게 분출되며 화려한 성과와 강한 행동력을 보여줍니다.
 18 |      403 | 사유축(巳酉丑) 삼합: 금()의 국 | {결실,수렴,엄격}     | 단단하게 굳어지는 기운으로 목표 중심적이며 결과에 대한 집요함이 강합니다.
 19 |      404 | 신자진(申子辰) 삼합: 수()의 국 | {지혜,유연,깊이}     | 유연하게 흐르는 거대한 물줄기를 형성하여 지적 깊이와 탁월한 적응력을 발휘합니다.
 20 |      501 | 인묘진(寅卯辰) 방합: 봄의 세력   | {생동,추진,동료}     | 계절적 동질성을 가진 강력한 목기가 형성되어 거침없는 시작과 추진력을 보여줍니다.
 21 |      502 | 사오미(巳午未) 방합: 여름의 세력 | {팽창,강렬,확산}     | 극강의 화기가 형성되어 자신의 영역을 넓히고 중심에 서려는 욕구가 강해집니다.
 22 |      503 | 신유술(申酉戌) 방합: 가을의 세력 | {견고,냉철,정리}     | 날카로운 금기가 모여 불필요한 것을 정리하고 결과물의 밀도를 높이는 힘이 강력합니다.
 23 |      504 | 해자축(亥子丑) 방합: 겨울의 세력 | {저장,침잠,지력}     | 차가운 수기가 결집하여 내면의 세계를 탐구하고 지식을 저장하는 힘이 탁월합니다.
 24 |      601 | 자오충(子午沖): 자존심의 충돌    | {폭발,극단,예민}     | 정반대의 강한 에너지가 부딪혀 감정의 변화가 크고 환경의 변동이 잦을 수 있습니다.
 25 |      602 | 축미충(丑未沖): 터전의 변동      | {조정,불화,이동}     | 단단한 흙들이 부딪혀 기반이 흔들리는 형상으로, 환경적인 변화나 조정 과정을 겪습니다.
 26 |      603 | 인신충(寅申沖): 역마의 정면충돌  | {활동,변화,속도}     | 시작과 결실의 기운이 부딪혀 매우 활동적이며 거주지나 직업의 변동이 잦을 수 있습니다.
 27 |      604 | 묘유충(卯酉沖): 상처와 대립      | {민감,분리,충격}     | 부드러운 나무와 날카로운 칼날이 부딪혀 대인관계의 소외감이나 건강상 주의가 필요합니다.
 28 |      605 | 진술충(辰戌沖): 영적인 충돌      | {복잡,변화,충돌}     | 거대한 기운들이 부딪혀 정신적인 혼란이나 예기치 못한 환경 변화를 가져옵니다.
 29 |      606 | 사해충(巳亥沖): 정보와 이동      | {변동,마찰,속도}     | 지식과 활동의 기운이 부딪혀 소통 과정의 마찰이나 잦은 이동수가 발생합니다.
 30 |      701 | 인사신(寅巳申) 삼형: 권력의 제어 | {조절,수술,기술}     | 강력한 세 기운이 얽혀 시시비비를 가려야 하니, 전문적인 제어 기술이나 리더십이 요구됩니다.
 31 |      702 | 축술미(丑戌未) 삼형: 무은의 형   | {배신,시비,조율}     | 가까운 관계에서의 시비나 배신수가 있을 수 있으니 철저한 문서 관리와 조율이 필요합니다.
 32 |      703 | 자묘형(子卯刑): 무례의 형        | {구설,불화,무례}     |()하는 관계임에도 예의에 어긋나는 상황이 생길 수 있어 대인관계의 주의가 필요합니다.
 33 |      801 | 자유파(子酉破): 조율의 마찰      | {분열,파괴,수정}     | 서로 다른 목적이 부딪혀 진행 중인 일이 일시적으로 중단되거나 수정이 필요할 수 있습니다.
 34 |      802 | 축진파(丑辰破): 내부적 균열      | {미묘,불편,조정}     | 비슷한 흙들이 서로를 밀어내며 내부적인 갈등이나 건강상의 미묘한 문제를 일으킵니다.
 35 |      803 | 인해파(寅亥破): 합 뒤의 균열     | {배신,마찰,변심}     | 합을 이루었으나 내부에 균열이 있으니 다 된 밥에 코 빠뜨리는 격으로 마무리에 주의해야 합니다.
 36 |      804 | 묘오파(卯午破): 열정의 과부하    | {손상,충돌,과열}     | 목기가 화기를 너무 급하게 생하여 에너지가 소진되거나 마찰이 생길 수 있습니다.
 37 |      805 | 사신파(巳申破): 기술적 수정      | {복잡,수리,변동}     | 변화가 많은 합 속에서 마찰이 생겨 지속적인 수리와 조정이 필요한 구조입니다.
 38 |      806 | 술미파(戌未破): 기반의 손상      | {조정,불편,변화}     | 건조한 흙들이 부딪혀 실질적인 기반이 약해지거나 관계의 소외감이 발생합니다.
 39 |      901 | 자미해(子未害): 감정의 앙금      | {질투,원망,방해}     | 서로의 합을 방해하는 관계라 예기치 못한 원망이나 질투로 인한 마찰이 생기기 쉽습니다.
 40 |      902 | 축오해(丑午害): 열정의 동결      | {냉담,방해,불신}     | 뜨거운 열정을 차가운 기운이 방해하니 의욕이 꺾이거나 주변의 시기 질투를 받습니다.
 41 |      903 | 인사해(寅巳害): 소통의 단절      | {오해,방해,충격}     | 강한 추진력들이 서로를 방해하여 소통 과정에서 오해가 생기고 진행이 더뎌집니다.
 42 |      904 | 묘진해(卯辰害): 성장판의 위축    | {침해,방해,시기}     | 부드러운 목기와 습한 토가 만나 자존심 대결을 벌이며 서로의 성장을 미묘하게 방해합니다.
 43 |      905 | 신해해(申亥害): 결실의 훼손      | {방해,변동,마찰}     | 결과를 맺으려는 금기와 시작하려는 수기가 부딪혀 마무리 단계에서 장애가 생길 수 있습니다.
 44 |      906 | 유술해(酉戌해): 날카로운 대립    | {질투,마찰,분열}     | 날카로운 결실들이 만나 서로를 시기하니 대인관계의 소외감이나 스트레스에 주의해야 합니다.
(44 rows)

이후, 이 데이터를 조합하여 분석하는 Rust 로직을 구현해 보자.

profile
Peter J Online Space - since July 2020 | 아무데서나 채용해줬으면 좋겠다

0개의 댓글