library(shiny)
ui <- fluidPage(
sliderInput("obs", "Number of observations", 0, 1000, 500),
actionButton("goButton", "Go!", class = "btn-success"),
plotOutput("distPlot")
)
server <- function(input, output) {
output$distPlot <- renderPlot({
input$goButton
dist <- isolate(rnorm(input$obs))
hist(dist)
})
}
shinyApp(ui, server)
bslib
bslib이란 bootstrap의 css를 R에서 사용할 수 있도록 만든 패키지입니다. 정확한 원문 설명은 Tools for theming Shiny and R Markdown via Bootstrap 3, 4, or 5. 으로, Shiny와 Rmarkdown (당연히 Quarto를 포함)에서 여러 테마를 활용할 수 있게 합니다.
이 글에서는 bslib의 활용 방법들중 Shiny에 집중하여 설명합니다.
사실 Shiny는 기본적으로 디자인을 위해 bootstrap을 사용합니다. 그런데 Shiny는 패키지를 이루고 있는 구성 요소들과, 관계가 너무 복잡하게 얽혀 있는 상당히 무거운 패키지가 되어버렸고 이로 인해 업데이트에 영향을 받는 부분이 많아, 기능 위주의 업데이트를 하는 것으로 알려져 있습니다.
즉, UI를 주로 다루는 bootstrap 부분은 5년 전의 버전인 3.4.1 버전을 사용하고 있고, 별도의 테마 설정을 하지 않는다면 특유의 파랑 / 회색 테마를 기본적으로 사용하게 됩니다.(최근 버전은 5.3.3)
그래서 shiny에서는 정체된 UI를 업데이트 하기 위해 UI를 다루는 별도의 R 패키지를 만들어 덮어 씌우듯 최근 bootstrap의 기능들을 제공하게 됩니다.
이 글에서는 bslib의 주요 사용법은 다루지 않습니다.
shiny with loading
actionButton
의 이 문제를 해결하기 위해 여러 방법들이 존재했습니다.
이 방법은 shiny에서 기본적으로 제공하는 Progress Indicator UI를 활용하는 방법으로 연산의 과정 / 단계가 진행됨에 따라 진행 정도를 사용자에게 보여줄 수 있습니다.
server <- function(input, output) {
output$plot <- renderPlot({
input$goPlot
dat <- data.frame(x = numeric(0), y = numeric(0))
withProgress(message = 'Making plot', value = 0, {
n <- 10
for (i in 1:n) {
dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
incProgress(1/n, detail = paste("Doing part", i))
Sys.sleep(0.1)
}
})
plot(dat$x, dat$y)
})
}
ui <- shinyUI(basicPage(
plotOutput('plot', width = "300px", height = "300px"),
actionButton('goPlot', 'Go plot')
))
shinyApp(ui = ui, server = server)
그러나 이는 withProgress
, incProgress
또는 Progress
등의 함수와 오브젝트를 시간이 오래걸리는 연산에 추가로 코드를 작성해야한다는 단점이 있습니다.
- 별도의 R 패키지 사용
R의 생태계에는 해결하려는 여러 문제가 있고, 그 문제마다의 R 패키지가 있다고 생각해도 과언이 아닌데요. actionButton과 연산 결과 사이의 긴 공백을 UI에 표기하기 위한 기능 또한 마찬가지입니다.
이전의 progress indicator와 유사하게 추가 코드를 작성하여 해결해야하며 조금 더 디자인이나 세부 설정을 할 수 있는 커스텀 기능이 있다고 생각하면 좋습니다.
아래는 몇가지 예시 패키지와 사례입니다 (알파벳순).
정리
이번 글에서는 bslib의 최신 기능인 input_task_button과 간단한 사용 사례를 소개했습니다.
이는 잠재적으로 사용자 경험을 향상시키는 기능이며, 기존의 shiny에서는 추가 코드를 작성해야하는 번거로움을 해결해주는 기능이라고 생각합니다.
특히 다른 웹 어플리케이션과 다르게 Shiny에서는 대용량 데이터 연산으로 인해 시간이 오래 걸리는 경우가 많지만, 상대적으로 빈약한 UI/UX를 가지고 있어 기존의 actionButton
을 input_task_button
으로 대체할 경우 이를 보완하는데 큰 도움이 될 것입니다.
이번 글이 도움이 되었길 바라며, 다음 글에서 또 만나요!
Reuse
Citation
@online{kim2024,
author = {Kim, Jinhwan},
title = {Bslib: Input\_task\_button {소개}},
date = {2024-03-30},
url = {https://blog.zarathu.com/posts/2024-03-30-input-task-button/},
langid = {en}
}