Google AppSheet라는 것을 알고 계십니까?
간단히 소개하자면 코딩 없이 모바일-웹 크로스플랫폼 앱을 만들 수 있는 no code 플랫폼 되시겠습니다. DB로 구글 스프레드 시트를 사용하거나, 테이블을 만드는 것만으로 CRUD 관련 화면을 자동 생성해 주는 등, 여러 재미있는 기능을 많이 가지고 있습니다. 저는 현재 일본에서 일하고 있어서 한국어권에서 얼마나 앱시트를 사용하는지는 모르겠습니다만, 제가 다니는 회사에선 그럭저럭 자주 앱시트 프로젝트가 들어옵니다.
그런데 이 친구가 노 코드 플랫폼이다보니 플랫폼 안에서 못 하는 일이 꽤나 많습니다. 뭘 좀 하려고 하면 간단히 안 되니까 검색을 하게 되는데, 검색을 해도 뭐가 나오는 게 없습니다. 그리고 가끔은 간단한 일을 위해 상당히 빙 돌아가게 되거나, 정체불명의 버그를 회피하려 불편한 길을 가야 하기도 합니다.
저는 이렇게 저의 능력과는 상관 없이 플랫폼에게 억까를 당해 왔습니다. 하지만 혼자 겪기는 억울해서, 그걸 블로그에 공유해 보기로 마음을 먹었습니다. 평소엔 오타쿠 번역물이나 올라오는 곳에 이런 삐삐쀼쀼 제재를 가져와도 되는가 약간 고민은 되었습니다만, 외국에서 겪은 일을 한국어로 공유하는 것도 가치가 있지 않을까 하는 생각이 들었습니다.
아무튼 그래서 제목의 억까 에피소드를 이야기하기 전에, 기왕이니 이 앱시트의 재미있는 특징들에 대해서 먼저 이야기해 보겠습니다.
앱시트의 기묘함
동시에 여러명이 작업할 수 없다
개인적으로 최고로 '말도 안 된다'고 생각한 특징은 여러 사람이 동시에 작업하는 게 불가능한 설계라는 점입니다.
왜인고 하니, 한 사람이 변경을 저장하면 다른 사람은 새로고침을 할 때까지 저장을 못 하기 때문입니다. 새로고침 하면 되는 거 아니냐고요? 새로고침을 하면 당연하게도 저장하지 않은 변경이 날아갑니다. 그러니까 누군가가 저장 버튼을 누를 때마다 다른 팀원은 '내가 지난번 저장으로부터 무슨 변경을 했는가?'를 다 기억해 놨다가 새로고침을 하고 같은 작업을 다시 해야 하는 것입니다.
상황이 이러니 저장 버튼을 자주 누르게 됩니다. 변경점을 전부 기억해 둬야 하니까요. 그런데 저장 버튼을 누르면 다른 팀원이 작업을 다시 해야 합니다. 세 명의 팀원이 평균 6분마다 저장 버튼을 누른다 치면 실제 작업에 쓸 수 있는 시간은 단 2분에 불과합니다. 2분 후에는 또 다른 누군가가 저장을 시도할 테니까요.
"잠깐만요. 새로고침 안내 메시지를 잘 보니까 버전 번호가 겹쳐서 그렇다는데요? 혹시 수동으로 버전 번호를 올려서 저장하면 저장이 되지 않나요?"
네 잘 보셨습니다. 사실 버전 번호를 올리면 저장이 되긴 됩니다. 그런데 그러면 내 버전이 최신 버전이 되는 겁니다. 새로고침을 안 했으니까 직전에 저장한 팀원의 변경 내역은 아직 내 브라우저에는 반영이 안 돼 있죠? 즉 방금 팀원이 저장한 내용이 날아가 버립니다. 이놈의 플랫폼은 변경점만 저장한다거나 그런 융통성이 없습니다. 전부 덮어써 버립니다.
해결법은 간단한데, 그냥 혼자 작업하든가, 아니면 새로고침을 받아들이는 겁니다.
서브 쿼리를 쓸 수 없다
앱시트에는 SELECT()나 FILTER() 같은 쿼리 함수가 있습니다. 그런데 쿼리의 조건에 쿼리를 넣을 수는 없습니다. 서브쿼리가 안 된다는 겁니다. 이게 참 자주는 아니지만 불편할 때 정말 불편합니다.
그러면 이걸 어떻게 해결할 수 있을까요? 정답은 서브쿼리의 결과물을 별도의 컬럼에 저장했다가 그걸 쓰면 됩니다. 컬럼을 변수마냥 쓰는 거죠. 이럴 때에 쓰이는 게 Virtual Column인데요. 이 친구는 테이블에 모종의 변경이 일어날 때마다 값을 다시 평가합니다. Lazy evaluation따위 없습니다. 만약 여기에 서브쿼리를 넣었고 테이블에 데이터가 그럭저럭 많다면... 음... 행운을 빕니다.
일부 Bot의 실행 로그가 남지 않는다
앱시트에선 일련의 실행을 하나로 묶어서, 특정 이벤트를 트리거로 실행시키는 Bot이란 기능이 있습니다. 이벤트로 자동 실행되는 함수라고 보시면 됩니다.
여기서 이벤트에는 몇가지 종류가 있는데, 대표적으로 '특정 테이블에 변경이 일어났을 때'와 '시간을 정해서 자동 실행' 등이 있습니다. 앱을 디플로이하기 전까지는 '시간을 정해서 실행'은 실행되지 않습니다. 대신 실행하기 버튼이 있어서, 그걸로 실행을 시켜 보면서 개발을 하게 됩니다.
그런데 테이블과 무관한 Bot을 실행하기 버튼으로 실행하면 실행 로그가 안 남습니다(...) 뭔가 실행이 된 것 같긴 한데 이게 끝까지 잘 실행된 건지, 중간에 실패해서 끊긴 건지, 무슨 이유로 실패했는지, 알 수 있는 게 없습니다.
그럼 이놈의 Bot을 어떻게 디버깅할 수 있을까요? 글쎄요. 일단 저는 각 스텝 사이사이에 'ㅇㅇ 테이블에 데이터 삽입' 같은 걸 추가해서 로그 대용으로 썼습니다. 물론 중간에 실패가 떠도 이유는 모릅니다.
Bot에서 Apps Script를 호출했더니 데이터가 변경되지 않는다
오늘의 본론입니다.
이런 기묘한 앱시트에도 약간의 양심이 있습니다. 플랫폼에서 뭘 하기가 팍팍하면 Google Apps Script에다 코딩을 하고 그걸 호출할 수 있습니다. 물론 여기에도 권한 문제나 여러 성가신 특징이 있습니다만 없는 것보단 낫죠.
그리하여 어느 날, 저는 이런 Bot을 설계했습니다.
TRIGGER 테이블에 레코드가 추가되면
-> 스크립트를 호출
-> 그 스크립트가 A 테이블의 데이터를 수정
-> TRIGGER 테이블에 추가된 레코드를 삭제
스크립트가 제대로 동작하는 것은 이미 검증된 후였고 Bot의 각각의 스텝도 특별할 게 없습니다. 그런데 결과를 보니 A 테이블이 수정되지 않았습니다.
스크립트의 실행이력을 보니 스크립트는 정상적으로 A 테이블의 데이터를 수정한 후였습니다. 그런데도 Bot을 실행한 뒤에 테이블을 확인해 보면 수정된 내용은 사라지고 없었습니다. 이게 대체 무슨 일이란 말입니까?
자세히 보니 스크립트는 확실히 A 테이블을 업데이트하고 있었습니다. 그런데 그 직후에 변경이 롤백(??)된다는 걸 알게 됐습니다. 누가 대체 어떻게? 범인은 하나밖에 없지 않겠습니까? TRIGGER 테이블에 추가된 레코드를 삭제한다는 마지막 스텝이 다른 테이블의 변경을 롤백하고 있었던 것입니다.
언뜻 보면 이해가 가지 않지만 그것 말고는 설명이 되지 않습니다. 실제로 저 마지막 스텝을 위로 옮기면 아무 문제 없이 잘 돌아가거든요.
이 기묘한 현상을 두고 저는 가설을 세웠습니다. 어쩌면 앱시트는 스프레드 시트(DB)의 로컬 복사본을 변경한 후에 원본을 덮어쓰고 있는 것은 아닐까? 스크립트는 원본 스프레드 시트를 직접 조작했고, 그 후에 삭제 스텝이 실행될 복사본엔 그 수정이 반영되지 않은 게 아닐까? 그리고선 변경점만 동기시키는 것도 아니고 스프레드 시트를 전부 덮어쓴 건......?
믿고 싶지 않은 엉망진창인 가설입니다만 가능성을 부정할 수 없다는 게 앱시트의 무서운 부분입니다.
'생각 > 개발' 카테고리의 다른 글
[AppSheet억까일기] 새로 추가한 데이터에 이전 버전이 어디 있어 (2) | 2025.01.09 |
---|