Elm과 JavaScript의 원활한 통합: Create Elm App에서 Ports 사용 방법

Elm과 JavaScript의 원활한 통합: Create Elm App에서 Ports 사용 방법

Create Elm App는 설정 없이도 Elm 앱을 만들 수 있는 도구로, 이는 단순히 프로젝트 시작을 용이하게 하는 데서 그치지 않고 Elm과 JavaScript 간의 원활한 통합 기능도 제공합니다. 본 문서에서는 Create Elm App 프로젝트에서 Ports 기능을 활용하여 Elm과 JavaScript 간의 데이터 전송 및 함수 호출 방법을 상세히 설명합니다. 이를 통해 개발자들은 Elm과 JavaScript의 강점을 조합하여 강력한 웹 앱을 구축할 수 있습니다.

Ports란 무엇인가?

Elm에서 Ports는 Elm 코드와 JavaScript 코드 사이에서 데이터를 전송하고 함수를 호출할 수 있는 특수한 메커니즘입니다. Ports를 통해 Elm과 JavaScript 간에 데이터를 주고받을 수 있고, 상호간의 함수를 호출할 수 있습니다. 이는 JavaScript 생태계의 라이브러리나 브라우저 API와 상호작용할 때 특히 유용합니다.

Create Elm App에서 Ports 사용 방법

Create Elm App에서 Ports를 사용하려면 먼저 Elm 모듈에서 Port를 정의해야 합니다. Elm 파일의 머리 부분에서 일반 module 키워드 대신 port module 키워드를 사용하고 Port 함수를 정의합니다. 예를 들어 src/Main.elm 파일에서 다음처럼 Port를 정의할 수 있습니다:

port module Main exposing (..)

port logMessage : String -> Cmd msg

이 Port 함수 logMessage는 문자열 매개변수를 받고 Cmd msg 유형의 값을 반환합니다. Elm에서 이 함수를 호출하면 JavaScript로 메시지를 전송합니다.

Elm에서 Ports를 통해 데이터 전송

Port를 정의한 후에는 Elm의 update 함수에서 이 Port를 사용하여 데이터를 JavaScript로 보내는 것이 가능합니다. 예를 들어 카운터 증가/감소 작업을 처리할 때 다음과 같이 Port를 사용할 수 있습니다:

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        Increment ->
            ( { model | count = model.count + 1 }
            , logMessage ("Count increased to " ++ String.fromInt (model.count + 1))
            )
        Decrement ->
            ( { model | count = model.count - 1 }
            , logMessage ("Count decreased to " ++ String.fromInt (model.count - 1))
            )
        NoOp ->
            ( model, Cmd.none )

위 코드에서 사용자가 '+' 또는 '-' 버튼을 클릭하면 Elm은 카운터 값을 업데이트하고 logMessage Port를 통해 JavaScript로 최신 카운터 값을 전송합니다.

JavaScript에서 Ports监听 및 데이터 수신

Elm에서 Port를 정의하고 사용한 후에는 JavaScript에서 해당 Port를监听하여 데이터를 수신해야 합니다. 일반적으로 src/index.js 파일에서 이 작업을 수행합니다. 예를 들어 logMessage Port를监听하는 방법은 다음과 같습니다:

import { Elm } from './Main.elm';

const app = Elm.Main.init({
  node: document.getElementById('root')
});

app.ports.logMessage.subscribe(function(message) {
  console.log('From Elm:', message);
  // 수신된 데이터를 처리하는 로직을 여기에 추가
});

위 코드에서 app.ports.logMessage.subscribe를 통해 콜백 함수를 등록하면 Elm으로부터 메시지가 전송될 때마다 이 함수가 호출됩니다.

JavaScript에서 Elm로 데이터 전송

Ports는 단방향 통신만을 위한 것이 아니라, JavaScript에서 Elm로도 데이터를 전송할 수 있는 기능을 제공합니다. 이를 위해 Elm에서 데이터 수신을 위한 Port를 정의하고 JavaScript에서 해당 Port의 send 메서드를 호출하면 됩니다.

먼저 Elm에서 다음처럼 Port를 정의합니다:

port module Main exposing (..)

port receiveMsg : (String -> msg) -> Sub msg

이 Port 함수 receiveMsg는 데이터 수신을 위한 함수를 인자로 받습니다. 그런 다음 Elm의 subscriptions 함수에서 이 Port를 구독합니다:

subscriptions : Model -> Sub Msg
subscriptions model =
    receiveMsg HandleMessage

여기서 HandleMessage는 수신된 메시지를 처리하는 Msg 유형의 함수입니다:

type Msg
    = Increment
    | Decrement
    | NoOp
    | HandleMessage String

그런 다음 JavaScript에서 다음과 같이 데이터를 보내는 것이 가능합니다:

app.ports.receiveMsg.send('Hello from JavaScript!');

JavaScript가 send 메서드를 호출하면 Elm은 HandleMessage 메시지를 통해 데이터를 처리합니다.

전체 예제: Elm과 JavaScript의 양방향 통신

아래는 Elm과 JavaScript 사이에서 Ports를 통해 양방향 통신을 수행하는 완전한 예제를 제공합니다:

Elm 코드 (src/Main.elm):

port module Main exposing (..)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)

type alias Model =
    { count : Int
    , message : String
    }

type Msg
    = Increment
    | Decrement
    | HandleMessage String

init : Model
init =
    { count = 0
    , message = ""
    }

port logMessage : String -> Cmd msg
port receiveMsg : (String -> msg) -> Sub msg

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        Increment ->
            ( { model | count = model.count + 1 }
            , logMessage ("Count increased to " ++ String.fromInt (model.count + 1))
            )
        Decrement ->
            ( { model | count = model.count - 1 }
            , logMessage ("Count decreased to " ++ String.fromInt (model.count - 1))
            )
        HandleMessage str ->
            ( { model | message = str }, Cmd.none )

view : Model -> Html Msg
view model =
    div []
        [ button [ onClick Increment ] [ text "+" ]
        , div [] [ text (String.fromInt model.count) ]
        , button [ onClick Decrement ] [ text "-" ]
        , div [] [ text ("Message from JS: " ++ model.message) ]
        ]

subscriptions : Model -> Sub Msg
subscriptions model =
    receiveMsg HandleMessage

main : Program () Model Msg
main =
    Browser.element
        { init = \_ -> (init, Cmd.none)
        , update = update
        , view = view
        , subscriptions = subscriptions
        }

JavaScript 코드 (src/index.js):

import { Elm } from './Main.elm';

const app = Elm.Main.init({
  node: document.getElementById('root')
});

// Elm에서 보내온 메시지를 수신하는 함수
app.ports.logMessage.subscribe(function(message) {
  console.log('From Elm:', message);
  
  // JavaScript에서 Elm로 응답 메시지 보내기
  app.ports.receiveMsg.send('Received: ' + message);
});

// 주기적으로 Elm에 데이터 보내기
setInterval(function() {
  app.ports.receiveMsg.send('Current time: ' + new Date().toLocaleTimeString());
}, 5000);

이 예제에서 Elm 앱은 사용자가 버튼을 클릭하면 카운터 값을 업데이트하고 JavaScript로 메시지를 보내며, JavaScript는 이 메시지를 수신 후 Elm로 응답 메시지를 보내는 과정을 반복합니다. 또한 JavaScript는 주기적으로 현재 시간을 Elm로 전송합니다.

결론

Ports를 통해 Create Elm App은 Elm과 JavaScript 간의 원활한 통합을 실현시킵니다. 이 기능을 통해 단방향 통신은 물론 양방향 통신까지 모두 가능하며, 개발자들은 Elm과 JavaScript의 강점을 최대한 활용할 수 있습니다. 본 문서를 통해 Ports의 사용 방법을 숙지한 후, 더 복잡한 통신 로직을 구현하는 데에 도전해 보시기 바랍니다.

실제 프로젝트에서는 필요에 따라 여러개의 Ports를 정의하고 다양한 통신 로직을 구현할 수 있습니다. 또한 Ports는 JSON으로 직렬화할 수 있는 데이터 유형만을 전송할 수 있다는 점을 유의하시기 바랍니다.Ports를 활용하여 기능이 풍부하고 상호작용이 훌륭한 웹 앱을 개발하시기 바랍니다.

태그: Elm JavaScript Ports Web Development Functional Programming

5월 26일 17:38에 게시됨