본문 바로가기
행복바이러스 행복바이러스

Bubble.io 상태(Custom State) 관리 최적화를 통한 불필요한 DB 저장 비용 절감

읽는 시간 약 16분

Bubble.io로 앱을 만들다 보면 탭 선택값, 팝업 열림 여부, 임시 필터, 장바구니 선택 목록처럼 잠깐만 필요한 정보까지 데이터베이스에 저장하는 경우가 있습니다. 기능은 정상적으로 작동하더라도 사용자의 클릭마다 Make changes to a thing이 실행되면 서버 작업이 반복되고, 데이터 구조도 불필요하게 복잡해집니다.

이럴 때 활용할 수 있는 기능이 **Custom State(사용자 정의 상태)**입니다. Custom State는 페이지나 요소에 임시 값을 보관하는 클라이언트 측 변수입니다. 영구 보존할 필요가 없는 UI 상태를 데이터베이스와 분리하면 불필요한 저장 요청을 줄이고 화면 반응 속도와 유지보수성을 함께 개선할 수 있습니다.

다만 Custom State가 데이터베이스를 완전히 대신하는 것은 아닙니다. 이 글에서는 어떤 값을 상태로 관리해야 하는지, 실제 Bubble 편집기에서는 어떻게 설정하는지, 그리고 잘못 사용할 때 생길 수 있는 보안·성능 문제까지 단계별로 정리합니다.

Custom State란 무엇인가?

Custom State는 페이지, 그룹, 팝업, 재사용 요소 등 Bubble 페이지의 요소에 정의할 수 있는 임시 변수입니다. 텍스트, 숫자, yes/no, 날짜, Option Set, Thing 또는 목록 형태의 값을 담을 수 있으며 워크플로의 Set state 액션으로 변경합니다.

예를 들어 상품 목록에서 사용자가 선택한 카테고리를 기억해야 한다면 매번 User 데이터의 selected_category 필드를 수정할 필요가 없습니다. 페이지에 selected_category라는 Custom State를 만들고 클릭할 때 값만 변경하면 됩니다. 조건부 표시와 검색 제약조건은 이 상태값을 참조할 수 있습니다.

Custom State의 핵심 특징은 다음과 같습니다.

  • 현재 페이지 세션에서만 사용하는 임시 데이터에 적합합니다.
  • Set state는 클라이언트 측에서 처리됩니다.
  • 페이지를 새로고침하거나 다른 페이지로 이동하면 값이 초기화됩니다.
  • 단일 값뿐 아니라 목록도 저장할 수 있습니다.
  • 데이터베이스의 개인정보 보호 규칙을 대체하지 않습니다.

Bubble 공식 문서에서도 Custom State를 페이지가 다시 로드될 때 초기화되는 임시 변수로 설명합니다. 따라서 ‘빠르게 바뀌지만 영구 저장할 필요가 없는 값’에 사용하는 것이 가장 적절합니다.

DB 저장과 Custom State의 차이

두 방식의 차이를 먼저 이해하면 저장 위치를 결정하기 쉬워집니다.

구분Custom StateBubble Database
저장 위치브라우저의 현재 페이지 상태서버 데이터베이스
유지 기간페이지 새로고침 전까지삭제하거나 수정할 때까지
적합한 데이터탭, 필터, 선택 목록, 임시 계산값회원정보, 주문, 결제, 게시물
처리 방식주로 클라이언트 측서버 측 데이터 작업
여러 기기 공유불가능가능
보안 용도사용하면 안 됨Privacy Rules와 함께 사용

가장 간단한 판단 기준은 다음 질문입니다.

사용자가 지금 브라우저를 닫아도 이 값이 반드시 남아 있어야 하는가?

대답이 ‘아니요’라면 Custom State가 적합할 가능성이 큽니다. 반대로 주문 상태, 결제 결과, 사용 권한, 작성 중인 중요한 문서처럼 유실되면 안 되는 값은 데이터베이스에 저장해야 합니다.

불필요한 DB 저장이 발생하는 대표 사례

1. 탭을 누를 때마다 User 데이터를 수정하는 경우

마이페이지에 ‘주문 내역’, ‘찜 목록’, ‘문의 내역’ 탭이 있다고 가정해 보겠습니다. 사용자가 탭을 바꿀 때마다 Current User's active_tab을 수정하면 단순한 화면 전환에도 서버 저장 작업이 실행됩니다.

이 값은 페이지를 떠난 뒤 유지할 필요가 없다면 페이지에 active_tab 상태를 만들고 각 버튼의 클릭 워크플로에서 Set state만 실행하는 편이 적절합니다.

2. 검색 필터 변경 즉시 DB에 저장하는 경우

가격 범위, 정렬 방식, 카테고리, 배송 조건을 클릭할 때마다 데이터베이스를 수정할 필요는 없습니다. 여러 필터를 상태에 보관한 뒤 사용자가 ‘적용’ 버튼을 눌렀을 때 Repeating Group의 데이터 소스에 반영할 수 있습니다.

사용자별 필터 프리셋을 다음 방문에도 불러와야 할 때만 ‘설정 저장’ 버튼을 별도로 두고 DB에 한 번 저장하는 구조가 효율적입니다.

3. 다단계 입력 폼의 각 단계마다 저장하는 경우

회원가입이나 견적 요청 폼에서 한 단계 이동할 때마다 Thing을 생성·수정하면 미완성 레코드가 늘어날 수 있습니다. 입력 도중의 단계 번호와 선택값은 Custom State로 관리하고, 최종 제출 시 검증을 통과한 데이터만 DB에 저장하면 불필요한 레코드를 줄일 수 있습니다.

단, 작성 시간이 길거나 중간 이탈 후 복구가 꼭 필요한 폼이라면 자동 저장이 필요합니다. 이때는 모든 키 입력마다 저장하지 말고 일정 시간 간격, 단계 완료 또는 명시적인 임시 저장 시점으로 묶는 방식을 고려해야 합니다.

4. 모달과 드롭다운의 표시 상태를 저장하는 경우

팝업의 열림 여부, 사이드바 접힘 상태, 선택된 아코디언 항목은 대부분 UI 상태입니다. yes/no 타입의 상태로 관리하거나 Bubble 요소의 표시 기능을 이용하면 충분합니다.

Bubble 편집기에서 Custom State 설정하기

상품 비교 화면에서 사용자가 선택한 상품 목록을 임시로 관리하는 예제를 만들어 보겠습니다.

1단계: 상태를 저장할 요소 선택

페이지 전체에서 참조해야 한다면 페이지 자체를 선택합니다. 특정 그룹 안에서만 사용할 값이라면 해당 그룹에 상태를 두는 것이 관리하기 쉽습니다.

2단계: Custom State 생성

선택한 요소의 속성 편집기에서 Custom States 영역을 열고 새 상태를 추가합니다.

  • State name: selected_products
  • State type: Product
  • This state is a list: 체크

이름은 temp, value1처럼 모호하게 짓기보다 selected_products, active_tab, draft_quantity처럼 역할이 드러나도록 작성하는 것이 좋습니다.

3단계: 클릭 워크플로에서 값 추가

상품 카드의 ‘비교하기’ 버튼을 클릭했을 때 Element Actions → Set state를 선택합니다.

  • Element: 상태를 만든 페이지 또는 그룹
  • Custom state: selected_products
  • Value: 기존 selected_products :plus item Current cell's Product

중복 추가를 막으려면 워크플로 조건에 selected_products doesn't contain Current cell's Product를 설정합니다.

4단계: 목록에서 값 제거

선택 해제 버튼에는 같은 상태를 지정하고 값을 selected_products :minus item Current cell's Product로 설정합니다. 별도의 DB 수정 없이 브라우저 화면에서 선택 목록이 즉시 바뀝니다.

5단계: 최종 확정 시 한 번만 저장

사용자가 ‘비교 목록 저장’을 눌렀을 때만 User 또는 별도 데이터 타입에 최종 목록을 저장합니다. 즉, 탐색 과정은 상태로 처리하고 명확한 저장 의사가 발생한 시점에만 DB 작업을 실행합니다.

비용 절감을 위한 상태 관리 설계 원칙

UI 상태와 비즈니스 데이터를 분리한다

UI 상태는 화면이 어떻게 보이는지를 결정합니다. 선택된 탭, 팝업 표시 여부, 임시 정렬 기준이 이에 해당합니다. 비즈니스 데이터는 서비스 운영과 기록에 필요한 정보로 주문, 예약, 결제, 권한 등이 해당합니다.

두 종류를 분리하면 어떤 워크플로가 서버 저장을 일으키는지 쉽게 파악할 수 있습니다.

상태의 범위를 가능한 작게 유지한다

페이지 전체에서 쓰지 않는 값을 무조건 Page에 모으면 나중에 의존 관계를 추적하기 어렵습니다. 상품 필터 그룹에서만 사용하는 상태는 필터 그룹에, 재사용 요소 내부에서만 사용하는 값은 해당 재사용 요소에 두는 방식이 좋습니다.

하나의 상태에 지나치게 큰 목록을 담지 않는다

Custom State가 DB 쓰기를 줄여 준다고 해서 수천 개의 Thing을 목록으로 저장하는 것은 바람직하지 않습니다. 브라우저 메모리와 렌더링 부담이 커질 수 있고, 상태를 참조하는 조건이 많으면 화면 갱신도 복잡해집니다.

상태에는 사용자가 실제로 선택한 소수 항목이나 필터 조건만 담고, 대규모 데이터 조회는 검색 제약조건과 페이지네이션을 활용하는 편이 안전합니다.

연속 입력과 최종 저장을 분리한다

슬라이더 이동, 텍스트 입력, 드래그 정렬처럼 짧은 시간에 여러 이벤트가 발생하는 기능은 우선 상태에 반영합니다. 사용자가 입력을 마치거나 저장 버튼을 누를 때 최종 결과만 DB에 기록하면 반복 수정 작업을 줄일 수 있습니다.

저장 시점을 사용자에게 명확히 알린다

임시 상태와 영구 저장을 구분한 앱에서는 ‘적용’, ‘임시 저장’, ‘완료’ 버튼의 의미가 분명해야 합니다. 저장 완료 메시지나 변경사항 미저장 안내를 제공하면 사용자가 페이지를 닫아 데이터를 잃는 문제를 예방할 수 있습니다.

반드시 데이터베이스에 저장해야 하는 값

다음 항목은 비용을 줄이겠다는 이유로 Custom State에만 보관하면 안 됩니다.

  • 결제 성공 여부와 거래 식별값
  • 주문·예약·배송 상태
  • 사용자 역할과 접근 권한
  • 다른 사용자와 공유해야 하는 데이터
  • 새로고침 이후에도 복구해야 하는 작성 내용
  • 감사 로그나 법적 보존이 필요한 기록
  • 서버 워크플로가 참조해야 하는 값

특히 Custom State는 보안 장치가 아닙니다. 브라우저에서 사용하는 값이므로 관리자 여부나 유료 회원 권한을 상태값만으로 판단해서는 안 됩니다. 권한 검증은 데이터베이스의 실제 값과 Privacy Rules, 서버 측 워크플로를 기준으로 구성해야 합니다.

새로고침 후에도 임시 값을 유지하려면?

Custom State는 새로고침하면 초기화됩니다. 값의 성격에 따라 다음 방식을 선택할 수 있습니다.

  • 검색어·카테고리처럼 공유 가능한 조건: URL parameter
  • 짧은 기간 브라우저에 남길 일반 설정: 적절한 로컬 저장 방식 검토
  • 로그인 사용자의 기기 간 동기화가 필요한 설정: Database
  • 민감하거나 권한에 영향을 주는 값: 서버 검증이 가능한 Database

URL parameter는 링크를 공유하거나 새로고침해도 조건을 복원할 수 있다는 장점이 있지만 주소창에 노출됩니다. 개인정보, 인증 토큰, 비밀값을 넣어서는 안 됩니다.

적용 전후를 확인하는 점검 방법

최적화 효과를 판단하려면 감으로 추측하기보다 동일한 사용자 흐름을 전후로 비교해야 합니다.

  1. 버튼 클릭, 필터 변경, 입력 이벤트에 연결된 DB 액션을 목록화합니다.
  2. 영구 보존이 필요 없는 Create a new thing과 Make changes to thing을 찾습니다.
  3. 해당 값을 Custom State로 전환합니다.
  4. 최종 제출 또는 저장 시점에만 DB 액션이 실행되는지 확인합니다.
  5. 새로고침, 뒤로 가기, 중복 클릭, 빠른 연속 입력을 테스트합니다.
  6. 실제 저장이 필요한 데이터가 누락되지 않았는지 검증합니다.

예를 들어 필터 5개를 바꿀 때마다 User 레코드를 수정하던 구조를 ‘필터 상태 변경 5회 + 적용 시 저장 1회’로 바꾸면 사용자 경험은 유지하면서 서버 저장 횟수를 줄일 수 있습니다. 다만 절감 폭은 앱의 워크플로, 데이터 검색 구조, 사용자 행동에 따라 달라지므로 실제 로그와 Bubble의 사용량 지표를 함께 확인해야 합니다.

자주 발생하는 실수

모든 데이터를 상태로 바꾸는 것

상태 최적화의 목적은 임시 데이터와 영구 데이터를 분리하는 것입니다. DB 사용 자체를 없애는 것이 아닙니다. 저장 책임이 있는 데이터를 상태로만 관리하면 새로고침이나 페이지 이동 시 유실됩니다.

상태 이름과 위치가 일관되지 않은 것

동일한 의미의 상태를 Page, Group, Reusable Element에 중복 생성하면 어느 값이 최신인지 알기 어렵습니다. 상태의 소유 요소와 이름 규칙을 미리 정하는 것이 좋습니다.

민감한 값을 담는 것

Custom State에 API 키, 비밀번호, 인증 토큰 같은 비밀정보를 보관해서는 안 됩니다. 화면에서 값을 숨기는 것과 데이터가 안전하게 보호되는 것은 다른 문제입니다.

자동 저장을 무조건 제거하는 것

긴 신청서나 문서 편집기에서는 중간 저장이 사용자 보호 기능이 될 수 있습니다. 이런 기능은 완전히 제거하기보다 저장 빈도를 조절하고 변경된 필드만 처리하는 방향으로 설계해야 합니다.

실무 체크리스트

  • 이 값은 새로고침 후에도 남아야 하는가?
  • 다른 사용자나 다른 기기에서도 조회해야 하는가?
  • 결제, 주문, 권한 또는 감사 기록과 관련되는가?
  • 버튼 클릭 때마다 DB 수정이 실행되고 있지는 않은가?
  • 연속 이벤트를 최종 저장 한 번으로 묶을 수 있는가?
  • Custom State의 타입과 목록 여부가 정확한가?
  • 상태 목록의 크기가 지나치게 커지지는 않는가?
  • 최종 저장 실패 시 사용자에게 오류를 안내하는가?
  • 상태값을 보안 판단의 근거로 사용하고 있지는 않은가?

자주 묻는 질문

Custom State를 사용하면 DB 비용이 무조건 줄어드나요?

DB 수정 대신 클라이언트의 Set state로 처리할 수 있는 흐름이라면 서버 저장 작업을 줄이는 데 도움이 됩니다. 그러나 상태값을 표시하기 위해 반복적으로 복잡한 검색을 실행한다면 조회 측 부하는 별도로 발생할 수 있습니다. 저장과 검색을 함께 점검해야 합니다.

Custom State에 Thing 전체를 저장해도 되나요?

가능하지만 해당 Thing이 브라우저에 로드되어야 하며, 데이터 접근은 Privacy Rules의 영향을 받습니다. 단순 선택 표시만 필요하다면 Thing 전체 목록 대신 필요한 식별 기준이나 소수의 선택 항목만 관리하는 편이 명확할 수 있습니다.

재사용 요소에서도 Custom State를 사용할 수 있나요?

가능합니다. 재사용 요소 내부 전용 상태를 만들면 구성 요소의 독립성을 높일 수 있습니다. 외부 페이지와 값을 주고받을 때는 노출된 상태나 이벤트 구조를 일관되게 설계해야 합니다.

입력값도 모두 Custom State로 복사해야 하나요?

아닙니다. Input 요소 자체가 현재 값을 보유하므로 별도의 상태가 필요하지 않은 경우가 많습니다. 여러 요소에서 가공된 값을 공동으로 참조하거나 단계 간 선택 결과를 관리할 때 Custom State를 사용하면 됩니다.

마무리

Bubble.io 앱의 저장 비용과 워크플로 복잡도를 줄이는 가장 현실적인 방법은 모든 값을 DB에 기록하는 습관부터 점검하는 것입니다. 탭, 필터, 모달, 임시 선택 목록처럼 페이지 안에서만 필요한 정보는 Custom State로 관리하고, 주문·결제·권한처럼 영구성과 신뢰성이 필요한 정보만 데이터베이스에 저장해야 합니다.

핵심은 ‘DB와 Custom State 중 어느 것이 더 좋은가’가 아니라 데이터의 수명과 책임에 맞는 저장 위치를 선택하는 것입니다. 이 원칙을 적용하면 불필요한 서버 저장 요청을 줄이면서도 데이터 유실과 보안 문제를 예방할 수 있습니다.

youngji
함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.

광고 차단 알림

광고 클릭 제한을 초과하여 광고가 차단되었습니다.

단시간에 반복적인 광고 클릭은 시스템에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.