Learning
레슨 2 / 3·20분

컴포넌트와 엔티티

ECS(Entity-Component-System) 아키텍처

A-Frame은 ECS 아키텍처를 기반으로 합니다. Entity()는 빈 컨테이너이고, Component는 기능(외형, 동작 등)을 부여하는 속성입니다. 는 사실 geometry="primitive: box"와 material 컴포넌트가 붙은 의 축약형입니다. 커스텀 컴포넌트를 만들면 원하는 기능을 자유롭게 추가할 수 있습니다.

html
<!-- a-entity + 컴포넌트 조합 — a-box와 동일한 결과 -->
<a-entity
  geometry="primitive: box; width: 1; height: 1; depth: 1"
  material="color: #e74c3c; metalness: 0.5; roughness: 0.3"
  position="0 1 -3"
  rotation="0 45 0"
></a-entity>

<!-- 구 + 커스텀 재질 -->
<a-entity
  geometry="primitive: sphere; radius: 0.8; segmentsWidth: 64"
  material="color: #3498db; shader: standard; metalness: 0.8"
  position="-2 1 -4"
></a-entity>

<!-- 조명 컴포넌트 -->
<a-entity
  light="type: directional; color: #ffffff; intensity: 0.8"
  position="1 4 2"
></a-entity>

<a-entity
  light="type: point; color: #ff6600; intensity: 1; distance: 10"
  position="0 3 -3"
></a-entity>

<a-entity
  light="type: ambient; color: #404060; intensity: 0.4"
></a-entity>

카메라, 커서, 커스텀 컴포넌트

html
<!-- 카메라와 커서 설정 -->
<a-entity
  camera
  look-controls
  wasd-controls="acceleration: 30"
  position="0 1.6 0"
>
  <!-- 시선 커서 (VR에서 응시로 선택) -->
  <a-entity
    cursor="fuse: true; fuseTimeout: 1500"
    position="0 0 -1"
    geometry="primitive: ring; radiusInner: 0.015; radiusOuter: 0.025"
    material="color: white; shader: flat"
  ></a-entity>
</a-entity>
javascript
// ── 커스텀 컴포넌트 등록 ──
AFRAME.registerComponent('color-change', {
  // schema — 컴포넌트의 속성(파라미터) 정의
  schema: {
    baseColor: { type: 'color', default: '#3498db' },
    hoverColor: { type: 'color', default: '#e74c3c' },
  },

  // init — 컴포넌트 초기화 시 1회 실행
  init: function () {
    const el = this.el;
    const data = this.data;

    el.setAttribute('material', 'color', data.baseColor);

    el.addEventListener('mouseenter', () => {
      el.setAttribute('material', 'color', data.hoverColor);
    });

    el.addEventListener('mouseleave', () => {
      el.setAttribute('material', 'color', data.baseColor);
    });
  },

  // tick — 매 프레임 실행 (선택사항)
  tick: function (time, deltaTime) {
    // 매 프레임 실행할 로직
  },

  // remove — 컴포넌트 제거 시 정리
  remove: function () {
    // 이벤트 리스너 정리 등
  },
});

// HTML에서 사용:
// <a-box color-change="baseColor: #2ecc71; hoverColor: #f39c12"></a-box>
  • — 빈 엔티티, 컴포넌트를 붙여 기능 부여
  • geometry 컴포넌트 — 형태 정의 (primitive, width, height 등)
  • material 컴포넌트 — 외형 정의 (color, metalness, roughness)
  • light 컴포넌트 — 조명 (directional, point, ambient, spot)
  • camera + look-controls + wasd-controls — 1인칭 카메라
  • cursor — 마우스/시선 기반 선택 (fuse: VR 응시 선택)
  • AFRAME.registerComponent — 커스텀 동작을 정의하는 핵심 API
💡

AFRAME.registerComponent의 schema에서 타입을 정의하면 HTML 속성 문자열이 자동으로 파싱됩니다. type: "vec3"이면 "1 2 3" 문자열이 {x:1, y:2, z:3} 객체로 변환됩니다. schema 없이도 컴포넌트를 만들 수 있지만, schema를 정의하면 재사용성과 가독성이 높아집니다.