Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Slate 의존 관계와 실행 설계

Slate의 위젯, 함수, 변수와 질의는 JSON 값을 만드는 노드입니다. Handlebars 참조가 노드 사이의 의존 관계를 정의하며 입력, 질의 결과나 변수값이 바뀌면 필요한 후속 노드를 다시 계산합니다.

값이 바뀌는 시점

Dependencies에서 문제 위젯의 상류를 확인합니다. 예상하지 않은 참조 때문에 무관한 입력이나 질의에 반응하고 있지 않은지 살핍니다.

의존 그래프는 상류의 값이 바뀌었을 때 후속 계산을 수행합니다. 상류를 다시 실행했어도 값이 이전과 같으면 질의를 다시 실행하거나 위젯을 다시 그리지 않을 수 있습니다. 선택 초기화에서 entropy를 함께 바꾸는 이유입니다.

이벤트를 사용할 때

일반적인 데이터와 표시 갱신은 의존 그래프에 맡깁니다. 질의 완료 후 toast, 클릭 후 Dialog, 여러 필터를 정한 뒤 버튼으로 질의 실행처럼 명시적인 동작이 필요하면 이벤트를 추가합니다.

이벤트 체인을 짧게 유지합니다. 앱의 이벤트가 50개를 넘고 단순 알림이나 질의 시작 이상의 로직이 많아지면 구조를 단순화하거나 앱을 나눌 시점인지 검토합니다. 50개는 플랫폼 한도가 아니라 설계 점검 기준입니다.

사용자 클릭 이벤트

HTML 또는 Table의 HTML 요소에 slClickEvent를 지정합니다.

<div class="pt-button" slClickEvent="delete">Delete Me</div>

위젯의 Click Event Names 배열에도 delete를 등록합니다. 그러면 myWidgetName.click.delete를 이벤트로 선택할 수 있습니다. HTML을 동적으로 만들더라도 가능한 이벤트 이름은 미리 등록해야 합니다.

조건부 동작

이벤트의 Action 코드에서 slDisableAction을 반환하면 이번 실행만 막습니다. 이벤트를 영구적으로 비활성화하지 않습니다.

복잡한 검사는 함수에 두고 Events에는 짧은 연결을 남깁니다. f_checkValidAction이 Boolean을 반환하는 구성의 예입니다.

if (!{{f_checkValidAction}}) {
  return {{slDisableAction}};
}

Events 코드에는 함수 편집기와 같은 lint 및 오류 안내가 없으므로 문제를 놓칠 수 있습니다. 필요한 경우 debugger;를 넣고 브라우저 개발 도구에서 실행을 조사합니다.

이벤트 값 전달

HTML 요소의 slClickEventValue로 추가 값을 전달하면 Events 코드에서 {{slEventValue}}로 읽습니다. 예를 들어 표의 행마다 삭제 요소를 만들고 값을 그 행의 기본 키로 정할 수 있습니다.

  1. myTable.click.delete를 v_idToDelete.set에 연결하여 이벤트값을 저장합니다.
  2. v_idToDelete.changed에서 수동 q_deleteRow.run을 실행합니다.
  3. 질의는 v_idToDelete를 대상 키로 사용합니다.

쓰기 동작은 사용자 클릭에서 시작하도록 구성하며 초기값이나 다른 상태 변경으로 같은 체인이 실행되지 않는지 구분합니다. 체인이 길어지면 관계를 확인하기 어려우므로 짧고 독립적으로 유지합니다.

순환 관계

의존 그래프는 방향성이 있고 순환이 없는 DAG입니다. 그러나 이벤트로 변수를 갱신하거나 질의를 실행하면 사실상 반복 관계를 만들 수 있습니다. 이런 구성은 실행 순서를 예측하기 어렵게 하므로 상태와 동작의 방향을 다시 나눕니다.

초기 질의와 연결 풀

페이지를 로드하면 그 범위의 필요한 노드가 계산됩니다. 상류 의존성이 없는 root 질의가 많으면 동시에 실행을 시도하여 브라우저 연결, 데이터베이스와 네트워크에 부하를 주고 대기나 실패가 생길 수 있습니다.

Postgate의 사용자별 연결 풀은 최대 10개 연결을 사용합니다. 모두 사용 중이면 다음 요청이 기다리며 연결을 기다리는 시간이 5초를 넘으면 풀에서 시간 초과가 발생할 수 있습니다. 이는 질의 자체의 5초 실행 제한이 아닙니다. 단독 Test에서는 빠른 질의도 다른 작업이 풀을 점유하면 기다리거나 실패할 수 있습니다.

다음처럼 초기 작업을 나눕니다.

  • 작은 사전 집계나 고유값 질의로 필터를 준비하고 사용자가 선택한 뒤 실제 데이터 질의를 실행합니다.
  • 초기 질의 수와 평균 5초 이상 걸리는 무거운 질의 및 결과 크기를 함께 줄입니다.
  • 조건부 질의 또는 수동 실행으로 필요한 때만 호출합니다.

예를 들어 페이지마다 다음을 반복한다면 category 목록을 상류에서 미리 계산할지 검토합니다.

SELECT DISTINCT category_col FROM "my_table";

파생 데이터셋을 준비한 뒤에는 다음처럼 읽을 수 있습니다.

SELECT * FROM "my_table_categories";

데이터 갱신 시 반복 작업을 상류에서 처리하고 앱에서는 필요한 결과를 가져오는 방식입니다. Postgres 성능과 인덱스 구성을 함께 확인합니다.

조건부 질의

Run 옆 설정의 In addition 또는 Triggers & interactions에서 조건을 지정할 수 있습니다. All dependencies are not null은 질의와 partial의 참조값이 없는 동안 실행을 막습니다. 조건은 수동 질의나 이벤트로 시작하는 질의와 함께 사용할 수도 있습니다.

수동 질의

Run 옆 드롭다운에서 manual을 선택하면 이벤트 또는 명시한 의존 관계로 실행합니다. 실행 후에는 의존 그래프가 후속 노드를 갱신하므로 이를 위해 모든 후속 작업을 q_queryName.success 이벤트로 다시 연결할 필요는 없습니다.

함수의 역할 나누기

관련된 표시값을 여러 함수에서 중복 계산하기보다 한 함수가 필요한 값을 객체로 반환할 수 있습니다. 반대로 서로 다른 작업을 과도하게 합치지 않도록 유지보수 범위도 고려합니다.

표시 열 추가

다음 예의 q_myQuery는 results 배열 첫 항목에 primaryKey 열 배열을 가진 객체를 반환합니다. f_deriveDisplayColumns는 각 키에 ID라는 표시 접두사를 붙인 열을 추가합니다.

var data = {{q_myQuery.results.[0]}};
data.newColA = _.map(data.primaryKey, value => "ID " + value);
return data;

이후 q_myQuery 대신 f_deriveDisplayColumns의 해당 결과를 참조합니다. 원래 열 구조를 유지하면서 표시 열을 추가하는 방식입니다. 같은 계산을 모든 사용자가 반복해야 한다면 변환 파이프라인에서 미리 만드는 것도 검토합니다.

재사용 라이브러리

복잡한 공통 JavaScript는 Functions editor의 라이브러리로 분리합니다. 라이브러리 안에는 Handlebars를 넣을 수 없으며 매개변수를 받는 순수 JavaScript 함수로 작성합니다. Slate 함수가 Handlebars 값을 읽어 매개변수로 전달합니다.

코드의 역할을 구분하고 의도나 제약이 바로 드러나지 않는 부분에 설명을 남깁니다. 사용자 입력과 상태 복원은 상호작용 패턴, 실제 값과 실행 순서는 Debugger로 확인합니다.