Skip to main content

Lightning 웹 구성 요소 만들기

학습 목표

이 유닛을 완료하면 다음을 수행할 수 있습니다.

  • 각 구성 요소 파일의 내용을 설명합니다.
  • Lightning 웹 구성 요소용 JavaScript 메서드를 생성합니다.
  • 구성 요소 JavaScript에서 수명 주기 후크를 사용합니다.

플레이 타임

Salesforce의 특정 객체와 별개로 데이터 표시 요소를 구축하려고 한다고 가정해 보겠습니다. 좋은 예로 ebikes 샘플 리포지토리의 productCard 구성 요소가 있습니다. 이 카드 구성 요소를 살펴보고 처음부터 직접 버전을 만들어서 완전한 Lightning 웹 구성 요소로 발전하는 과정을 확인해 보겠습니다. 구성 요소의 각 부분을 만들고 다양한 샘플을 살펴보면 기본 사항을 빠르게 익힐 수 있습니다.

조직으로 한 걸음 더 나아가기

이 유닛에서는 Salesforce 확장과 함께 Visual Studio Code를 사용하여 Lightning 웹 구성 요소를 개발합니다.

필요 사항

첫 번째 유닛에서 설명한 대로 계속 진행하려면 Salesforce DX에 어느 정도 익숙해야 합니다. 이 유닛을 완료하는 데 필요한 사항은 다음과 같습니다.

  • Salesforce 확장팩이 포함된 Visual Studio Code(VS Code)
  • Salesforce CLI

이러한 요구 사항을 충족하려면 빠른 시작: Lightning 웹 구성 요소 프로젝트를 완료하세요.

HTML 파일 살펴보기

모든 Lightning 웹 구성 요소 HTML 파일에는 template 태그가 포함되어 있습니다. 그리고 template 태그에는 구성 요소의 구조를 정의하는 HTML이 포함됩니다. ebikes 리포지토리의 productCard 구성 요소의 간단한 버전에 대한 HTML을 살펴보겠습니다.

이 예제를 VS Code에 붙여넣어 다음 단계를 따르세요.

  1. VS Code의 Command Palette(명령 팔레트)에서 SFDX: Create Project(SFDX: 프로젝트 만들기)를 선택하여 프로젝트를 생성합니다. 표준 템플릿을 수락하고 프로젝트 이름을 bikeCard로 지정합니다.
  2. force-app/main/default에서 lwc 폴더를 마우스 오른쪽 버튼으로 클릭하고 SFDX: Create Lightning Web Component(SFDX: Lightning 웹 구성 요소 만들기)를 선택합니다.
  3. 새 구성 요소의 이름으로 app(앱)을 입력합니다.
  4. Enter 키를 누른 다음 Enter 키를 다시 눌러 기본값인 force-app/main/default/lwc를 수락합니다.
  5. 다음을 app.html에 붙여넣습니다(파일에 있는 기존 HTML을 모두 대체함).
    <template>
      <div>
        <div>Name: {name}</div>
        <div>Description: {description}</div>
        <div>Category: {category}</div>
        <div>Material: {material}</div>
        <div>Price: {price}</div>
        <div><img src={pictureUrl} alt={name}/></div>
      </div>
    </template>
    중괄호 {} 안의 식별자는 해당 JavaScript 클래스에서 같은 이름의 필드에 바인딩됩니다.
  6. 다음을 app.js에 붙여넣습니다.
    import { LightningElement } from 'lwc';
    export default class App extends LightningElement {
      name = 'Electra X4';
      description = 'A sweet bike built for comfort.';
      category = 'Mountain';
      material = 'Steel';
      price = '$2,700';
      pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg';
    }
  7. 파일을 저장합니다.

이제 실제 사례를 살펴보겠습니다. 여러분은 데이터를 표시하려 하지만, 로드하는 데 시간이 걸린다는 것을 알고 있는 상황입니다. 사용자가 무슨 문제가 생긴건 아닌지 생각하게 만드는 일은 없어야 하죠. 여러분은 템플릿 내에서 lwc:iflwc:else 조건부 지시문을 사용하여 렌더링되는 시각적 요소를 결정할 수 있습니다.

  1. 다음을 app.html에 붙여넣습니다. “display”의 div 태그의 컨텐츠는 HTML 파일에서 ready 값이 true가 될 때까지 표시되지 않습니다.
    <template>
      <template lwc:if={ready}>
        <div id="display">
          <div>Name: {name}</div>
          <div>Description: {description}</div>
          <div>Category: {category}</div>
          <div>Material: {material}</div>
          <div>Price: {price}</div>
          <div><img src={pictureUrl} alt={name}/></div>
        </div>
      </template>
      <template lwc:else>
        <div id="waiting">Loading…</div>
      </template>
    </template>
  2. 다음을 app.js에 붙여넣습니다. 여기에는 데이터 값이 저장되고 3초 타이머가 설정됩니다. 그리고 3초가 지나면 컨텐츠가 표시됩니다. (물론 이것은 테스트용입니다.)
    import { LightningElement } from 'lwc';
    export default class App extends LightningElement {
      name = 'Electra X4';
      description = 'A sweet bike built for comfort.';
      category = 'Mountain';
      material = 'Steel';
      price = '$2,700';
      pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg';
      ready = false;
      connectedCallback() {
        setTimeout(() => {
          this.ready = true;
        }, 3000);
      }
    }
  3. 파일을 저장합니다.

기본 Lightning 웹 구성 요소

이제 모든 구성 요소를 처음부터 새로 구축하지 않아도 됩니다. 이제 기본 Lightning 웹 구성 요소를 사용해 보겠습니다. 물론 필드 유형, 디스플레이 컨트롤러, 탐색 항목 등 많은 구성 요소가 있습니다. 모든 구성 요소는 구성 요소 참조에 나열되어 있습니다.

자전거의 디테일을 돋보이게 만들어 보겠습니다. app.html 파일에서, 마지막 예제의 소재와 카테고리에 대한 div 태그를 Lightning 배지 구성 요소로 바꿉니다. HTML은 다음과 같습니다.

<template>
  <template lwc:if={ready}>
    <div id="display">
      <div>Name: {name}</div>
      <div>Description: {description}</div>
      <lightning-badge label={material}></lightning-badge>
      <lightning-badge label={category}></lightning-badge>
      <div>Price: {price}</div>
      <div><img src={pictureUrl} alt={name}/></div>
    </div>
  </template>
  <template lwc:else>
    <div id="waiting">Loading…</div>
  </template>
</template>

파일을 저장합니다.

SteelMountain이라는 단어가 배지로 표시됩니다. 아주 간단하죠.

구성 요소 빌드 구조

구성 요소에는 동일한 이름의 폴더와 해당 파일만 있으면 됩니다. 이름과 위치에 따라 자동으로 연결됩니다.

폴더의 구성 요소 파일

모든 Lightning 웹 구성 요소에는 하이픈이 있어 폴더 이름과 구분할 수 있는 네임스페이스가 있습니다. 예를 들어, 기본 네임스페이스 c에 폴더 이름이 app인 Lightning 웹 구성 요소의 마크업은 <c-app>입니다.

하지만 Salesforce Platform에서는 구성 요소 폴더나 파일 이름에 하이픈을 사용할 수 없습니다. 그렇다면, 구성 요소의 이름에 ‘mycomponent’와 같이 두 단어 이상이 포함된 경우에는 어떻게 해야 할까요? 폴더와 파일의 이름을 my-component로 지정할 수는 없지만 방법이 있습니다.

카멜 표기법을 사용하여 구성 요소의 이름을 myComponent로 표기하는 것입니다. 카멜 표기법 구성 요소의 폴더 이름은 마크업에서 kebab-case로 매핑됩니다. 마크업에서 폴더 이름이 myComponent인 구성 요소를 참조하려면 <c-my-component>를 사용합니다.

예를 들어, LWC 샘플 리포지토리에는 viewSource 구성 요소에 대한 파일이 있는 viewSource 폴더가 있습니다. hello 구성 요소가 HTML에서 viewSource 구성 요소를 참조하는 경우에는 c-view-source를 사용합니다.

좋습니다. 이제 JavaScript를 살펴보겠습니다.

JavaScript로 작업하기

여기에서 작업을 실현할 수 있습니다. 지금까지 살펴본 것처럼 JavaScript 메서드는 입력, 데이터, 이벤트, 상태 변경 등으로 구성 요소를 작동시키기 위해 수행할 작업을 정의합니다.

Lightning 웹 구성 요소의 JavaScript 파일에는 최소한 이 코드가 포함되어야 하며, 여기서 MyComponent는 구성 요소 클래스를 할당하는 이름입니다.

import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
}

export 문은 LightningElement 클래스를 확장하는 클래스를 정의합니다. 모범 사례로, 클래스 이름은 일반적으로 JavaScript 클래스의 파일 이름과 일치하지만 필수 사항은 아닙니다.

LWC 모듈

Lightning 웹 구성 요소는 모듈(내장 모듈은 ECMAScript 6에 소개됨)을 사용하여 핵심 기능을 번들로 묶고, 구성 요소 파일의 JavaScript에서 액세스할 수 있도록 합니다. Lightning 웹 구성 요소의 핵심 모듈은 lwc입니다.

import 문으로 모듈을 시작하고 구성 요소가 사용하는 모듈의 기능을 지정합니다.

import 문은 JavaScript가 lwc 모듈의 LightningElement 기능을 사용한다는 것을 나타냅니다.

// import module elements
import { LightningElement} from 'lwc';
// declare class to expose the component
export default class App extends LightningElement {
  ready = false;
  // use lifecycle hook
  connectedCallback() {
    setTimeout(() => {
      this.ready = true;
    }, 3000);
  }
}
  • LightningElement는 Lightning 웹 구성 요소의 기본 클래스로, connectedCallback()을 사용할 수 있습니다.
  • connectedCallback() 메서드는 수명 주기 후크 중 하나입니다. 수명 주기 후크에 대한 자세한 내용은 다음 섹션에서 살펴보겠습니다. 지금은 구성 요소가 문서 객체 모델(DOM)에 삽입될 때 메서드가 트리거된다는 점만 알아두세요. 이 경우, 타이머가 시작됩니다.

수명 주기 후크

Lightning 웹 구성 요소는 구성 요소의 수명 주기에서 중요한 이벤트에 코드를 '후크'할 수 있는 메서드를 제공합니다. 이러한 이벤트에는 구성 요소가 다음과 같은 경우에 포함됩니다.

  • 생성됨
  • DOM에 추가됨
  • 브라우저에서 렌더링됨
  • 오류가 발생됨
  • DOM에서 삭제됨

callback 메서드를 사용하여 이러한 수명 주기 이벤트에 응답할 수 있습니다. 예를 들어 connectedCallback()은 구성 요소를 DOM에 삽입할 때 호출합니다. disconnectedCallback()은 구성 요소를 DOM에서 제거할 때 호출합니다.

조건부 렌더링을 테스트하는 데 사용한 JavaScript 파일에서는 구성 요소를 DOM에 삽입할 때 connectedCallback() 메서드를 사용해 코드를 자동으로 실행했습니다. 코드는 3초가 흐른 뒤 readytrue 설정합니다.

import { LightningElement } from 'lwc';
export default class App extends LightningElement {
  ready = false;
  connectedCallback() {
    setTimeout(() => {
      this.ready = true;
    }, 3000);
  }
}
참고

VS Code와 같은 편집기에서 이 예제를 사용하면 setTimeout() 함수에 대해 "제한된 비동기 작업...." 경고가 표시될 수 있습니다. 이 경고는 잘못된 비동기 작업을 사용하고 있음을 나타내며, 이벤트를 기다리는 것이 아니라 해당 시간만큼 동작을 지연시킵니다. setTimeout()은 임의의 지연 시간 지연을 보여주는 데 적합합니다. 하지만 해당 경고가 여러분이 사용하지 못하도록 막는 것은 아닙니다.

또한 this 키워드를 사용한 것을 주목하세요. 키워드 사용법은 JavaScript를 작성해 본 사람이라면 익숙할 것이며, 다른 환경에서도 똑같이 작동합니다. JavaScript에서 this 키워드는 현재 컨텍스트의 최상위 레벨을 나타냅니다. 여기서 컨텍스트는 이 클래스입니다. connectedCallback() 메서드는 최상위 ready 변수의 값을 할당합니다. 이는 Lightning 웹 구성 요소를 통해 JavaScript 기능을 개발에 도입하는 방법을 보여주는 좋은 예시입니다. 리소스 섹션에서 this에 대한 유용한 정보가 있는 링크를 확인할 수 있습니다.

데코레이터

데코레이터는 JavaScript에서 속성이나 함수의 동작을 수정하는 데 자주 사용됩니다.

lwc 모듈에서 가져와 속성이나 함수 앞에 배치하여 사용할 수 있습니다.

import { LightningElement, api } from 'lwc';
export default class MyComponent extends LightningElement{
  @api message;
}

여러 데코레이터를 가져올 수도 있지만 단일 속성이나 함수에는 데코레이터가 하나만 존재합니다. 예를 들어, 한 속성은 @api@wire 데코레이터를 모두 가질 수 없습니다.

Lightning 웹 구성 요소 데코레이터의 예는 다음과 같습니다.

  • @api: 필드를 공개로 표시합니다. 공용 속성은 구성 요소의 API를 정의합니다. HTML 마크업에서 구성 요소를 사용하는 소유자 구성 요소는 구성 요소의 공개 속성에 액세스할 수 있습니다. 모든 공개 속성은 반응형이므로 프레임워크가 속성의 변경 사항을 관찰합니다. 속성 값이 변경되면 프레임워크가 반응하여 구성 요소를 다시 렌더링합니다.
참고

필드와 속성은 거의 같은 의미로 쓰이는 용어입니다. 구성 요소 작성자는 JavaScript 클래스에서 필드를 선언합니다. 클래스의 인스턴스에는 속성이 있습니다. 구성 요소 소비자에게 필드는 속성입니다. Lightning 웹 구성 요소에서는 구성 요소 작성자가 @api로 데코레이트한 필드만 소비자에게 공개되어 객체 속성으로 사용할 수 있습니다.

  • @track: 프레임워크에 객체의 속성이나 배열의 요소에 대한 변경 사항을 관찰하도록 지시합니다. 변경 사항이 발생하면 프레임워크가 구성 요소를 다시 렌더링합니다. 모든 필드는 반응형입니다. 필드 값이 변경되고 해당 필드가 템플릿에서 사용되거나 템플릿에 사용된 속성의 getter에 사용된 경우 프레임워크는 구성 요소를 다시 렌더링합니다. @track으로 필드를 데코레이트하지 않아도 됩니다. 필드에 객체 또는 배열이 포함되어 있고 프레임워크에서 객체의 속성이나 배열의 요소에 대한 변경 사항을 관찰하려는 경우에만 @track을 사용하세요. 전체 속성의 값을 변경하려는 경우에는 @track을 사용할 필요가 없습니다.
참고

2020년도 봄 이전까지는 @track을 사용하여 필드(개인 속성이라고도 함)를 반응형으로 표시해야 했습니다. 이제 더 이상 그렇게 하지 않아도 됩니다. 객체의 속성이나 배열의 요소에 대한 변경 사항을 관찰하도록 프레임워크에 지시할 때만 @track을 사용하세요. 필요하지 않은 곳에 @track이 사용된 레거시 예제도 있습니다. 하지만 데코레이터를 사용해도 기능이 변경되거나 코드가 손상되지 않으므로 괜찮습니다.

  • @wire: Salesforce org에서 데이터를 쉽게 가져오고 바인딩할 수 있는 방법을 제공합니다.

다음은 @api 데코레이터를 사용하여 한 구성 요소(bike)의 값을 다른 구성 요소(app)에 렌더링하는 예제입니다. 파일 구조는 다음과 같습니다.

샘플 앱 파일 구조

앱 구성 요소는 다음 HTML을 사용합니다.

<!-- app.html -->
<template>
  <div>
    <c-bike bike={bike}></c-bike>
  </div>
</template>

앱 구성 요소는 다음 JavaScript를 사용합니다.

// app.js
import { LightningElement } from 'lwc';
export default class App extends LightningElement {
  bike = {
    name: 'Electra X4',
    picture: 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg'
  };
}

bike 구성 요소는 다음 HTML을 사용합니다.

<!-- bike.html -->
<template>
  <img src={bike.picture} alt="bike picture" />
  <p>{bike.name}</p>
</template>

bike 구성 요소는 다음 JavaScript를 사용합니다.

// bike.js
import { LightningElement, api } from 'lwc';
export default class Bike extends LightningElement {
  @api bike;
}

여러분은 이제 VS Code에서 일부 코드를 작업할 수 있게 되었습니다. 다음 유닛에서는 코드 몇 가지를 배포하고 구성 요소가 있는 환경에 대해 자세히 알아보겠습니다.

리소스

Salesforce 도움말에서 Trailhead 피드백을 공유하세요.

Trailhead에 관한 여러분의 의견에 귀 기울이겠습니다. 이제 Salesforce 도움말 사이트에서 언제든지 새로운 피드백 양식을 작성할 수 있습니다.

자세히 알아보기 의견 공유하기