소개
시도하고자 했던 것
10년간 축적한 한국 전통 명리학 데이터 310건(통변 자료)을 체계적으로 관리할 수 있는 Rails 백엔드 시스템을 구축하려고 했습니다. 기존에는 HTML/JavaScript + localStorage로 프로토타입을 만들었지만, 데이터가 계속 늘어나면서 한계에 부딪혔습니다.
프로젝트 목표:
PostgreSQL 기반 정규화된 데이터베이스 구축
명리학 데이터의 복잡한 관계(원국-대운-세운) 체계화
향후 Dify AI 연동을 위한 RESTful API 준비
UNESCO 디지털 문화유산 등재를 위한 데이터 투명성 확보
왜 이것을 선택했는가
기술적 이유:
정규화 필요성: 하나의 사주에 여러 개의 대운, 수십 개의 세운이 연결되는 복잡한 관계
데이터 무결성: localStorage는 관계형 데이터 관리가 어려움
확장성: 향후 1.1M+ 조합 데이터 처리를 위한 준비
문화적 이유:
한국 전통 지식의 디지털 보존
비영리 재능기부 프로젝트
학술적 접근과 투명성 중시
진행 방법
사용한 도구
개발 환경
GitHub Codespaces: 클라우드 개발 환경 (PostgreSQL 사전 설치)
Ruby on Rails 8.1.1: 웹 프레임워크
SQLite 3: 개발 데이터베이스 (PostgreSQL로 전환 예정)
AI 협업
Claude Sonnet 4.5: 전체 아키텍처 설계부터 디버깅까지
프로젝트 모드: 지속적인 컨텍스트 유지
핵심 프롬프트 전략
1단계: 문제 진단 프롬프트
text
PostgreSQL을 로컬에 설치하려고 하는데 계속 실패합니다.
권한 문제와 설정 오류가 반복됩니다.
[에러 메시지 전체 복사]
다른 대안이 있을까요?Claude의 답변: GitHub Codespaces 제안 → 즉시 해결!
2단계: 구조 설계 프롬프트
text
명리학 데이터를 Rails로 관리하고 싶습니다.
데이터 구조:
- Profile (기본 정보): 310건
- Wonkuk (원국, 사주): Profile당 1개
- Daeun (대운): Profile당 평균 5-8개
- Sewun (세운): Profile당 연도별 10개
JSON 데이터를 Rails 모델로 정규화하는 방법을 알려주세요.결과: 5개 모델 + 관계 설정 완벽 설계
3단계: 마이그레이션 프롬프트
text
data_310.json 파일을 Rails DB에 import하고 싶습니다.
JSON 구조:
{
"tables": {
"profiles": [...],
"wonkuk": [...],
"daeun": [...],
"sewun": [...]
}
}
UUID로 연결된 관계를 Rails ID로 변환하는 방법을 포함해서
Rake task를 만들어주세요.결과: 완벽하게 작동하는 import 스크립트 생성
실제 구현 과정
Step 1: Rails 프로젝트 생성
bash
rails new hanbadook_rails
cd hanbadook_railsStep 2: 모델 생성
bash
rails generate model Profile name:string birth_date:date birth_time:time gender:string solar_calendar:boolean timezone:string
rails generate model Wonkuk profile:references year_pillar:string month_pillar:string day_pillar:string time_pillar:string interpretation:text
rails generate model Daeun profile:references period:string name:string summary:text jaemul:text investment:text health:text family:text social:text job_change:text precaution:text
rails generate model Sewun profile:references year:integer pillar:string prediction:text fortune_score:integer
rails generate model DaeunGroup profile:references current_daeun:string total_periods:integerStep 3: 마이그레이션 실행
bash
rails db:migrateStep 4: Import Rake Task 작성
파일: lib/tasks/import_profiles.rake
ruby
namespace :data do
desc "Import profile data"
task import_profiles: :environment do
require 'json'
puts "🚀 Starting profile import..."
file_path = Rails.root.join('db', 'seeds', 'data_310.json')
json_data = JSON.parse(File.read(file_path))
puts "📚 Importing profiles..."
success = 0
failed = 0
json_data['tables']['profiles'].each_with_index do |data, index|
begin
Profile.create!(
name: data['record_number'],
birth_date: Date.parse(data['birth_date']),
birth_time: Time.parse(data['birth_time']),
gender: data['gender'],
solar_calendar: data['solar_calendar'],
timezone: data['timezone']
)
success += 1
print "." if (index + 1) % 50 == 0
rescue => e
failed += 1
end
end
puts "\n✅ Profile import completed!"
puts "📊 Success: #{success}, Failed: #{failed}"
puts "📈 Total profiles: #{Profile.count}"
end
end파일: lib/tasks/import_wonkuk.rake
ruby
namespace :data do
desc "Import wonkuk data"
task import_wonkuk: :environment do
require 'json'
puts "🚀 Starting wonkuk import..."
file_path = Rails.root.join('db', 'seeds', 'data_310.json')
json_data = JSON.parse(File.read(file_path))
# Profile UUID → record_number 매핑 생성
profile_uuid_map = {}
json_data['tables']['profiles'].each do |p|
profile_uuid_map[p['profile_id']] = p['record_number']
end
puts "📚 Importing wonkuk..."
success = 0
failed = 0
json_data['tables']['wonkuk'].each_with_index do |data, index|
record_number = profile_uuid_map[data['profile_id']]
profile = Profile.find_by(name: record_number)
unless profile
failed += 1
next
end
begin
Wonkuk.create!(
profile_id: profile.id,
year_pillar: data['year_pillar'],
month_pillar: data['month_pillar'],
day_pillar: data['day_pillar'],
time_pillar: data['time_pillar'],
interpretation: data['interpretation']
)
success += 1
print "." if (index + 1) % 50 == 0
rescue => e
failed += 1
end
end
puts "\n✅ Wonkuk import completed!"
puts "📊 Success: #{success}, Failed: #{failed}"
puts "📈 Total wonkuk: #{Wonkuk.count}"
end
endStep 5: 실행
bash
rails data:import_profiles출력 결과:
text
🚀 Starting profile import...
📚 Importing profiles...
......
✅ Profile import completed!
📊 Success: 310, Failed: 0
📈 Total profiles: 310bash
rails data:import_wonkuk출력 결과:
text
🚀 Starting wonkuk import...
📚 Importing wonkuk...
......
✅ Wonkuk import completed!
📊 Success: 310, Failed: 0
📈 Total wonkuk: 310활용 화면
통합 도해 자료:
hanbadook_complete_guide.html이 도해에는 다음이 포함되어 있습니다:
전체 진행 현황 (40% 완성률)
9단계 작업 타임라인
5개 테이블 데이터베이스 스키마
상세한 데이터 처리 흐름
다음 단계 가이드
이미지 표시
결과와 배운 점
최종 성과
정량적 성과
✅ 620개 레코드 성공적 import (Profile 310 + Wonkuk 310)
✅ 100% 성공률 (실패 0건)
✅ 8초 소요 (전체 import 시간)
✅ 5개 테이블 정규화 완료
✅ 8개 마이그레이션 성공
정성적 성과
🎯 PostgreSQL 장애물을 우회하는 창의적 해결책 발견
🎯 "Vibe Coding"에서 "Structured Development"로 전환
🎯 재사용 가능한 import 파이프라인 구축
🎯 향후 3,500개 레코드 처리 준비 완료
배운 점과 꿀팁
1. 🌟 환경 문제는 우회하라
배운 것: 로컬 설치가 안 되면 클라우드를 활용하세요! GitHub Codespaces는 PostgreSQL, Redis, Node.js 등이 사전 설치되어 있습니다.
꿀팁:
bash
# Codespaces에서 PostgreSQL 확인
psql --version
# PostgreSQL 14.x 이미 설치됨!2. 🎯 AI에게 "구체적인 입력"을 주자
나쁜 예:
text
Rails로 데이터베이스 만들어줘좋은 예:
text
명리학 데이터를 Rails로 관리하고 싶습니다.
[JSON 구조 첨부]
이 데이터를 정규화된 5개 테이블로 설계해주세요.
Profile이 중심이고, Wonkuk은 1:1, Daeun은 1:N 관계입니다.결과: 완벽한 모델 설계 + 마이그레이션 + Rake task 한 번에!
3. 💡 UUID 매핑의 중요성
시행착 오: 처음에 UUID를 Rails ID로 직접 변환하려다 실패했습니다.
해결책:
ruby
# UUID → record_number 매핑 테이블 생성
profile_uuid_map = {}
json_data['tables']['profiles'].each do |p|
profile_uuid_map[p['profile_id']] = p['record_number']
end
# 사용할 때
record_number = profile_uuid_map[uuid]
profile = Profile.find_by(name: record_number)이렇게 하면 UUID 기반 JSON을 Rails ID로 완벽하게 변환!
4. 🔧 에러 처리는 필수
꿀팁:
ruby
begin
Profile.create!(data)
success += 1
rescue => e
puts "Failed: #{data['name']} - #{e.message}"
failed += 1
endcreate! (느낌표) 사용하면 검증 실패 시 예외 발생 → 즉시 catch 가능!
5. 📊 진행 상황 표시로 안심시키기
꿀팁:
ruby
print "." if (index + 1) % 50 == 050개마다 점(.) 찍어서 진행 중임을 시각화!
실행 화면:
text
📚 Importing profiles...
......
✅ Profile import completed!겪었던 시행착오
시행착오 1: PostgreSQL 로컬 설치 지옥
문제: 밤새 PostgreSQL 설치 시도 → 권한 오류 → 재설치 → 경로 문제 → 반복...
해결: Claude가 "GitHub Codespaces 써보세요"라고 제안 → 5분 만에 PostgreSQL 사용 가능한 환경 확보!
교훈: 문제를 "해결"하는 것보다 "우회"하는 게 더 현명할 때가 있습니다.
시행착오 2: "Vibe Coding"의 한계
문제: Claude에게 "그냥 만들어줘" 식으로 요청 → 코드는 나오는데 왜 그렇게 작동하는지 이해 안 됨 → 에러 나면 또 Claude에게 물어봐야 함
해결: 단계별로 쪼개서 물어보기:
"먼저 데이터 구조 설계해줘"
"이제 마이그레이션 만들어줘"
"import 로직은 어떻게 짜야 해?"
교훈: AI는 마법사가 아닙니다. 구조화된 접근이 장기적으로 더 효율적!
시행착오 3: Rails의 "번거로움"
문제: PostgreSQL에서는 COPY profiles FROM 'data.csv' 한 줄이면 끝! Rails는 모델 정의 → 마이그레이션 → Rake task → 실행... 왜 이렇게 길어?
깨달음: Rails의 "번거로움"은 사실 "안전장치"였습니다:
검증 (Validation): 잘못된 데이터 자동 차단
관계 (Associations): Profile-Wonkuk 관계 자동 관리
타임스탬프: created_at, updated_at 자동 기록
트랜잭션: 실패 시 자동 롤백
교훈: 빠른 것이 항상 좋은 것은 아닙니다. 유지보수를 생각하면 Rails가 더 현명한 선택!
도움이 필요한 부분
1. PostgreSQL 전환
현재 SQLite를 사용 중인데, production에서는 PostgreSQL을 쓰고 싶습니다. database.yml 설정만 바꾸면 될까요? 아니면 추가 작업이 필요한가요?
2. Bulk Insert 최적화
앞으로 1.1M 조합을 처리해야 하는데, 현재 방식(레코드 하나씩 생성)으로는 너무 느릴 것 같습니다. Rails의 insert_all 같은 bulk insert 방법이 더 나을까요?
3. Dify AI 연동
Rails API를 만들어서 Dify AI와 연동하려면:
RESTful API 엔드포인트 설계
인증 (API Key)
Rate limiting
이런 것들을 어떻게 구현해야 할까요?
도움 받은 글 (옵션)
지피터스 커뮤니티
"Claude Projects 100% 활용법" - 프로젝트 모드의 지속적 컨텍스트 유지 방법 학습
"AI와 함께하는 데이터베이스 설계" - 정규화 원칙과 관계 설정 참고
"아이디어만 있으면 AI가 다 개발해주는 바이브코딩 전 문서 작성 워크플로우" - 바이브 코딩 → 구조적 코딩으로 전환하는 실무형 워크플로우 참고자료
외부 참고 자료
Ruby on Rails Guides
https://guides.rubyonrails.orgActive Record Migrations
Active Record Associations
Custom Rake Tasks
GitHub Codespaces 문서
https://docs.github.com/codespaces개발 환경 설정
PostgreSQL 사용법
명리학 전통 텍스트
『연해자평(淵海子平)』: 기초 이론
4관법(사주 보는 네 가지 관점) 체계