Skip to content
Published on

Oh My OpenCode 사용법 — OpenCode를 멀티 에이전트 팀으로

공유하기
Authors

개요

터미널에서 동작하는 AI 코딩 에이전트가 하나둘 늘어나면서, 이제는 "에이전트 하나"가 아니라 "에이전트 팀"을 다루는 시대가 되었다. Oh My OpenCode는 바로 그 팀을 만들어 주는 도구다. 사이트는 ohmyopencode.com, GitHub 저장소는 opensoft/oh-my-opencode, npm 패키지는 oh-my-opencode다.

Oh My OpenCode는 독립적인 에이전트가 아니라 OpenCode 위에 얹는 의견 있는(opinionated) 플러그인이자 오케스트레이션 레이어다. OpenCode는 opencode.ai에서 배포하는 오픈소스 터미널 AI 코딩 에이전트로, 이 글의 전제 조건이다. Oh My OpenCode는 그 위에 다음을 더한다.

  • Claude Code처럼 동작하는 비동기 서브에이전트(async subagents)
  • 각자 적절한 모델에 매핑된, 큐레이션된 전문 에이전트 로스터
  • 큐레이션된 MCP 서버 모음
  • 번들로 제공되는 LSP/AST 도구
  • "Claude Code 호환" 레이어

한 문장으로 요약하면, 터미널 안에 존재하는 가상의 AI 개발팀이다. 코디네이터가 계획을 세우고, 워커가 코드를 쓰고, 스페셜리스트가 아키텍처를 검토하고 문서를 뒤진다. 이 글에서는 OpenCode 기본기부터 시작해 Oh My OpenCode 설치와 설정, 멀티 에이전트 팀 구성, 실제 작업 실행, 그리고 반드시 알아야 할 비용 안전까지 순서대로 다룬다.

참고로 다른 저자가 만든 형제 프로젝트 oh-my-openagent(별칭 lazycodex)도 존재한다. 이름이 비슷해서 헷갈릴 수 있으니 존재만 언급해 두고, 이 글은 철저히 oh-my-opencode에 집중한다.

비동기 서브에이전트가 왜 중요한가

기존 코딩 에이전트는 대체로 하나의 대화 흐름 안에서 순차적으로 움직였다. 파일을 읽고, 수정하고, 다음 파일로 넘어가는 식이다. 이 방식은 작은 변경에는 충분하지만, 수십 개 파일을 동시에 살펴야 하는 큰 작업에서는 병목이 된다. 비동기 서브에이전트는 이 병목을 깬다. 메인 에이전트가 여러 서브에이전트를 동시에 띄워, 각자 다른 파일이나 다른 관점을 병렬로 처리하게 만드는 것이다.

Claude Code가 대중화한 이 패턴을 Oh My OpenCode는 OpenCode 위에서 재현한다. 코디네이터는 큰 그림을 붙들고, 코드베이스 검색은 Explore에게, 문서 조사는 Librarian에게, 아키텍처 판단은 Oracle에게 나눠 맡긴다. 각 서브에이전트는 자기 몫만 끝내고 결과를 코디네이터에게 돌려주므로, 사람이 여러 터미널 탭을 오가며 손으로 조율하던 일을 도구가 대신한다. 이 글의 나머지는 그 팀을 실제로 굴리는 방법이다.

1. 전제 조건 — OpenCode 설치와 기본 사용법

Oh My OpenCode를 쓰기 전에 OpenCode부터 설치하고 손에 익혀야 한다. OpenCode 없이는 Oh My OpenCode도 동작하지 않는다.

1.1 설치

가장 간단한 방법은 공식 설치 스크립트다.

curl -fsSL https://opencode.ai/install | bash

npm이나 Homebrew를 선호한다면 아래 방법도 있다.

npm i -g opencode-ai
brew install anomalyco/tap/opencode

1.2 프로젝트에서 실행하기

설치가 끝나면 작업하려는 프로젝트 디렉터리로 이동해서 실행한다.

cd my-project
opencode

그러면 터미널 UI(TUI)가 뜬다. 처음 실행했다면 다음 명령을 먼저 익혀 두는 것이 좋다.

  • /init — 저장소를 스캔해서 AGENTS.md 파일을 생성한다. 프로젝트 구조와 규칙을 에이전트가 이해하는 기준 문서가 된다.
  • /connect — 모델 프로바이더를 추가한다. OpenRouter, OpenAI, Anthropic, 로컬 모델 등 원하는 것을 고르고, 프롬프트가 뜨면 API 키를 붙여 넣는다.
  • Tab — Plan 모드와 Build 모드를 토글한다. 먼저 계획을 세우고 실행으로 넘어가는 흐름을 만들 때 유용하다.
  • @ — 파일을 퍼지 검색(fuzzy-find)한다. 컨텍스트에 넣을 파일을 빠르게 찾을 수 있다.
  • /share, /undo, /redo — 세션 공유, 되돌리기, 다시 실행. 실수했을 때 요긴하다.

1.3 OpenRouter 연결 예시

/connect를 실행하면 프로바이더 목록이 나온다. OpenRouter를 선택하면 API 키를 물어보는데, openrouter.ai에서 발급받은 키를 붙여 넣으면 된다. OpenRouter는 여러 모델을 하나의 키로 접근할 수 있어서, 뒤에서 다룰 에이전트별 모델 매핑을 실험할 때 특히 편하다. 연결이 끝나면 TUI 안에서 바로 모델을 골라 쓸 수 있다.

1.4 Plan 모드와 Build 모드를 구분하는 습관

Tab으로 토글하는 두 모드는 단순한 UI 스위치가 아니라 작업 태도의 차이다. Plan 모드는 에이전트가 코드를 바로 바꾸지 않고 무엇을 어떻게 할지 먼저 제안하게 한다. Build 모드는 실제로 파일을 수정하며 실행한다. 익숙해지기 전까지는 Plan 모드에서 접근 방식을 확인하고, 방향이 맞다 싶을 때 Build 모드로 넘어가는 흐름을 권한다. 이 습관 하나만으로도 "에이전트가 엉뚱한 파일을 건드려 놓았다" 같은 사고를 크게 줄일 수 있다. 뒤에서 다룰 Oh My OpenCode의 계획 우선 흐름도 결국 이 두 모드의 확장판이다.

2. Oh My OpenCode 설치

OpenCode가 손에 익었다면 이제 팀을 꾸릴 차례다. Oh My OpenCode 설치는 프로젝트 루트에서 실행하며, Bun 또는 npx가 필요하다.

2.1 대화형 설치

가장 표준적인 방법은 bunx로 설치 프로그램을 실행하는 것이다.

bunx oh-my-opencode install

이 명령은 대화형 TUI를 띄운다. 여기서 어떤 에이전트를 쓸지, 어떤 도구와 MCP를 연결할지 단계별로 선택하면 알아서 배선(wiring)해 준다. 처음이라면 이 대화형 방식을 권한다.

2.2 비대화형 설치 (CI/에이전트용)

CI 파이프라인이나 다른 에이전트가 자동으로 돌려야 한다면 대화형 UI 없이 플래그로 지정할 수 있다.

bunx oh-my-opencode install --no-tui \
  --claude=<yes|no|max20> --openai=<yes|no> \
  --gemini=<yes|no> --copilot=<yes|no>

각 플래그로 어떤 프로바이더를 붙일지 결정한다. 예를 들어 --claude=max20은 Claude 계열을 상위 등급으로 붙이겠다는 의미이고, 필요 없는 프로바이더는 no로 끄면 된다.

2.3 설치 확인

설치가 끝나면 프로젝트에 .opencode/ 디렉터리와 관련 설정이 생겼는지 확인한다. 이후 OpenCode를 다시 실행하면, Oh My OpenCode가 배선한 에이전트와 도구, MCP가 함께 로드된 상태로 TUI가 뜬다. 만약 에이전트가 보이지 않는다면, 전역 설치를 시도하지 않았는지, 프로젝트 루트에서 실행했는지부터 다시 점검하는 것이 좋다. 대부분의 초기 문제는 실행 위치와 패키지 이름을 잘못 잡은 데서 비롯된다.

2.4 반드시 알아야 할 주의사항

설치와 관련해 흔히 저지르는 실수가 몇 가지 있다. 명확히 짚고 넘어가자.

  • 전역 설치는 지원하지 않는다. npm i -gbun add -g 방식은 지원 대상이 아니다. 반드시 프로젝트 루트에서 bunx로 실행해야 한다.
  • npm의 omo는 전혀 다른 패키지다. bunx omo를 실행하면 관계없는 패키지가 돌아가니 절대 쓰지 말 것.
  • 앞서 언급한 형제 프로젝트 oh-my-openagent(lazycodex)와도 혼동하지 말 것. 이름만 비슷할 뿐 이 가이드의 대상이 아니다.

3. 설정 — 에이전트별·카테고리별 모델 오버라이드

Oh My OpenCode의 진짜 힘은 설정에서 나온다. 어떤 에이전트가 어떤 모델을 쓸지 세밀하게 조정할 수 있기 때문이다.

3.1 설정 파일 위치

설정 파일은 두 위치에 둘 수 있다.

  • 프로젝트별: .opencode/oh-my-opencode.jsonc
  • 사용자별: ~/.config/opencode/oh-my-opencode.json

프로젝트별 설정은 해당 저장소에만 적용되고, 사용자별 설정은 모든 프로젝트에 적용된다. 팀 저장소라면 프로젝트별 파일을 커밋해 두는 편이 재현성 측면에서 유리하다.

3.2 모델 오버라이드 예시

에이전트별로, 그리고 카테고리별로 모델을 바꿀 수 있다. JSONC는 주석을 허용하므로 설정 의도를 파일 안에 남길 수 있다.

{
  "agents": {
    "explore": { "model": "ollama/qwen2.5-coder:7b" },
    "oracle": { "model": "openai/gpt-5.4" }
  },
  "categories": {
    "quick": { "model": "ollama/qwen2.5-coder:7b" },
    "deep": { "model": "openai/gpt-5.3-codex" }
  }
}

위 예시는 두 가지 축을 동시에 보여 준다. agents 블록은 특정 에이전트(예: 코드베이스를 빠르게 뒤지는 Explore)에 값싼 로컬 모델을 물려 주고, 아키텍처 상담을 맡는 Oracle에는 더 강한 모델을 붙인다. categories 블록은 작업 성격별로 묶어서, 가볍고 빈번한 quick 작업은 로컬 모델로, 무거운 deep 작업은 codex 계열로 라우팅한다. 뒤의 카테고리 절에서 이 개념을 더 자세히 다룬다.

3.3 에이전트 오버라이드와 카테고리 오버라이드의 우선순위

한 가지 자주 나오는 질문은 "에이전트에 지정한 모델과 카테고리에 지정한 모델이 충돌하면 어느 쪽이 이기는가"다. 개념적으로 정리하면 이렇다. 카테고리는 작업의 유형에 따라 동적으로 스폰되는 에이전트(예: Sisyphus-Junior)가 어떤 모델을 상속할지를 정하는 넓은 규칙이다. 반면 에이전트별 지정은 이름이 고정된 특정 에이전트(예: Oracle, Explore)에 직접 붙는 좁은 규칙이다. 따라서 실무에서는 이름이 명확한 상시 에이전트는 agents에서, 작업 유형에 따라 갈라지는 실행자들은 categories에서 관리하는 식으로 역할을 나누면 설정이 깔끔해진다.

3.4 팀 저장소에서의 설정 공유

프로젝트별 .opencode/oh-my-opencode.jsonc를 저장소에 커밋해 두면, 팀원 모두가 같은 에이전트-모델 매핑으로 작업하게 된다. 이는 "내 로컬에서는 값싼 모델로 잘 돌았는데 동료 환경에서는 비싼 모델로 튀더라" 같은 재현성 문제를 줄여 준다. 다만 API 키 같은 비밀 값은 이 파일에 넣지 않는다. 키는 앞서 본 /connect 흐름이나 프로바이더별 환경 변수로 관리하고, 설정 파일에는 모델 선택과 동시성 제한 같은 정책만 남기는 것이 원칙이다.

4. 멀티 에이전트 팀 — 에이전트 로스터

Oh My OpenCode는 역할이 정해진 에이전트 로스터를 제공한다. 각 에이전트는 이름과 책임, 그리고 권장 모델이 정해져 있다. 아래 표는 역할군별로 정리한 것이다.

역할군에이전트책임권장 모델 / 특징
오케스트레이터Sisyphus메인 코디네이터. 계획을 세우고 위임하며, 공격적인 병렬 실행으로 작업을 밀어붙인다기본 Claude Opus
오케스트레이터Atlas투두리스트 오케스트레이터Claude Sonnet
계획Prometheus전략 플래너. Tab 또는 /start-work로 시작하며, 인터뷰로 범위를 못 박는다계획 특화
계획Metis갭 분석기(gap analyser). 놓친 부분을 찾는다높은 temperature
계획Momus무자비한 계획 리뷰어. OK/reject 게이트 역할승인 게이트
워커Hephaestus자율 딥 코더. 강력한 codex급 모델을 기대한다codex급 모델
워커Sisyphus-Junior동적으로 스폰되는 실행자. 자신을 띄운 카테고리의 모델을 상속한다카테고리 상속
스페셜리스트Oracle아키텍처/디버깅 상담역 (읽기 전용 성향)강한 추론 모델
스페셜리스트Librarian문서 리서처. 값싸고 빠른 모델로 충분하다저비용 모델
스페셜리스트Exploregrep/패턴으로 코드베이스를 빠르게 병렬 검색빠른 모델
스페셜리스트Multimodal Looker비전. 다이어그램/PDF/이미지를 읽는다멀티모달 모델

이 로스터를 이해하는 핵심은 "누가 무엇을, 어떤 비용으로 하는가"다. 오케스트레이터와 플래너는 전체 흐름을 통제하고, 워커는 실제로 코드를 만들며, 스페셜리스트는 읽기 전용이거나 도구가 제한된 서브에이전트로 특정 작업만 담당한다. 예를 들어 문서를 뒤지는 Librarian이나 코드베이스를 검색하는 Explore에는 굳이 비싼 모델을 붙일 이유가 없고, 자율적으로 깊게 코드를 쓰는 Hephaestus에는 강한 모델이 필요하다.

로스터를 실제 모델 예산에 매핑할 때는 대략 다음 원칙으로 생각하면 좋다.

  • 오케스트레이터(Sisyphus, Atlas): 전체를 조율하므로 판단력이 좋은 상위 모델이 유리하다. 기본값을 존중하되 예산이 빠듯하면 Atlas 쪽부터 낮춘다.
  • 플래너(Prometheus, Metis, Momus): 계획 품질이 결과를 좌우하므로 너무 값싼 모델은 피한다. Metis는 높은 temperature로 빈틈을 찾는 역할임을 기억한다.
  • 워커(Hephaestus, Sisyphus-Junior): 실제 구현 품질에 직결된다. Hephaestus에는 codex급을, Sisyphus-Junior에는 카테고리를 통해 적절한 모델을 상속시킨다.
  • 스페셜리스트(Oracle, Librarian, Explore, Multimodal Looker): 역할 편차가 크다. Oracle과 Multimodal Looker에는 강한 모델을, Librarian과 Explore에는 값싸고 빠른 모델을 배정하는 것이 비용 효율적이다.

4.1 읽기 전용 스페셜리스트가 주는 안전성

스페셜리스트 그룹이 읽기 전용이거나 도구가 제한되어 있다는 점은 단순한 제약이 아니라 설계상의 안전장치다. Oracle이 아키텍처를 진단하거나 Explore가 코드를 훑을 때, 이들이 파일을 직접 수정하지 못하도록 묶어 두면, 상담 과정에서 의도치 않게 코드가 바뀌는 사고를 원천적으로 막을 수 있다. 실제 변경은 Hephaestus나 Sisyphus-Junior 같은 워커에게만 맡기고, 스페셜리스트는 조언과 정보만 제공하도록 역할을 분리하는 것이다. 이 구조 덕분에 병렬로 여러 에이전트가 돌아도, 파일을 쓰는 주체는 소수의 워커로 좁혀져 통제가 쉬워진다.

5. ultrawork로 작업 실행하기

에이전트 팀은 있지만, 그냥 프롬프트를 넣는다고 자동으로 팀이 움직이지는 않는다. 멀티 에이전트 위임은 명시적으로 트리거해야 한다.

5.1 트리거 키워드

멀티 에이전트 위임은 프롬프트에 ultrawork라는 키워드(접두사 ulw)를 넣어야 발동한다. 이것은 자동이 아니다. 즉, 평범한 프롬프트는 단일 에이전트로 처리되고, 팀 전체를 동원하려면 의도적으로 ultrawork(또는 ulw)를 붙여야 한다는 뜻이다.

5.2 계획 우선 흐름

무거운 작업일수록 바로 실행보다 계획을 먼저 세우는 편이 좋다. Tab 또는 /start-work로 Prometheus를 띄우면, 이 플래너가 인터뷰를 통해 작업 범위를 명확히 못 박는다. 범위가 흐릿한 채로 병렬 실행을 돌리면 서브에이전트들이 제각기 다른 방향으로 달려갈 수 있으므로, 큰 작업은 계획 → 실행 순서를 지키는 것이 안전하다.

5.3 카테고리 라우팅

위임된 작업은 카테고리를 통해 라우팅된다. 각 카테고리는 권장 모델과 폴백 체인(fallback chain)에 매핑되어 있다. 카테고리는 다음과 같다.

  • visual-engineering
  • artistry
  • ultrabrain
  • deep
  • unspecified-high
  • unspecified-low
  • quick
  • writing

작업이 어느 카테고리로 분류되느냐에 따라 어떤 모델이 붙는지가 결정된다. 3장에서 본 것처럼 카테고리별 모델을 오버라이드하면, 비용과 성능을 작업 성격에 맞춰 조절할 수 있다.

5.4 시작 오버헤드

한 가지 현실적인 주의점이 있다. 멀티 에이전트 오케스트레이션에는 시작 오버헤드가 실재한다. 본격적인 작업이 시작되기 전에 대략 15,000~25,000 토큰이 소모된다. 작은 작업에 이 오버헤드를 물리면 손해이므로, 언제 팀을 동원할지에 대한 판단이 중요하다. 이 판단은 마지막 장에서 정리한다.

5.5 전형적인 작업 흐름

앞의 요소들을 하나로 이으면 큰 작업의 표준 흐름은 다음과 같이 정리된다.

  1. Tab 또는 /start-work로 Prometheus를 띄워 계획을 세운다. 이때 인터뷰에 성실히 답해 범위를 좁힌다.
  2. 필요하면 Metis가 계획의 빈틈을 찾고, Momus가 계획을 승인하거나 반려한다.
  3. 계획이 통과되면 프롬프트에 ultrawork(또는 ulw)를 붙여 멀티 에이전트 실행을 발동한다.
  4. Sisyphus가 작업을 카테고리별로 쪼개 위임한다. 검색은 Explore, 문서는 Librarian, 깊은 구현은 Hephaestus, 아키텍처 판단은 Oracle이 맡는다.
  5. 각 서브에이전트의 결과가 코디네이터로 모이면, 최종 변경을 검토하고 필요하면 /undo로 되돌린다.

이 흐름을 몸에 익히면 "계획 없이 바로 ultrawork" 같은 위험한 습관을 피할 수 있다. 계획 단계가 짧더라도 범위를 못 박아 두는 것이, 병렬 실행이 엉뚱한 방향으로 폭주하는 것을 막는 가장 값싼 보험이다.

6. 비용 안전 — 반드시 챙길 것

이 부분은 솔직하게 짚어야 한다. 멀티 에이전트 도구는 편리한 만큼 비용이 통제를 벗어날 위험도 있다.

6.1 실제로 있었던 사고

초기에 확인된 버그로 인해 예상치 못한 큰 지출이 발생한 사례가 있다. 어떤 사용자는 하루 오후에만 약 438달러가 청구되었다고 보고했다. 원인은 조용히 일어난 모델 라우팅(silent model routing)과 폭주하는 루프(runaway loop)였다. 즉, 사용자가 의도하지 않은 비싼 모델로 작업이 흘러가고, 그것이 멈추지 않고 반복되면서 비용이 눈덩이처럼 불어난 것이다.

6.2 동시성 제한으로 방어하기

가장 실용적인 방어책은 설정에서 프로바이더 동시성(concurrency)을 제한하는 것이다. 아래처럼 특정 프로바이더의 동시 실행 수를 묶어 둘 수 있다.

{ "background_task": { "providerConcurrency": { "google": 1 } } }

이 설정은 백그라운드 작업에서 google 프로바이더의 동시 실행을 1로 제한한다. 폭주 루프가 발생해도 병렬 호출이 억제되므로 피해를 줄일 수 있다.

6.3 그 외 안전 수칙

동시성 제한 외에도 다음을 습관화하면 좋다.

  • 카테고리와 모델 설정을 감사(audit)한다. 어떤 작업이 어떤 모델로 가는지 명시적으로 파악해 둔다.
  • 대량으로 호출되는 서브에이전트에는 더 값싼 모델을 우선 배정한다. Librarian이나 Explore처럼 빈번한 역할이 대표적이다.
  • 프로바이더의 지출 대시보드를 주기적으로 확인한다. 이상 징후를 조기에 발견하는 것이 최선의 방어다.

6.4 큰 작업 전 사전 점검

비용 사고는 대개 "무심코 돌린 큰 작업"에서 터진다. 그래서 규모 있는 작업을 ultrawork로 발동하기 전에, 세 가지만 눈으로 확인하는 습관을 들이면 좋다. 첫째, 설정 파일에서 각 카테고리가 어떤 모델로 매핑되어 있는지 다시 본다. 둘째, 동시성 제한이 걸려 있는지 확인한다. 셋째, 지금 붙은 프로바이더가 유료 등급이라면 대략적인 예상 비용을 머릿속에 그려 둔다. 이 30초짜리 점검이 앞서 본 하루 약 438달러 같은 사고를 막는 가장 현실적인 방벽이다.

7. 언제 쓰고, 언제 바닐라 OpenCode를 쓸까

마지막으로 가장 실용적인 질문이다. 모든 작업에 Oh My OpenCode를 쓰는 것은 정답이 아니다.

Oh My OpenCode가 빛나는 경우는 크고, 여러 파일에 걸쳐 있으며, 여러 단계로 나뉘는 작업이다. 리서치 → 계획 → 구현으로 이어지는 흐름처럼, 병렬 서브에이전트의 이점을 살릴 수 있는 작업이 여기에 해당한다. 이럴 때 팀은 명백한 파워 배가기(power multiplier)가 된다.

반대로, 단일 컨텍스트 윈도에 들어가는 작은 작업이나, 예산형(budget) 모델을 돌리는 경우에는 바닐라 OpenCode가 낫다. 예산형 모델은 하나의 깔끔한 프롬프트에서 더 좋은 결과를 낸다. 이런 작업에 멀티 에이전트를 동원하면 앞서 본 시작 오버헤드만 물게 되어 순수한 낭비가 된다.

정리하면 이렇다. Oh My OpenCode는 알맞은 작업에는 강력한 파워 배가기이고, 맞지 않는 작업에는 오버헤드일 뿐이다. 작업의 규모와 단계 수, 그리고 병렬화의 이득을 기준으로 선택하면 된다.

7.1 선택 체크리스트

망설여진다면 다음 질문에 답해 보자. "예"가 많을수록 Oh My OpenCode 쪽이다.

  • 이 작업은 세 개 이상의 파일을 건드리는가.
  • 리서치, 계획, 구현처럼 성격이 다른 단계로 나뉘는가.
  • 서로 독립적이라 병렬로 진행해도 되는 하위 작업이 있는가.
  • 강한 모델을 붙일 예산 여유가 있는가.

반대로 "이건 프롬프트 하나로 끝난다", "예산형 로컬 모델만 쓴다", "컨텍스트가 파일 한두 개면 충분하다"에 해당한다면 바닐라 OpenCode가 맞다. 도구를 고르는 기준은 취향이 아니라 작업의 형태다.

7.2 한눈에 보는 요약

이 글의 핵심을 순서대로 다시 정리하면 다음과 같다.

  • OpenCode를 먼저 설치하고 /init, /connect, Tab을 손에 익힌다.
  • 프로젝트 루트에서 bunx oh-my-opencode install로 팀을 배선한다. 전역 설치와 bunx omo는 금물이다.
  • .opencode/oh-my-opencode.jsonc에서 에이전트별·카테고리별 모델을 조정한다.
  • 큰 작업은 Tab 또는 /start-work로 계획을 세운 뒤 ultrawork로 실행한다.
  • 동시성 제한을 걸고, 카테고리-모델 매핑을 감사하고, 지출 대시보드를 주기적으로 본다.
  • 작은 작업이나 예산형 모델에는 바닐라 OpenCode를 쓴다.

이 여섯 줄만 지켜도 Oh My OpenCode의 이점은 대부분 취하고 위험은 대부분 피할 수 있다.

참고 자료