HTML 같이 레이아웃을 자유롭게 변경할 수 있는 새로운 메시지 유형, ‘Flex Message’를 소개합니다

Flex Message라는 새로운 메시지 유형이 LINE Messaging API에 추가되었습니다. 기존 Messaging API에서도 단순 텍스트 외에 스티커나 이미지, 비디오 같은 미디어 유형, 혹은 다양한 버튼과 URL을 배치할 수 있는 템플릿 유형의 메시지를 사용할 수 있었습니다. 그 중에서도 템플릿은 사용자가 여러 가지 선택지 중에서 답을 골라야 하는 상황에 특히 유용했습니다. 다만, 버튼 템플릿 같은 경우 버튼을 최대 네 개까지만 배치할 수 있다든가, 레이아웃을 제목, 본문, 버튼 순으로만 설정할 수 있다는 제약이 있었습니다.

Flex Message 란?

Flex Message는 바로 이런 제약에서 벗어나 레이아웃을 굉장히 자유롭게 바꿀 수 있는 메시지 유형으로, 변경 가능한 가짓수가 무한대에 가깝습니다. 일정한 디스플레이 프레임이 있으면서도 레이아웃을 HTML처럼 원하는 대로 변경할 수 있고, 각각의 구성 요소도 보기 좋게 정돈되어 나타납니다. 예를 들어, 아래와 같은 메시지를 작성할 수 있습니다.

Flex Message 구현 사례

그럼 실제로 Flex Message를 사용한 두 가지 챗봇 사례를 살펴보겠습니다.

사례 1. The QUIZ

먼저, ‘친구에게 퀴즈 내기’ 기능을 제공하는 챗봇입니다. 다음 QR 코드를 스캔하여 챗봇을 친구 추가하면 테스트 해볼 수 있습니다.

챗봇을 친구 추가하면 퀴즈에 도전할 것인지(Challenge), 직접 퀴즈를 낼 것인지(Create) 선택하게 됩니다. Challenge를 선택하면 문항이 두 개인 퀴즈가 주어지는데, 보기 번호가 적힌 녹색 버튼을 눌러 답을 제출하는 방식입니다.

위 동영상처럼 버튼을 가로로 배치할 수 있습니다. 버튼의 위치도 footer 부분에서 벗어나 메시지 중간이나 header 부분으로 변경할 수 있습니다. 다음은 동영상 속 메시지의 메시지 객체입니다.

{
  "type": "flex",
  "altText": "Q1. Which is the API to create chatbot?",
  "contents": {
    "type": "bubble",
    "body": {
      "type": "box",
      "layout": "vertical",
      "spacing": "md",
      "contents": [
        {
          "type": "box",
          "layout": "vertical",
          "contents": [
            {
              "type": "text",
              "text": "Q1",
              "align": "center",
              "size": "xxl",
              "weight": "bold"
            },
            {
              "type": "text",
              "text": "Which is the API to create chatbot?",
              "wrap": true,
              "weight": "bold",
              "margin": "lg"
            }
          ]
        },
        {
          "type": "separator"
        },
        {
          "type": "box",
          "layout": "vertical",
          "margin": "lg",
          "contents": [
            {
              "type": "box",
              "layout": "baseline",
              "contents": [
                {
                  "type": "text",
                  "text": "1.",
                  "flex": 1,
                  "size": "lg",
                  "weight": "bold",
                  "color": "#666666"
                },
                {
                  "type": "text",
                  "text": "Login API",
                  "wrap": true,
                  "flex": 9
                }
              ]
            },
            {
              "type": "box",
              "layout": "baseline",
              "contents": [
                {
                  "type": "text",
                  "text": "2.",
                  "flex": 1,
                  "size": "lg",
                  "weight": "bold",
                  "color": "#666666"
                },
                {
                  "type": "text",
                  "text": "Messaging API",
                  "wrap": true,
                  "flex": 9
                }
              ]
            },
            {
              "type": "box",
              "layout": "baseline",
              "contents": [
                {
                  "type": "text",
                  "text": "3.",
                  "flex": 1,
                  "size": "lg",
                  "weight": "bold",
                  "color": "#666666"
                },
                {
                  "type": "text",
                  "text": "Graph API",
                  "wrap": true,
                  "flex": 9
                }
              ]
            },
            {
              "type": "box",
              "layout": "baseline",
              "contents": [
                {
                  "type": "text",
                  "text": "4.",
                  "flex": 1,
                  "size": "lg",
                  "weight": "bold",
                  "color": "#666666"
                },
                {
                  "type": "text",
                  "text": "Cartoon API",
                  "wrap": true,
                  "flex": 9
                }
              ]
            }
          ]
        }
      ]
    },
    "footer": {
      "type": "box",
      "layout": "horizontal",
      "spacing": "sm",
      "contents": [
        {
          "type": "button",
          "style": "primary",
          "height": "sm",
          "action": {
            "type": "message",
            "label": "1",
            "text": "Login API"
          }
        },
        {
          "type": "button",
          "style": "primary",
          "height": "sm",
          "action": {
            "type": "message",
            "label": "2",
            "text": "Messaging API"
          }
        },
        {
          "type": "button",
          "style": "primary",
          "height": "sm",
          "action": {
            "type": "message",
            "label": "3",
            "text": "Graph API"
          }
        },
        {
          "type": "button",
          "style": "primary",
          "height": "sm",
          "action": {
            "type": "message",
            "label": "4",
            "text": "Cartoon API"
          }
        }
      ]
    }
  }
}

사례 2. 메구로 도서관

두 번째 챗봇을 이용하면 도쿄 메구로구 도서관에 소장된 책을 검색할 수 있고, 해당 도서관의 회원일 경우 대출증 번호와 비밀번호를 등록한 뒤 실제로 책을 예약할 수도 있습니다.

예약이 완료되면 ‘예약표’라는 메시지가 채팅창에 나타납니다. 예약표를 보면 현재 예약 중인 책을 확인할 수 있고, 각 책 제목의 오른쪽에 위치한 빨간 X 버튼을 눌러 예약을 취소할 수도 있습니다. 예약표의 메시지 객체는 다음과 같습니다.

{
  "type": "flex",
  "altText": "予約票",
  "contents": {
    "type": "bubble",
    "body": {
      "type": "box",
      "layout": "vertical",
      "spacing": "xl",
      "contents": [
        {
          "type": "text",
          "text": "予約票",
          "align": "center",
          "size": "xl",
          "color": "#1DB446"
        },
        {
          "type": "separator"
        },
        {
          "type": "box",
          "layout": "horizontal",
          "contents": [
            {
              "type": "box",
              "layout": "vertical",
              "flex": 8,
              "spacing": "sm",
              "contents": [
                {
                  "type": "text",
                  "text": "10年後の仕事図鑑",
                  "weight": "bold"
                },
                {
                  "type": "text",
                  "text": "順番:191/233",
                  "size": "xs",
                  "color": "#aaaaaa"
                }
              ]
            },
            {
              "type": "button",
              "style": "primary",
              "color": "#ff0000",
              "flex": 2,
              "height": "sm",
              "action": {
                "type": "postback",
                "label": "X",
                "displayText": "10年後の仕事図鑑をキャンセル",
                "data": "{\"_type\":\"intent\",\"intent\":{\"name\":\"cancel-reservation\",\"parameters\":{\"reservation_number\":\"1 \"}}}"
              }
            }
          ]
        }
      ]
    }
  }
}

이처럼 Flex Message는 box라 불리는 구성 요소를 가로 혹은 세로로 나열한 뒤, 이를 다시 중첩하면서 자유롭게 레이아웃을 구성할 수 있습니다. 또한 버튼에는 기존 action 객체를 그대로 적용할 수 있어서, 텍스트나 포스트백, URI와 같은 액션을 현재와 동일한 방식으로 실행하는 게 가능합니다.

Flex Message 구현 방법

Flex Message를 보내려면 새로 추가된 flex 유형의 메시지 객체를 지정해야 합니다. 종류는 크게 두 가지로, 말풍선이 하나만 표시되는 유형과 말풍선이 여러 개 표시되어 이를 가로 방향으로 스크롤할 수 있는 유형(템플릿 메시지의 캐러셀(carousel)처럼)이 있습니다.

메시지 객체 형식에 관한 자세한 내용은 공식 문서를 참고하시기 바랍니다.

좀 더 쉽게 구현하는 방법

위에서 보신 것처럼 Flex Message는 높은 확장성을 갖고 있습니다. 메시지 객체는 이런 확장성을 지원하기 위해 일정량의 정보를 다층적으로 보유하게 되는데요. 이때 디스플레이 상태를 조정하고 객체를 형식에 맞게 생성하려면 메시지 출력 결과를 바로바로 확인할 수 있는 툴이 있어야 합니다. 바로 그런 작업이 가능한 Flex Message Simulator 툴이 함께 릴리스되어 있습니다. 몇 가지 샘플이 제공되는 Flex Message Simulator 툴을 사용하면, 메시지 객체를 생성하기 위해 JSON 객체를 편집할 때 메시지가 어떻게 표시되는지 바로바로 확인하면서 작업할 수 있습니다.

맺으며

자유롭게 레이아웃을 바꿀수 있는 Flex Message와 그런 Flex Message를 손쉽게 구현할 수 있도록 도와주는 Flex Message Simulator 툴을 이용해 더욱 창의적인 메시지를 만들어 보시길 바랍니다.

Related Post