← 목록
기타 2026-06-27 18KB 읽기 21분

크라우니엔진 크로스플랫폼 (맥/윈도우/리눅스)

Reconnaissance complete. Here is the full cross-platform architecture design for /Users/ef/crowny-engine.


크라우니엔진 크로스플랫폼 아키텍처 설계 (mac/win 동시 + linux 기획)

핵심 진단 (정찰 종합)

3개 레이어로 분리하면 깨끗하게 정리된다:

레이어플랫폼 의존성조치
**crownyc.c / hanseonc_.c (VM·컴파일러)이미 #ifdef _WIN32/__APPLE__/__linux__ 완비. PE32+ exe 사전빌드 존재재사용 (compositor.c 하드코딩 15곳만 별도)
core/.한선 (로직 SSOT)OS 무관 — 단 체계() 호출 안에 BSD명령·/Users/ef 하드코딩 섞임core/플랫폼.한선 1곳으로 명령 격리
셸 레이어** (엔진.sh, shell/*.sh)bash 전제 — flock/launchctl/shasum/sed -i ''/whoami/pgreplib/platform.sh + 엔진.cmd/.ps1 진입점
설계 원칙: 플랫폼 차이는 두 파일에만 산다 — core/플랫폼.한선(한선씨 레벨)과 lib/platform.sh(셸 레벨). 나머지 26개 core 모듈과 모든 비즈니스 로직은 공통.


(a) 플랫폼 추상화 계층 설계

A-1. core/플랫폼.한선 (신규 — 한선씨 레벨 명령 매핑 SSOT)

OS를 환경변수로 주입받아(한선씨는 uname 직접 못 부름) 플랫폼별 체계() 명령 문자열을 반환하는 순수 매핑 모듈. 기존 시간헬퍼.한선date -j||date -d 이중화 패턴을 일반화한다.

han// core/플랫폼.한선 — OS감지 + 명령매핑 SSOT
// 주입: CROWNY_PLATFORM = darwin|linux|windows (부트스트랩이 uname으로 설정)
// VM함정: 체계() stdout 캡처불가 → >/tmp 후 읽기() / 포함()=미발견 -1 / 파일존재()=-1
가져오기 "문자열.한선"

함수 플랫폼() {
  변수 p = 환경변수("CROWNY_PLATFORM")
  만약 (글자수(p) == 0) { p = "darwin" }   // 안전 기본값(현 운영=mac)
  반환 p
}

// ── 1. 해시 (앵커/체크섬/싱크) ─────────────────
함수 해시명령(경로) {
  변수 p = 플랫폼()
  만약 (p == "linux")   { 반환 "sha256sum '"  + 경로 + "' | awk '{print $1}'" }
  만약 (p == "windows") { 반환 "certutil -hashfile '" + 경로 + "' SHA256 | findstr /R \"^[0-9a-f]\"" }
  반환 "shasum -a 256 '" + 경로 + "' | awk '{print $1}'"   // darwin
}

// ── 2. 날짜 (어제/월말 — 정산·빌드판정의 토대) ──
함수 어제날짜명령(tmp) {
  변수 p = 플랫폼()
  만약 (p == "windows") {
    반환 "powershell -NoProfile -C \"(Get-Date).AddDays(-1).ToString('yyyy-MM-dd')\" > '" + tmp + "'"
  }
  // darwin(BSD) → linux(GNU) 이중 폴백 (시간헬퍼.한선 검증패턴)
  반환 "date -v-1d '+%Y-%m-%d' > '" + tmp + "' 2>/dev/null || date -d 'yesterday' '+%Y-%m-%d' > '" + tmp + "' 2>/dev/null"
}

// ── 3. 파일잠금 (정산 단일라이터 / 원장 WAL) ────
// 전 플랫폼 공통: mkdir 원자성 (flock 불필요, 파이프라인.sh 검증패턴)
함수 잠금획득(락디렉토리) {
  변수 결과 = 체계("mkdir '" + 락디렉토리 + "' 2>/dev/null")
  반환 결과   // 0=획득 / 비0=이미잠김
}
함수 잠금해제(락디렉토리) {
  체계("rm -rf '" + 락디렉토리 + "'")
  반환 0
}

// ── 4. 스케줄러 (정산/빌드 크론 상태) ──────────
함수 스케줄러상태명령(작업명, tmp) {
  변수 p = 플랫폼()
  만약 (p == "linux")   { 반환 "systemctl --user is-active " + 작업명 + " > '" + tmp + "' 2>/dev/null" }
  만약 (p == "windows") { 반환 "schtasks /query /tn " + 작업명 + " > '" + tmp + "' 2>NUL" }
  반환 "launchctl list | grep -q " + 작업명 + " && echo active > '" + tmp + "'"   // darwin
}

// ── 5. 프로세스 생존 (서버 기동 확인) ──────────
함수 프로세스확인명령(패턴, tmp) {
  변수 p = 플랫폼()
  만약 (p == "windows") { 반환 "tasklist | findstr crownyc > '" + tmp + "' 2>NUL" }
  반환 "pgrep -f '" + 패턴 + "' > '" + tmp + "' 2>/dev/null"   // mac/linux 공통
}

// ── 6. 홈/경로 (포터빌리티.한선이 이미 처리, 래퍼만) ─
함수 홈경로() {
  변수 h = 환경변수("HOME")
  만약 (글자수(h) == 0) { h = 환경변수("USERPROFILE") }   // windows
  반환 h
}
함수 엔진루트() {
  변수 r = 환경변수("ENGINE_ROOT")
  만약 (글자수(r) == 0) { r = 홈경로() + "/crowny-engine" }
  반환 r
}

사용 규약: 모든 core 모듈은 체계("date -v-1d ...") 직접 호출을 금지하고 가져오기 "플랫폼.한선"해시명령()/어제날짜명령() 등을 거친다. 이렇게 하면 BSD/GNU/Windows 분기가 이 한 파일에만 산다.

A-2. lib/platform.sh (신규 — 셸 레벨 추상화, bash 진입점 공용)

bash#!/usr/bin/env bash
# lib/platform.sh — 셸 레벨 OS 추상화 (엔진.sh가 source)
detect_platform() {
  case "$(uname -s 2>/dev/null)" in
    Darwin) echo darwin ;; Linux) echo linux ;;
    MINGW*|MSYS*|CYGWIN*) echo windows ;; *) echo unknown ;;
  esac
}
export CROWNY_PLATFORM="${CROWNY_PLATFORM:-$(detect_platform)}"   # 한선씨로 그대로 전달
get_home(){ [ -n "${HOME:-}" ] && echo "$HOME" || echo "$USERPROFILE"; }
hash_sha256(){ if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1"|awk '{print $1}';
               elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1"|awk '{print $1}';
               else echo "NO_SHA_TOOL" >&2; return 1; fi; }
lock_dir(){ local d="$1" to="${2:-30}" n=0; while ! mkdir "$d" 2>/dev/null; do
            [ "$n" -ge "$to" ] && return 1; sleep 1; n=$((n+1)); done
            echo $$ >"$d/pid"; trap "rm -rf '$d'" EXIT; }
sched_status(){ case "$CROWNY_PLATFORM" in
  darwin) launchctl list 2>/dev/null|grep -q "$1" && echo active ;;
  linux)  systemctl --user is-active "$1" 2>/dev/null ;;
  windows) schtasks /query /tn "$1" 2>NUL ;; esac; }

엔진.sh의 라인 153/213 $(whoami)는 POSIX 공통이라 유지, 라인 346/355 launchctlsched_status, 라인 337 pgrep은 그대로(mac/linux 공통)로 두되 windows 진입은 .cmd가 담당.


(b) macOS ↔ Windows 차이 비교표

기능macOS (darwin/BSD)WindowsLinux (기획)격리 위치
SHA256shasum -a 256 f \| awkcertutil -hashfile f SHA256sha256sum f \| awk해시명령() / hash_sha256
어제날짜date -v-1d '+%F'powershell (Get-Date).AddDays(-1)date -d yesterday '+%F'어제날짜명령()
월말날짜date -j -v1d -v+1m -v-1dpowershell AddMonthsdate -d '+1 month -1 day'시간헬퍼.한선(기존)
파일잠금mkdir 원자 (flock 없음)mkdir 원자flock 또는 mkdir잠금획득() (mkdir 통일)
스케줄러launchctl + plistschtasks.exe / 작업스케줄러systemd --user timer스케줄러상태명령()
프로세스확인pgrep -ftasklist \| findstrpgrep -f프로세스확인명령()
$HOME(/Users/ef)%USERPROFILE%/$HOME(Git Bash)$HOME(/home/x)홈경로()
임시/tmp ($TMPDIR)%TEMP% (Git Bash /tmp 매핑)/tmp/tmp 유지(매핑됨)
in-place 편집sed -i ''perl -i.bak (MSYS)sed -iperl로 통일
텍스트검색grep/awkfindstr 또는 MSYS grepgrep/awkMSYS2 동봉 시 grep 공통
줄바꿈LFCRLF 주의 (.cmd/.bat=CRLF, .한선/.sh=LF)LF.gitattributes/패키징
데몬화nohup &/launchctlstart /b/작업스케줄러nohup &/systemd진입점별
C 컴파일cc + -framework Cocoamingw gcc -lws2_32 -luser32 -lgdi32cc -lX11 -lpthreadMakefile/빌드스크립트
셸 진입엔진.sh엔진.cmd→MSYS bash 또는 네이티브엔진.sh(c) 레이아웃
CRLF 규칙: dist-win/ 패키징 시 .cmd/.bat만 CRLF로 변환, .한선/.sh/.psv/.toau는 LF 유지(크라우니c가 LF 가정). 패키지 빌드 스크립트에서 강제.


(c) 패키지 디렉토리 레이아웃

세 dist는 공통 core 한선씨 + 공통 libs + 플랫폼별 셸 + 플랫폼별 crownyc 바이너리로 구성. core/libs는 바이트 동일(SSOT).

/Users/ef/crowny-engine/                 ← 소스 (단일 원본)
├── core/            *.한선  (26+1 플랫폼.한선)  ← 공통, 무수정 복사
├── libs/            *.한선  (표준 라이브러리)    ← 공통
├── lib/             platform.sh (신규)           ← 셸 추상화 공통
├── shell/           *.sh + *.한선 동반           ← bash(mac/linux 공통)
├── win/             엔진.cmd 엔진.bat *.ps1 (신규) ← windows 전용 진입
├── 엔진.sh                                        ← mac/linux 진입
├── 매니페스트.psv
└── dist/            (빌드 산출물 — 아래 3종)

dist-mac/                          dist-win/                       dist-linux/ (기획)
├── core/      (동일)              ├── core/      (동일)            ├── core/
├── libs/      (동일)              ├── libs/      (동일)            ├── libs/
├── lib/platform.sh               ├── lib/platform.sh             ├── lib/platform.sh
├── shell/*.sh                    ├── shell/*.sh (MSYS bash용)     ├── shell/*.sh
├── 엔진.sh                       ├── 엔진.cmd 엔진.bat *.ps1      ├── 엔진.sh
├── bin/crownyc          (Mach-O) ├── bin/crownyc.exe  (PE32+)     ├── bin/crownyc       (ELF)
├── bin/hanseonc_high    (Mach-O) ├── bin/hanseonc_high.exe        ├── bin/hanseonc_high (ELF)
└── README-mac.md                 └── crowny-start.cmd (5단계설치) └── crowny-install.sh + .service

윈도우 바이너리는 신규 빌드 불필요 — /Users/ef/crowny-win-pkg/bin/*.exe(검증된 PE32+) 재사용. std/ 110개도 /Users/ef/crowny-windows-package/crowny-bin/std/에서 가져와 dist-win/libs/로 병합 가능.


(d) 윈도우에서 한선씨 REPL(크라우니코드.한선) 동작 방법

REPL 진입점: crownyc.exe run core/크라우니코드.toau. 핵심은 REPL 내부 체계() 호출들이 쓰는 grep/awk/date를 윈도우에서 어떻게 충족하느냐.

3가지 경로 (권장순):

  1. MSYS2/Git Bash 동봉 (권장, 최소공수)엔진.cmd가 Git Bash 환경에서 crownyc.exe를 실행. grep/awk/sed/date(GNU) 전부 제공됨 → core/*.한선체계() 명령이 거의 그대로 작동. CROWNY_PLATFORM=linux 매핑 사용(GNU 명령군이므로). 실제로 정찰의 "Git Bash면 POSIX 셸 코드 대부분 작동" 결론과 일치.
  1. 네이티브 cmd + findstr 폴백 — Git Bash 없이 순수 cmd. 룩업.한선/학습.한선grep -m1 -Ffindstr /C:"..."로 매핑하는 분기를 플랫폼.한선에 추가:
han함수 한줄검색명령(패턴, 파일, tmp) {
  만약 (플랫폼() == "windows") { 반환 "findstr /C:\"" + 패턴 + "\" \"" + 파일 + "\" > \"" + tmp + "\"" }
  반환 "grep -m1 -F '" + 패턴 + "' '" + 파일 + "' > '" + tmp + "'"
}
단 findstr은 -m1(첫줄만)·정규식 차이가 있어 부분()으로 첫 줄 잘라야 함.

  1. 한선씨 네이티브화 (장기, 헌법 정합)읽기()로 DB 전체 로드 후 포함()/부분()으로 한선씨 내부에서 검색. 외부 grep 제거 → 완전 OS독립. 단 학습DB가 16KB(STR_MAX_LEN=16384, 단일 읽기() 한계) 초과 시 샤딩 필요. 룩업DB가 작으면 즉시 적용 가능, 크면 페이지네이션.
입력()/출력값(): crownyc.exe는 stdin/stdout 직결이라 cmd·PowerShell·Git Bash 모두 동작(콘솔 chcp 65001로 UTF-8 한글 보장 — crowny-start.cmd에 이미 존재). 체계()cmd /c로 위임되므로 명령만 윈도우 호환이면 됨.

권장: 경로 1(MSYS2 동봉) + 플랫폼.한선에 windows 분기 점진 추가. 즉시 동작 + 헌법적 한선씨 네이티브화는 룩업/학습부터 단계 이행.


(e) 리눅스 dist-linux 기획

  • 빌드: cc -O2 -DCROWNY_WINDOW -lX11 -lpthread crownyc.c crownyc_window_x11.c compositor.c ui.c theme.c -lm -o crownyc (GUI). 헤드리스 서버는 cc -O2 crownyc.c -lm -o crownyc. crownyc.c__linux__ 분기 40+곳 이미 존재 → 그대로 빌드.
  • 명령군: GNU coreutils 표준 → CROWNY_PLATFORM=linux. sha256sum/date -d/grep/awk 전부 네이티브, 시간헬퍼.한선의 GNU 폴백이 이미 1차 경로가 됨.
  • 잠금: flock 사용 가능하나 mkdir 원자성으로 통일(mac과 동일 코드 경로 유지 → 검증 단순화).
  • 스케줄러: systemd --user timer. deploy/org.crowny.engine-settle.service + .timer, org.crowny.engine-dailybuild.{service,timer} 신규. 엔진.sh statuslaunchctl list플랫폼.한선 스케줄러상태명령()systemctl --user is-active로 분기.
  • 경로: $HOME=/home/x, ENGINE_ROOT=$HOME/crowny-engine — 이미 환경변수 기반(엔진.sh SCRIPT_DIR 자동감지)이라 무수정.
  • 설치: crowny-install.sh (apt/dnf/pacman 분기로 build-essential·libx11-dev 설치 → 빌드 → systemd --user enable).
  • CI: .github(또는 crowny-hub) 3-OS 매트릭스에서 bash -n 문법검사 + 제곱합=385 자체검사.

(f) 빌드 순서 + 이번에 만들 파일 목록 (절대경로)

신규 생성 파일

/Users/ef/crowny-engine/core/플랫폼.한선              ← (a) OS감지+명령매핑 SSOT [핵심]
/Users/ef/crowny-engine/core/플랫폼.toau             ← 컴파일 산출 (hanseonc_high)
/Users/ef/crowny-engine/lib/platform.sh              ← (a) 셸 추상화 (엔진.sh가 source)
/Users/ef/crowny-engine/win/엔진.cmd                 ← (c)(d) windows 진입(Git Bash 위임)
/Users/ef/crowny-engine/win/엔진.bat                 ← cmd 네이티브 폴백
/Users/ef/crowny-engine/win/엔진포트.ps1             ← netstat/Get-NetTCPConnection
/Users/ef/crowny-engine/win/crowny-start.cmd         ← crowny-windows-package 패턴 재사용(5단계)
/Users/ef/crowny-engine/deploy/org.crowny.engine-settle.service     ← (e) linux systemd
/Users/ef/crowny-engine/deploy/org.crowny.engine-settle.timer
/Users/ef/crowny-engine/deploy/org.crowny.engine-dailybuild.service
/Users/ef/crowny-engine/deploy/org.crowny.engine-dailybuild.timer
/Users/ef/crowny-engine/crowny-install.sh            ← (e) linux 설치(apt/dnf/pacman)
/Users/ef/crowny-engine/패키지빌드.sh                ← dist-{mac,win,linux} 3종 빌드 + CRLF처리

수정 파일 (플랫폼 분기 위임 — 라이브 무접촉, core SSOT만)

/Users/ef/crowny-engine/엔진.sh         ← 상단에 `source lib/platform.sh`; 346/355 launchctl→sched_status
/Users/ef/crowny-engine/core/돈실행.한선        ← flock → 가져오기 플랫폼.한선; 잠금획득()
/Users/ef/crowny-engine/core/달란트서버.한선    ← flock 2곳 → 잠금획득(); /Users/ef → 환경변수("HOME")
/Users/ef/crowny-engine/core/패키지빌드판정.한선 ← sha256sum → 해시명령(); date 분기 유지
/Users/ef/crowny-engine/core/구독게이트.한선    ← date -j -f → 시간헬퍼 위임
/Users/ef/crowny-engine/core/학습.한선·룩업.한선 ← grep → 한줄검색명령()(windows findstr 분기)
/Users/ef/crowny-engine/매니페스트.psv          ← 플랫폼|core/플랫폼.한선|OS감지+명령매핑 행 추가

빌드 순서 (DRYRUN 안전 — 라이브/돈/원장 무접촉)

bash# 0) 컴파일러 확인 (재사용 — 빌드 불필요)
ls /Users/ef/CrownyOS/crownyc/{crownyc,hanseonc_high}            # mac Mach-O
ls /Users/ef/crowny-win-pkg/bin/{crownyc.exe,hanseonc_high.exe}  # win PE32+ (검증됨)

# 1) core/플랫폼.한선 작성 → 컴파일 검증
/Users/ef/CrownyOS/crownyc/hanseonc_high /Users/ef/crowny-engine/core/플랫폼.한선 \
  > /Users/ef/crowny-engine/core/플랫폼.toau 2>/dev/null
/Users/ef/CrownyOS/crownyc/crownyc run /Users/ef/crowny-engine/core/플랫폼.toau   # 스모크

# 2) lib/platform.sh 작성 → 문법 검사
bash -n /Users/ef/crowny-engine/lib/platform.sh
bash -n /Users/ef/crowny-engine/엔진.sh

# 3) core 모듈에 플랫폼.한선 위임 반영 → 각 재컴파일 (2>/dev/null 필수)
for f in 돈실행 달란트서버 패키지빌드판정 학습 룩업; do
  /Users/ef/CrownyOS/crownyc/hanseonc_high /Users/ef/crowny-engine/core/$f.한선 \
    > /Users/ef/crowny-engine/core/$f.toau 2>/dev/null && echo "OK $f"
done

# 4) win/ 진입점 + deploy/ systemd + crowny-install.sh 작성

# 5) 패키지빌드.sh 실행 → dist-mac/ dist-win/ dist-linux/ 생성 (CRLF: .cmd/.bat만)
bash /Users/ef/crowny-engine/패키지빌드.sh   # DRYRUN, 기존 dist/ 무접촉

# 6) 검증: 제곱합=385 자체검사 (3 dist 모두)
# mac:   ./dist-mac/bin/crownyc run <시험.toau>
# win:   crowny-win-pkg/bin/crownyc.exe run <시험.toau> (또는 mingw 크로스 재확인)

권장 착수 순서 (의존도)

  1. core/플랫폼.한선 + lib/platform.sh (다른 모든 변경의 전제) — P0
  2. /Users/ef 하드코딩 → 환경변수 (돈실행/달란트서버, 포터빌리티.한선 패턴 재사용) — P0
  3. flock/sha256/date를 플랫폼.한선 위임 — P1
  4. win/엔진.cmd(Git Bash 경로) + crowny-start.cmd 재사용 → dist-win 즉시 가동 — P1
  5. deploy systemd + crowny-install.sh (linux 기획) — P2
  6. 패키지빌드.sh 3종 산출 + CI 매트릭스 — P2
핵심 메시지: VM·컴파일러는 이미 크로스플랫폼이라 재빌드 거의 불필요, 작업의 90%는 셸/체계() 명령을 core/플랫폼.한선 + lib/platform.sh 두 파일로 격리하는 것이다. 헌법 정합(한선씨 우선)을 위해 명령 매핑은 셸이 아닌 core/플랫폼.한선을 SSOT로 둔다.