Lightning Message Service 란?
LMS (Lightning Message Service)는 하나의 Lightning page에 있는 DOM들이 서로 소통하기 위한 방법이다.
즉, 하나의 Lightning page에 삽입된 Visualforce page, Aura component, LWC들끼리 커뮤니케이션하기 위한 방법이다.
전체 Application에서의 메세지를 구독하거나 특정 active area의 메세지만을 구독할 수 있다.
Lightning Experience나 Expereince Builder 사이트에서 사용이 가능하다.
LWC는 Hierarchy 구조에 있는 컴포넌트들 끼리는 Event up Property Down이라는 원칙에 따라 부모-자식 요소간 소통이 가능하지만 동떨어져 있는 요소들의 DOM branch들끼리 소통을 하기 위해서는 이 LMS를 사용한다.
Message Channel 생성하기
LightningMessageChannel이라는 metadata type을 이용하여 sf org에 채널을 생성할 수 있다.
기본 경로는 force-app/main/default/messageChannels/ 가 되어야 하며 파일 이름 형식은 messageChannelName.messageChannel-meta.xml와 같이 생성된다.
생성 방법은 아래와 같다.
첫번째로 vscode의 project 폴더에서, default 폴더 하위에 messageChannels라는 이름의 폴더를 생성한다.

이후 해당 폴더에 내가 생성하려고 하는 LightningMessageChannel에 대해 xml 파일을 만들어 줘야 한다.
https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_lightningmessagechannel.htm
나는 아래와 같이 작성하였고, 이후 해당 파일에서 우클릭 > deploy to org를 하여 배포하였다.

만약 협업 중, 다른 사람이 작성하고 배포한 Message Channel을 내려받기 위해서는 package.xml에 다음과 같이 작성하여 내려받는다.
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<name>LightningMessageChannel</name>
</types>
<version>47.0</version>
</Package>
Message Channel 사용해보기
LMS를 테스트해보기 위하여 부모-자식의 관계가 아닌, 독립된 두개의 LWC를 생성하였다.
- messageChannelTestInput
- messageChannelTestOutput
아래 사진에서 왼쪽의 input 필드에 값을 입력 시 해당 입력값을 message channel로 전달받아 오른쪽 컴포넌트에서 출력하는 작업을 진행하려 한다.

생성된 Message Channel을 import를 시켜야 하는데 구문은 다음과 같다.
// Basic syntax
import channelName from "@salesforce/messageChannel/channelReference";
// Syntax for resources in a managed package
import channelName from "@salesforce/messageChannel/namespace__channelReference";
해당 구문에 맞춰서 우리에 맞게 바꿔보면, 아래와 같이 될 것이라고 생각한다. 주의할 점은 MessageChannel을 만들 때 사용했던 <MasterLabel> 값이 아니라 그냥 그 xml 파일의 이름 자체를 사용해야 한다는 것이다.
import TestMessageChannel from '@salesforce/messageChannel/MyFirstMessageChannel__c'
메세지 채널은 커스텀 오브젝트는 아니지만 __c prefix가 붙는다.
또한 메세지 채널을 사용하기 위해서, Message Service의 Scope 설정을 해주어야 한다.
여기서 말하는 Scope란 채널의 구독자(Subscribing component)가 메세지를 어디에서 받을지에 대한 범위를 말한다.
우리에겐 두 옵션이 존재한다.
- application의 active area에서만 나오는 메세지를 받을지
- 전체 application에서 나오는 메세지를 받을지
두 가지의 차이는, 문서 상 숨겨진 (Hidden) tab들에서 나오는 메세지를 받을지 말지의 여부로 보인다. 그러나 정확한 차이는 실제 테스트를 해봐야 한다.
Application 전체를 scope로 정할 때는 APPLICATION_SCOPE를 lightning/messageService에서 import 해와야 한다. 그리고 subscribe()를 호출 할 때 파라미터로 넘겨주게 된다.
Active area를 scope로 정할 땐 별다른 액션을 취할 필요는 없다. default behavior로 동작하기 때문이다.
Message를 publish 해보기
html 파일에서 input 태그에 onchange event handler를 걸어주었다.
<template>
텍스트값을 입력하세요:
<lightning-input type="text" onchange={handleChangeInput}></lightning-input>
</template>
js파일은 아래와 같이 작성하였다. 기본적으로 특정 message channel를 import 한 후에, publish() 함수를 호출하는 방식이다. MessageContextObject를 생성하기 위해 @wire(MessageContext)를 사용한 것도 눈여겨 보자. 이것은 Lightning message service를 사용하는 Lightning web component에 대한 정보를 담고 있는 객체이다. wire adapter를 사용할 땐 해당 component의 lifecycle event들과 별도로 연동시킬 필요는 없다. Lightning message service의 기능들은 컴포넌트가 destroyed 될때 자동으로 unregister 된다.
import { LightningElement, wire } from 'lwc';
import TestMessageChannel from '@salesforce/messageChannel/MyFirstMessageChannel__c';
import { publish, MessageContext } from 'lightning/messageService';
export default class MessageChannelTestInput extends LightningElement {
@wire(MessageContext)
messageContext;
handleChangeInput(e) {
const payload = { inputData: e.target.value };
publish(this.messageContext, TestMessageChannel, payload);
}
}
publish() 메서드는 3개의 파라미터를 가지는데 그 중 마지막 message payload 같은 경우에는 JSON object로써 우리가 Message Channel를 만들 때 정의한 lightningMessageFields의 내용들을 key로써 사용한다.
You can’t use @wire(MessageContext) in a constructor() function.
Message Subscribe 하기
<template>
<b>사용자가 입력한 값은?</b>: {inputValue}
</template>
import { LightningElement, wire } from 'lwc';
import TestMessageChannel from '@salesforce/messageChannel/MyFirstMessageChannel__c';
import {
subscribe,
unsubscribe,
APPLICATION_SCOPE,
MessageContext,
} from "lightning/messageService";
export default class MessageChannelTestOutput extends LightningElement {
inputValue;
subscription = null;
@wire(MessageContext)
messageContext;
subscribeToTestMessageChannel() {
if (!this.subscription) {
this.subscription = subscribe(
this.messageContext,
TestMessageChannel,
(message) => this.inputValue = message.inputData,
{ scope: APPLICATION_SCOPE },
);
}
}
unsubscribeToTestMessageChannel() {
unsubscribe(this.subscription);
this.subscription = null;
}
connectedCallback() {
this.subscribeToTestMessageChannel();
this.inputValue = '아직 아무런 값이 입력되지 않음!';
}
disconnectedCallback() {
this.unsubscribeToTestMessageChannel();
}
}
subscribe()와 unsubscribe()를 활용해 메세지 채널을 구독/구독해제 할 수 있다.APPLICATION_SCOPE를 사용하는것은 optional로써 전체 application이 아닌 active area에서만 구독을 하고자 한다면 사용할 필요가 없다.
'Salesforce > Salesforce Dev' 카테고리의 다른 글
| SFDC Query 튜닝 - Selective Query (1) | 2024.06.11 |
|---|---|
| SFDC Query 튜닝 - Skinny Table (1) | 2024.06.11 |
| Salesforce Deployment Error - Invalid api version:61.0 (0) | 2024.06.04 |
| Apex Unit Test에 대한 개인적인 생각 (1) | 2024.06.03 |
| Testing Apex 시리즈 시작 (0) | 2024.06.03 |