MCP HubMCP Hub
스킬 목록으로 돌아가기

build-shiny-module

pjt222
업데이트됨 Yesterday
2 조회
17
2
17
GitHub에서 보기
메타reactaitestingdesign

정보

이 스킬은 개발자가 NS()를 사용하여 적절한 네임스페이스 격리를 갖춘 재사용 가능한 Shiny 모듈을 생성하도록 돕습니다. UI/서버 쌍 구축, 반응형 값 처리, 모듈 간 통신 및 중첩 구현 방법을 다룹니다. 성장하는 애플리케이션에서 재사용 가능한 컴포넌트를 추출하거나 복잡한 로직을 깔끔한 인터페이스 뒤로 캡슐화할 때 활용하세요.

빠른 설치

Claude Code

추천
기본
npx skills add pjt222/agent-almanac -a claude-code
플러그인 명령대체
/plugin add https://github.com/pjt222/agent-almanac
Git 클론대체
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/build-shiny-module

Claude Code에서 이 명령을 복사하여 붙여넣어 스킬을 설치하세요

문서

Build Shiny Module

創具正命名空間隔離、反應式溝通、可組合之可復用 Shiny UI/server 模組對。

適用時機

  • 自漸長之 Shiny 應用抽可復用組件
  • 建多處可用之 UI 小部件
  • 以潔介面封繁之反應邏輯
  • 自更小可測之單位組大應用

輸入

  • 必要:模組之旨與功能描
  • 必要:輸入/輸出之合同(模組受何返何)
  • 選擇性:模組是否嵌他模組(預設:否)
  • 選擇性:框架脈絡(golem、rhino、或 vanilla)

步驟

步驟一:定模組介面

書代碼前,定模組所受所返:

Module: data_filter
Inputs: reactive dataset, column names to filter on
Outputs: reactive filtered dataset
UI: filter controls (selectInput, sliderInput, dateRangeInput)

預期: 明之合同,指定反應輸入、反應輸出、UI 元素。

失敗時: 若介面不明,模組恐過廣。分為單責之小模組。

步驟二:創模組 UI 函

#' Data Filter Module UI
#'
#' @param id Module namespace ID
#' @return A tagList of filter controls
#' @export
dataFilterUI <- function(id) {
  ns <- NS(id)
  tagList(
    selectInput(
      ns("column"),
      "Filter column",
      choices = NULL
    ),
    uiOutput(ns("filter_control")),
    actionButton(ns("apply"), "Apply Filter", class = "btn-primary")
  )
}

要則:

  • 函名循 <name>UI 約定
  • 首參恆為 id
  • 於頂立 ns <- NS(id)
  • inputIdoutputId 皆包於 ns()
  • tagList() 以允彈性置

預期: UI 函創命名空間之輸入/輸出元素。

失敗時: 若用模組二次時 ID 碰撞,查每 ID 皆包於 ns()。常漏:renderUI()uiOutput() 內之 ID——此亦需 ns()

步驟三:創模組伺服器函

#' Data Filter Module Server
#'
#' @param id Module namespace ID
#' @param data Reactive expression returning a data frame
#' @param columns Character vector of filterable column names
#' @return Reactive expression returning the filtered data frame
#' @export
dataFilterServer <- function(id, data, columns) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns

    # Update column choices when data changes
    observeEvent(data(), {
      available <- intersect(columns, names(data()))
      updateSelectInput(session, "column", choices = available)
    })

    # Dynamic filter control based on selected column
    output$filter_control <- renderUI({
      req(input$column)
      col_data <- data()[[input$column]]

      if (is.numeric(col_data)) {
        sliderInput(
          ns("value_range"),
          "Range",
          min = min(col_data, na.rm = TRUE),
          max = max(col_data, na.rm = TRUE),
          value = range(col_data, na.rm = TRUE)
        )
      } else {
        selectInput(
          ns("value_select"),
          "Values",
          choices = unique(col_data),
          multiple = TRUE,
          selected = unique(col_data)
        )
      }
    })

    # Return filtered data as a reactive
    filtered <- eventReactive(input$apply, {
      req(input$column)
      col <- input$column
      df <- data()

      if (is.numeric(df[[col]])) {
        req(input$value_range)
        df[df[[col]] >= input$value_range[1] &
           df[[col]] <= input$value_range[2], ]
      } else {
        req(input$value_select)
        df[df[[col]] %in% input$value_select, ]
      }
    }, ignoreNULL = FALSE)

    return(filtered)
  })
}

要則:

  • 函名循 <name>Server 約定
  • 首參恆為 id
  • 餘參為反應式表達或靜值
  • moduleServer(id, function(input, output, session) { ... })
  • 伺服器內創之動態 UI 用 session$ns
  • 明返反應值

預期: 伺服器函處輸入、返反應輸出。

失敗時: 若反應值不更,查動態 UI 之輸入用 session$ns(非外之 ns)。若模組返 NULL,確 return()moduleServer() 內末表達。

步驟四:於父應用接模組

# In app_ui.R or ui
ui <- page_sidebar(
  title = "Analysis App",
  sidebar = sidebar(
    dataFilterUI("filter1")
  ),
  card(
    DT::dataTableOutput("table")
  )
)

# In app_server.R or server
server <- function(input, output, session) {
  # Raw data source
  raw_data <- reactive({ mtcars })

  # Call module — capture its return value
  filtered_data <- dataFilterServer(
    "filter1",
    data = raw_data,
    columns = c("cyl", "mpg", "hp", "wt")
  )

  # Use the module's returned reactive
  output$table <- DT::renderDataTable({
    filtered_data()
  })
}

預期: 模組於 UI 顯,其所返反應流至下游輸出。

失敗時: 若模組 UI 不渲,驗 UI 與伺服器呼間 id 字串相符。若所返反應為 NULL,查伺服器函實返值。

步驟五:組嵌模組(選)

含他模組之模組:

analysisUI <- function(id) {
  ns <- NS(id)
  tagList(
    dataFilterUI(ns("filter")),
    plotOutput(ns("plot"))
  )
}

analysisServer <- function(id, data) {
  moduleServer(id, function(input, output, session) {
    # Call inner module with namespaced ID
    filtered <- dataFilterServer("filter", data = data, columns = names(data()))

    output$plot <- renderPlot({
      req(filtered())
      plot(filtered())
    })

    return(filtered)
  })
}

要則:UI 中以 ns("inner_id") 嵌。伺服器中僅以 "inner_id" 呼——moduleServer 處命名空間之鏈。

預期: 內模組於外模組之命名空間中正渲。

失敗時: 若內模組 UI 不現,恐忘於外 UI 函中以 ns() 包內模組 ID。若伺服器溝通斷,查內模組 ID 相符(伺服器呼中無 ns())。

步驟六:隔離測模組

# Quick test app for the module
if (interactive()) {
  shiny::shinyApp(
    ui = fluidPage(
      dataFilterUI("test"),
      DT::dataTableOutput("result")
    ),
    server = function(input, output, session) {
      data <- reactive(iris)
      filtered <- dataFilterServer("test", data, names(iris))
      output$result <- DT::renderDataTable(filtered())
    }
  )
}

預期: 模組於最小測應用中正工。

失敗時: 若模組於隔離敗而於全應用工(或反),查對全域變或父會話狀態之隱依。

驗證

  • 模組 UI 函受 id 為首參且用 NS(id)
  • UI 中每輸入/輸出 ID 皆包於 ns()
  • 模組伺服器用 moduleServer(id, function(input, output, session) { ... })
  • 伺服器中動態 UI 之 ID 用 session$ns
  • 模組可實例化多次而無 ID 碰撞
  • 反應返值可為父應用存取
  • 模組於最小獨立測應用中工

常見陷阱

  • renderUI() 中忘 ns():伺服器內創之動態 UI 須用 session$ns——外之 nsmoduleServer() 內不可得
  • 傳非反應數據:隨時變之模組參須為反應式表達。傳 reactive(data)data
  • ID 失配:UI 呼中之 id 字串須與伺服器呼中之 id 完相符
  • 不返反應:若模組算父所需之物,須 return() 一反應。忘此為默錯
  • 嵌模組之命名空間:UI:ns("inner_id")。伺服器:僅 "inner_id"。混致雙包或漏前綴

相關技能

  • scaffold-shiny-app — 加模組前立應用結構
  • test-shiny-app — 以 testServer() 單元測測模組
  • design-shiny-ui — 模組 UI 之 bslib 版型與主題
  • optimize-shiny-performance — 模組內之快取與 async 模式

GitHub 저장소

pjt222/agent-almanac
경로: i18n/wenyan-lite/skills/build-shiny-module
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

연관 스킬

content-collections

메타

이 스킬은 콘텐츠 콜렉션(Content Collections)을 위한 프로덕션 검증된 설정을 제공합니다. 콘텐츠 콜렉션은 Markdown/MDX 파일을 Zod 검증이 포함된 타입 안전한 데이터 콜렉션으로 변환해주는 TypeScript 최우선 도구입니다. 블로그, 문서 사이트 또는 콘텐츠 중심의 Vite + React 애플리케이션을 구축할 때 타입 안전성과 자동 콘텐츠 검증을 보장하기 위해 사용하세요. Vite 플러그인 구성과 MDX 컴파일부터 배포 최적화 및 스키마 검증에 이르기까지 모든 것을 다룹니다.

스킬 보기

polymarket

메타

이 스킬은 개발자들이 Polymarket 예측 시장 플랫폼을 활용한 애플리케이션을 구축할 수 있도록 지원하며, 거래 및 시장 데이터를 위한 API 통합 기능을 포함합니다. 또한 WebSocket을 통한 실시간 데이터 스트리밍을 제공하여 실시간 거래와 시장 활동을 모니터링할 수 있습니다. 이를 통해 거래 전략을 구현하거나 실시간 시장 업데이트를 처리하는 도구를 생성하는 데 활용할 수 있습니다.

스킬 보기

creating-opencode-plugins

메타

이 스킬은 개발자들이 명령어, 파일, LSP 작업 등 25개 이상의 이벤트 유형에 연결되는 OpenCode 플러그인을 만들 수 있도록 돕습니다. JavaScript/TypeScript 모듈을 위한 플러그인 구조, 이벤트 API 명세, 구현 패턴을 제공합니다. OpenCode AI 어시스턴트의 라이프사이클을 사용자 정의 이벤트 기반 로직으로 가로채거나, 모니터링하거나, 확장해야 할 때 사용하세요.

스킬 보기

sglang

메타

SGLang은 RadixAttention 프리픽스 캐싱을 활용하여 JSON, 정규식, 에이전트 워크플로우를 위한 고속 구조화 생성에 특화된 고성능 LLM 서빙 프레임워크입니다. 특히 반복되는 프리픽스가 있는 작업에서 상당히 빠른 추론 속도를 제공하여 복잡한 구조화 출력 및 다중 턴 대화에 이상적입니다. 제약 디코딩이 필요하거나 광범위한 프리픽스 공유가 있는 애플리케이션을 구축할 때는 vLLM과 같은 대안보다 SGLang을 선택하십시오.

스킬 보기