iBetter Books
수정

ipywidgets에서 mo.ui로 매핑

PART 01 Ch 04에서 ipywidgetsinteract 함수가 marimo에서 동작하지 않는다고 짚었습니다. PART 03 Ch 01에서는 mo.ui의 기본 위젯을 다뤘습니다. 이 챕터는 그 두 내용을 연결합니다. Jupyter에서 ipywidgets로 작성한 코드를 marimo 방식으로 옮기는 구체적인 방법을 패턴별로 살펴봅니다.

기본 위젯 매핑

ipywidgets의 각 위젯에 대응하는 mo.ui 위젯이 있습니다. 아래 표는 자주 쓰이는 위젯과 대응 관계를 정리한 것입니다.

ipywidgets mo.ui 대응
widgets.IntSlider() mo.ui.slider()
widgets.FloatSlider() mo.ui.slider(step=0.1)
widgets.Dropdown() mo.ui.dropdown()
widgets.RadioButtons() mo.ui.radio()
widgets.SelectMultiple() mo.ui.multiselect()
widgets.Text() mo.ui.text()
widgets.Textarea() mo.ui.text_area()
widgets.IntText() mo.ui.number()
widgets.Checkbox() mo.ui.checkbox()
widgets.Button() mo.ui.button()

모든 mo.ui 위젯은 .value 속성으로 현재 값을 읽습니다.

IntSlider 대체

# ipywidgets 방식import ipywidgets as widgetsslider = widgets.IntSlider(value=5, min=0, max=10, description="임계값")display(slider)print(slider.value)
# marimo 방식import marimo as mo# Cell 1 — 위젯 정의slider = mo.ui.slider(0, 10, value=5, label="임계값")slider# Cell 2 — slider.value 참조, slider가 바뀌면 자동 재실행mo.md(f"현재 임계값: **{slider.value}**")

ipywidgetsdescription이라는 인자를 쓰고, mo.ui.sliderlabel을 씁니다. minmax는 위치 인자로 바꿉니다. display(slider) 대신 셀 마지막 표현식으로 위젯 변수를 놓습니다.

# ipywidgets 방식import ipywidgets as widgetsdropdown = widgets.Dropdown(    options=["사과", "바나나", "포도"],    value="사과",    description="과일 선택")display(dropdown)print(dropdown.value)
# marimo 방식import marimo as mo# Cell 1 — 위젯 정의dropdown = mo.ui.dropdown(["사과", "바나나", "포도"], value="사과", label="과일 선택")dropdown# Cell 2 — 반응형 사용mo.md(f"선택한 과일: **{dropdown.value}**")

Text 대체

# ipywidgets 방식import ipywidgets as widgetstext = widgets.Text(value="", description="이름 입력", placeholder="홍길동")display(text)print(text.value)
# marimo 방식import marimo as mo# Cell 1 — 위젯 정의text = mo.ui.text(value="", label="이름 입력", placeholder="홍길동")text# Cell 2mo.md(f"안녕하세요, **{text.value}**님.")

interact 패턴 대체

ipywidgets에서 가장 많이 쓰이는 패턴이 interact입니다. 함수와 파라미터 범위를 넘겨주면 자동으로 슬라이더와 연결해줍니다.

# ipywidgets 방식import ipywidgets as widgetsfrom ipywidgets import interactimport numpy as npimport matplotlib.pyplot as pltdef plot_sine(frequency=1.0, amplitude=1.0):    x = np.linspace(0, 2 * np.pi, 300)    y = amplitude * np.sin(frequency * x)    plt.figure(figsize=(8, 4))    plt.plot(x, y)    plt.ylim(-3, 3)    plt.title(f"주파수: {frequency}, 진폭: {amplitude}")    plt.show()interact(plot_sine, frequency=(0.5, 5.0, 0.5), amplitude=(0.5, 3.0, 0.5))

marimo에서는 interact를 쓸 수 없습니다. 위젯을 전역 변수로 정의하고, 별도 셀에서 .value를 참조하는 방식으로 재작성합니다.

# marimo 방식import marimo as moimport numpy as npimport matplotlib.pyplot as plt# Cell 1 — 위젯 정의frequency = mo.ui.slider(0.5, 5.0, step=0.5, value=1.0, label="주파수")amplitude = mo.ui.slider(0.5, 3.0, step=0.5, value=1.0, label="진폭")mo.vstack([frequency, amplitude])# Cell 2 — 위젯 값을 참조해 그래프 생성x = np.linspace(0, 2 * np.pi, 300)y = amplitude.value * np.sin(frequency.value * x)fig, ax = plt.subplots(figsize=(8, 4))ax.plot(x, y)ax.set_ylim(-3, 3)ax.set_title(f"주파수: {frequency.value}, 진폭: {amplitude.value}")fig

interact가 내부에서 자동으로 처리하던 위젯 생성과 재실행 연결을 marimo에서는 두 셀로 명시적으로 나눕니다. 슬라이더를 움직이면 Cell 2가 자동으로 재실행됩니다.

observe 콜백 대체

ipywidgets에서는 위젯 값이 바뀔 때 특정 함수를 호출하는 observe 패턴을 씁니다.

# ipywidgets 방식import ipywidgets as widgetsslider = widgets.IntSlider(value=0, min=0, max=10)output = widgets.Output()def on_change(change):    with output:        output.clear_output()        print(f"새 값: {change['new']}")slider.observe(on_change, names="value")display(slider, output)

marimo에서는 위젯 값이 바뀌면 의존 셀이 자동으로 재실행됩니다. 별도의 콜백을 등록할 필요가 없습니다.

# marimo 방식import marimo as mo# Cell 1 — 위젯 정의slider = mo.ui.slider(0, 10, value=0, label="값")slider# Cell 2 — slider.value가 바뀌면 자동 재실행mo.md(f"새 값: **{slider.value}**")

observe 콜백의 역할을 marimo의 반응형 실행이 대신합니다. "값이 바뀔 때 무엇을 한다"는 로직을 콜백 함수로 분리하지 않고, 의존 셀의 코드로 직접 씁니다.

여러 위젯 간 공유 상태가 필요하거나, 한 위젯이 다른 위젯의 값을 바꾸는 패턴이 필요하다면 mo.state를 사용합니다.

# mo.state로 카운터 만들기import marimo as mo# Cell 1 — 상태 정의get_count, set_count = mo.state(0)# Cell 2 — 버튼으로 상태 변경increment = mo.ui.button(    label="증가",    on_change=lambda _: set_count(lambda v: v + 1),)decrement = mo.ui.button(    label="감소",    on_change=lambda _: set_count(lambda v: v - 1),)mo.hstack([increment, decrement])# Cell 3 — 현재 상태 표시 (get_count()가 바뀌면 자동 재실행)mo.md(f"카운터: **{get_count()}**")

위젯 매핑 전환 요령

ipywidgetsmo.ui로 전환할 때 자주 막히는 지점을 정리합니다.

display() 제거. display(widget)은 marimo에서 필요 없습니다. 셀 마지막 표현식으로 위젯 변수를 놓으면 됩니다.

여러 위젯 한 셀에 표시. mo.vstack 또는 mo.hstack으로 묶어서 셀 마지막 표현식으로 넘깁니다.

# mo.vstack으로 여러 위젯을 한 셀에 표시import marimo as mofreq = mo.ui.slider(1, 10, value=3, label="주파수")amp = mo.ui.slider(1, 5, value=2, label="진폭")mo.vstack([freq, amp])

description 대신 label. ipywidgetsdescription 인자가 mo.ui에서는 label입니다.

전역 변수 할당 필수. interact(fn, x=(0,10))처럼 함수에 직접 넘기는 방식은 없습니다. 위젯을 전역 변수에 할당해야 다른 셀에서 .value를 참조할 수 있습니다.

정리

  • ipywidgets의 기본 위젯(IntSlider, Dropdown, Text, Checkbox, Button 등)은 mo.ui에 대응하는 위젯이 있습니다.
  • interact 패턴은 위젯 전역 변수 정의 셀과 .value 참조 셀로 분리해서 재작성합니다.
  • observe 콜백은 marimo의 반응형 재실행으로 대체됩니다. 공유 상태가 필요하면 mo.state를 씁니다.
  • display() 호출을 제거하고, 셀 마지막 표현식으로 위젯을 렌더링합니다.
  • 여러 위젯을 한 셀에 표시하려면 mo.vstack 또는 mo.hstack으로 묶습니다.