Skip to content

Latest commit

 

History

History
133 lines (99 loc) · 8.75 KB

File metadata and controls

133 lines (99 loc) · 8.75 KB

연재 3회: Fundation Setup

가장 먼저 튼튼한 기반을 다집니다. 이 프로젝트는 모든 구성 요소(서버, 앱, 플러그인)가 하나의 저장소에 있는 Monorepo 구조를 따릅니다.

은유: 이것은 **"온 가족의 짐을 하나의 거대한 트렁크에 담는 것"**과 같습니다. 각자 작은 가방을 들고 다니면 잃어버리기 쉽지만, 하나로 묶어 관리하면 필요한 물건을 찾기도, 통째로 옮기기도 훨씬 쉬워지죠.


1-1. 환경 설정 (Micro-Process)

이제 2회에서 준비한 '베이스캠프(openclaw-lab)' 폴더에 들어가 본격적으로 OpenClaw의 **'국가 헌법(규칙)'**을 세워보겠습니다.

  1. 준비 상태 확인: VSCode를 열고 openclaw-lab 폴더가 열려 있는지 확인하세요. 터미널(Ctrl + `)도 준비되어 있어야 합니다.
  2. 프로젝트 정체성 선포: 아래 명령어로 우리 집의 문패(package.json)를 답니다.
    pnpm init
  3. 핵심 부품 로컬 조립: 우리 프로젝트에서만 쓸 수 있도록 부품들을 정식으로 주문합니다.
    pnpm add hono @hono/node-server @whiskeysockets/baileys better-sqlite3
    pnpm add -D typescript @types/node

많은 분들이 "일단 server.ts 파일 만들고 코드부터 치면 안 되나요?" 라고 묻습니다. 결론부터 말하면, OpenClaw(Moltbot) 같은 거대한 프로젝트에서는 불가능합니다. 그 이유를 아주 쉽게 설명해 드립니다.

1. 은유(Metaphor): 건물을 짓기 전의 "토지 용도 변경"

  • 일반적인 코딩 (HTML/JS): 맨땅에 텐트를 치는 것과 같습니다. 그냥 폴대(index.html) 꽂고 천(script.js) 덮으면 집이 됩니다. 규칙이 없어도 됩니다.
  • OpenClaw(Moltbot) (TS/ESM): 100층짜리 마천루를 짓는 것과 같습니다. 땅을 파기 전에 "여기는 상업지구이며, 내진 설계 기준은 7.0이고, 철근은 KS규격을 써야 한다"법적/행정적 허가(tsconfig.json) 가 먼저 떨어져야 합니다. 허가증 없이 철근(import)을 하나라도 세우면 공사 중지 명령(Syntax Error)이 떨어집니다.

2. 비교(Comparison): 동네 축구 vs 월드컵

  • 동네 축구 (Legacy JS Project): 심판도 없고 규칙도 대충입니다. "손만 안 쓰면 돼." 바로 공 차면 됩니다.
  • 월드컵 (Modern TypeScript Project): 경기 시작 전에 "오프사이드 반칙 기준", "VAR 판독 여부", "교체 선수 숫자"가 룰북(tsconfig.json)에 정의되어야 합니다. OpenClaw(Moltbot)은 월드컵 결승전급의 엄격한 규칙 하에 돌아가는 시스템입니다.

3. 실제 예시 (Real World Scenario)

만약 설정 없이 바로 코드를 짠다면?

  • 개발자: (자신있게) import { Server } from 'http';
  • 컴퓨터(Node.js): "잠깐, import가 뭐죠? 저는 옛날 방식(require)밖에 모르는데요?" -> 에러 발생 (Crash)
  • 개발자: (당황하며) "어? 요즘 다 이거 쓰던데?"
  • 컴퓨터: "그건 tsconfig.json 이라는 번역기가 있을 때 얘기입니다. 저한테 미리 언질을 안 주셨잖아요."

결론: tsconfig.json을 먼저 만드는 것은 컴퓨터에게 "지금부터 우리는 최신 유행어(ESM)와 엄격한 문법(TypeScript)으로 대화할 거야. 준비해." 라고 선전포고를 하는 것입니다. 이 합의가 없으면 단 한 줄의 코드도 실행되지 않습니다.

---

### 1-3. 🛠️ [실전 가이드] tsconfig.json 설정: 새로운 나라의 헌법 제정

"Moltbot은 대형 프로젝트라서 이미 설정이 다 되어있지만, 맨땅에서 시작하는 나만의 작은 앱은 어떻게 시작하나요?"

1. 은유(Metaphor): 새로운 국가를 세울 때의 "헌법 제정"

백지에 그림을 그리는 것과 같습니다. 나라를 처음 세울 때, 우리 국민은 어떤 언어를 쓰고(Target), 주변 나라와는 어떻게 소통하며(Module), 범죄(Error)에는 얼마나 엄격할 것인지(Strict)를 정하는 **'국가 헌법'**을 만드는 과정이 바로 tsconfig.json 초기화입니다. 헌법이 모호하면 나라가 혼란에 빠지듯, 이 설정이 부실하면 개발 과정 내내 충돌이 일어납니다.

2. 개념(Concept): 초기화의 두 가지 경로 (자동 vs 실전)

TypeScript는 개발자가 처음부터 고생하지 않도록 **'표준 헌법 초안'**을 자동으로 생성해주는 도구(npx tsc --init)를 제공합니다. 초보자는 자동 생성된 초안에서 시작하고, 숙련자는 프로젝트의 목적(고성능 서버, 프론트엔드 등)에 맞춰 그 초안을 수정하여 사용합니다.

3. 코드(Code): 헌법의 탄생과 핵심 3조항

  • 방법 A: 표준 초안 자동 생성 (권장) 연재 2회에서 사용하던 터미널 창을 그대로 사용하세요. 다음 명령어를 입력하면 수중한 주석과 함께 설정 파일이 생성됩니다.

    npx tsc --init
  • 방법 B: 실전 프로젝트 핵심 설정 (수동 수정) 자동 생성된 파일에서 아래 **'핵심 3개 조항'**만은 반드시 확인하고 수정해 주세요.

    {
      "compilerOptions": {
        "target": "ES2022",    // [제1조] 사용할 언어의 문법 수준 (최신 사투리 인정)
        "module": "NodeNext",  // [제2조] 소통 규약 (최신 스마트폰 규격 사용)
        "strict": true         // [제3조] 법 집행의 엄격함 (무관용 원칙)
      }
    }

4. 배경 및 실전 가이드(Context & Guide): 왜 이 3가지인가?

  • target: ES2022인가?: 과거에는 구식 브라우저를 위해 코드를 어렵게 번역해야 했습니다. 하지막 지금 우리가 만드는 서버(Node.js 22)는 똑똑합니다. 최신 문법을 그대로 써야 속도가 빠르고 코드가 깔끔해집니다.
  • module: NodeNext인가?: 자바스크립트 세계는 지금 '구식(CommonJS)'과 '신식(ESM)'이 교체되는 과도기입니다. NodeNext는 "우리는 신식을 쓰되, 구식도 알아듣겠다"는 가장 현명한 중재안입니다.
  • strict: true인가?: "대충 짜고 나중에 고치지 뭐"라는 생각은 개발자의 가장 큰 착각입니다. 처음부터 엄격하게 관리하는 것이, 나중에 버그를 찾느라 밤을 새우는 것보다 100배 경제적입니다.

Tip

요약: 작은 프로젝트라도 npx tsc --init으로 시작하고, Target(최신), Module(NodeNext), Strict(True) 이 세 가지만 기억하세요. 이것만으로도 여러분의 프로젝트는 구글이나 메타(Facebook) 부럽지 않은 튼튼한 기초를 갖추게 됩니다.

1-3-1. TypeScript 설정 (tsconfig.json) - 아키텍처 심층 분석

1. 은유: 수족관을 탈출한 자바스크립트

  • 자바스크립트(JavaScript): 원래 브라우저라는 '수족관' 안에서만 살 수 있는 물고기였습니다.
  • Node.js: 이 물고기에게 **'기계 슈트'**를 입혀 수족관 밖(서버)에서 파일을 만지고 DB를 관리하는 **'천하무적 일꾼'**으로 만든 것입니다.

2. 개념(Concept): TypeScript 컴파일러 설정 안내서

이 파일은 tsc(컴파일러)에게 "이 프로젝트의 소스 코드는 여기에 있고, 번역된 결과물은 저기에 저장하고, 번역할 때는 이런 규칙을 지켜줘!"라고 상세히 지시하는 메뉴얼입니다. 단순한 설정 파일이 아니라, 프로젝트의 **정체성(ESM vs CJS)**을 결정짓는 핵심 문서입니다.

은유로 보는 주요 조항들:

  • outDir (dist): 번역이 끝난 문서(결과물)를 차곡차곡 쌓아두는 **'출고 창고'**입니다.
  • rootDir (src): 번역가가 작업해야 할 원본 원고가 들어있는 **'원고 보관함'**입니다.
  • esModuleInterop: 서로 다른 통신 규격(ESM과 CJS)을 쓰는 부품들이 대화할 수 있게 해주는 **'유니버설 어댑터'**입니다.
  • skipLibCheck: "이미 검증된 외부 서적까지 일일이 오타 검사를 하느라 시간을 낭비하지 않겠다"는 '검수 생략' 조항입니다.

3. 코드(Code): 원본 tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "noEmitOnError": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["src/**/*"],
  "exclude": [
    "node_modules",
    "dist",
    "src/**/*.test.ts",
    "src/**/*.test.tsx",
    "src/**/test-helpers.ts"
  ]
}