Opkle(옵클) - 창작자를 위한 앱과 시스템
옵클(Opkle)은 창작자를 위한 다양한 앱과 시스템을 제공하는 개발사입니다. 전자책 에디터 앱 'Opkle editor'를 출시했고, 관련 전자책 클래스를 제공하고 있습니다.
EDITOR
CLASS
BLOG
LOGIN
표현한다는 것의
무한한 가능성,
새로운 형태로
담아내다.
새로운 형태의 콘텐츠
Opkle은 코드 없이 웹을 마음껏 만들고, 누구나 자기 화면을 그릴 수 있도록 에디터를 만들고, 그 결과물을 어디서나 즐길 수 있게 돕는 팀입니다.
텍스트와 화면과의 조화를 통해, 웹을 짓는다는 것이 그저 단순한 코딩이 아닌, 상상을 펼치고 감각을 깨우는 과정이 될 수 있도록 좋은 도구를 만들어 냅니다.
옵클 에디터 개발기: 표 이미지를 만들기 위한 스프레드시트
dev
17
옵클 에디터 개발기: 같은 데이터를 표와 보드, 캘린더로
dev
18
옵클 에디터 개발기: 책을 웹에서 그대로 읽게 하는 퍼블리셔
dev
19
옵클 에디터 개발기: 편집 화면을 그대로 웹에 게시하기
dev
20
옵클 에디터 개발기: EPUB 에디터가 모든 작업을 연결하는 방식
dev
21
9
10
11
12
13
...
20
옵클 에디터 개발기: 편집 화면을 그대로 웹에 게시하기
퍼블리셔의 미리보기와 디자인 상태를 완성한 다음에는 그 화면을 실제 공개 URL로 옮기는 게시 시스템을 만들었습니다. 여기서 목표는 파일을 서버에 올리는 것보다 더 분명했습니다. 에디터에서 확인한 작업영역이 브라우저의 공개 페이지에서도 같은 크기 계산과 같은 챕터 이동, 같은 테마와 반응형 동작으로 실행되어야 했습니다.
일반적인 웹 내보내기는 편집 데이터를 읽어 새로운 HTML을 만듭니다. 그러나 출력물을 별도로 만들면 에디터와 공개본은 그 순간부터 서로 다른 두 해석기가 됩니다. 한쪽의 페이지 계산이나 모바일 탐색 방식을 고칠 때 다른 쪽에서도 같은 변경을 반복해야 하고, 조금만 어긋나도 미리보기에서 승인한 결과와 실제 링크가 달라집니다.
게시를 새로운 문서를 생성하는 변환으로 정의하지 않았습니다. 편집 시점에 확정된 문서 의미를 다른 실행 환경에서도 보존하는 과정으로 보았습니다. 서버와 브라우저의 책임을 어떻게 나눴는지보다 더 중요한 것은, 서로 다른 환경에서 같은 입력 상태가 같은 관측 결과를 만들어야 한다는 원칙이었습니다. 20편에서는 그 원칙을 공개 문서의 수학적 성질로 정리해 보려고 합니다.
Snapshot semantics
게시 시점의 문서를 \(\sigma_t\)라고 하면 공개본은 계속 변하는 편집 상태가 아니라 특정 시각에 확정된 상태를 읽어야 합니다. 그렇지 않으면 게시 요청이 진행되는 동안 바뀐 일부 값만 섞여, 어느 시점에도 실제로 존재하지 않았던 문서가 만들어질 수 있습니다. 스냅샷은 단순한 복사본이 아니라 하나의 논리적 시각에 대한 일관된 관측입니다.
렌더 결과를 \(R(\sigma,e)\)라고 두면 \(e\)는 화면 크기나 입력 방식 같은 실행 환경입니다. 에디터와 공개 페이지의 환경이 완전히 같을 수는 없으므로 픽셀 배열 전체가 동일할 필요는 없습니다. 대신 내용, 읽기 순서, 제약식, 허용된 상호작용이 같은 의미를 가져야 합니다. 환경 차이에 의해 달라질 수 있는 것과 문서 자체의 불변량을 분리하는 일이 먼저였습니다.
스냅샷은 완전해야 하지만 중복될 필요는 없습니다. 완전성은 공개 결과를 결정하는 데 필요한 정보가 외부의 가변 상태에 의존하지 않는다는 뜻입니다. 반면 이미 원본이 가진 내용을 다시 복제하거나, 계산으로 유도할 수 있는 값을 모두 저장하는 것은 상태 공간만 키웁니다. 최소 충분 통계량처럼 결과를 재현하는 데 필요한 정보만 남기되, 그것만으로 관측 의미를 결정할 수 있도록 경계를 잡았습니다.
정규화 함수 \(N\)에 대해 \(N(N(\sigma))=N(\sigma)\)가 성립하게 하면 오래된 상태와 새 상태도 같은 정규형에서 만납니다. 누락된 값, 허용 범위를 벗어난 값, 표현만 다른 동치값이 부팅할 때마다 다른 결과를 만들지 않습니다. 이 멱등적 정규화 덕분에 게시 스냅샷은 시간과 실행 환경이 바뀌어도 안정적인 의미 단위가 되었습니다.
Resource closure
전자책은 본문 하나로 이루어지지 않습니다. 문서가 글꼴과 이미지, 스타일, 내부 탐색 구조를 참조한다면 게시 가능한 단위는 시작 파일이 아니라 참조 그래프의 폐포입니다. 자원 그래프를 \(G=(V,E)\), 루트 문서를 \(r\)이라고 할 때 필요한 자원 집합은 \(r\)에서 도달 가능한 꼭짓점의 집합 \(\mathrm{Reach}(r)\)입니다.
이 집합에서 원소 하나가 빠지면 문서는 부분적으로만 존재합니다. 본문은 열리지만 글꼴이 달라지거나, 표지는 보이지만 내부 이미지가 사라지는 결과는 파일 전송의 성공과 문서 보존의 성공이 다르다는 뜻입니다. 그래서 게시 단위는 개별 파일의 목록보다 도달 가능성에 의해 정의되는 자기완결 그래프로 보는 편이 정확했습니다.
반대로 도달할 수 없는 자원을 계속 포함하면 스냅샷은 불필요하게 커지고 오래된 정보가 남습니다. 그래프 폐포를 구한 뒤 그 밖의 꼭짓점을 제외하는 것은 garbage collection의 mark-and-sweep와 같은 원리입니다. 루트에서 시작해 필요한 것만 표시하고, 관측 결과에 기여하지 않는 자원은 게시 의미에서 제거할 수 있습니다.
대표 이미지처럼 본문 실행에 필수적이지 않은 자원은 별도의 선택적 집합으로 두었습니다. 필수 집합 \(M\)과 부가 집합 \(A\)가 있을 때 게시 가능성은 \(M\)의 완전성으로 결정되고, \(A\)의 실패는 품질 저하일 수는 있어도 문서 자체의 실패가 되어서는 안 됩니다. 이 구분을 명확히 하니 자원 하나의 문제로 전체 출판이 중단되는 일 없이 자기완결성과 회복성을 함께 얻을 수 있었습니다.
Atomic publication
게시 시스템에서 가장 피해야 할 상태는 독자가 접근할 수는 있지만 내용이 덜 준비된 문서입니다. 외부에서 관측 가능한 상태를 \(U\), 준비가 끝난 상태를 \(C\)라고 하면 전이는 논리적으로 \(U\to C\)로 한 번에 보이는 편이 좋습니다. 내부에서 여러 작업이 필요하더라도 외부 관측자에게 중간 상태가 노출되지 않아야 합니다.
이 요구는 데이터베이스의 원자성보다 넓습니다. 큰 자원과 작은 메타데이터는 비용과 실패 양상이 다르고, 하나의 물리적 트랜잭션에 모두 넣는다고 문제가 사라지지 않습니다. 중요한 것은 어느 지점을 publication의 선형화 지점으로 정할 것인지입니다. 그 지점 이전에는 이전 버전이 유효하고, 이후에는 새 버전 전체가 유효해야 합니다.
실패 모델도 명시적으로 나누었습니다. 준비 전 실패는 아무것도 공개되지 않은 상태로 돌아가야 하고, 확정 후 정리 실패는 이미 성공한 공개 상태를 되돌려서는 안 됩니다. 이를 상태 기계로 쓰면 준비 \(P\), 확정 \(C\), 정리 \(K\) 사이의 전이에서 어떤 실패가 보상 가능한지 분명해집니다. 모든 오류를 같은 방식으로 되돌리려 하면 오히려 성공한 결과까지 손상됩니다.
재시도 가능성은 멱등성에서 나옵니다. 같은 게시 의도 \(q\)를 두 번 적용해도 \(F(F(s,q),q)=F(s,q)\)가 성립하면 네트워크 단절 뒤의 재요청이 중복 문서를 만들지 않습니다. 게시, 갱신, 복구를 이 원칙에 맞춰 검증했고, 외부에서는 언제나 완성된 이전 상태 또는 완성된 새 상태만 관측되도록 안정화했습니다.
Identity와 namespace
문서의 내용, 문서의 정체성, 독자가 사용하는 이름은 같은 것이 아닙니다. 내용은 시간이 지나며 바뀌고, 정체성은 그 변화들을 하나의 문서 역사로 묶으며, 공개 이름은 정체성을 외부 namespace에 사상한 결과입니다. 이 세 층을 합치면 내용을 고칠 때 주소가 바뀌거나, 이름이 우연히 같다는 이유로 서로 다른 문서가 충돌합니다.
정체성 집합을 \(I\), 공개 이름 집합을 \(N\)이라고 하면 이름 부여는 부분함수 \(u:I\rightharpoonup N\)로 볼 수 있습니다. 공개 중인 문서들에 대해 이 함수는 단사여야 합니다. \(u(i_1)=u(i_2)\)이면 \(i_1=i_2\)가 성립해야 하나의 이름이 둘을 동시에 가리키지 않습니다. 반면 같은 정체성의 새 버전은 계속 같은 이름에 대응할 수 있어야 합니다.
프로젝트와 그 안의 출판물처럼 포함 관계가 있는 객체도 별개의 정체성을 가집니다. 집합을 가리키는 이름과 집합의 원소를 가리키는 이름은 대체할 수 없습니다. 관계형 관점에서는 후보키가 다르고, 그래프 관점에서는 서로 다른 종류의 꼭짓점입니다. 상위 객체가 같다는 이유만으로 하위 객체까지 같다고 간주하면 다중 문서를 다루는 순간 모호성이 생깁니다.
동일성을 값 비교가 아니라 명목적 동일성으로 다뤘습니다. 내용이 같아도 서로 다른 문서일 수 있고, 내용이 바뀌어도 같은 문서일 수 있습니다. 이 기준을 세운 뒤에는 편집과 재게시를 반복해도 외부 이름이 흔들리지 않았고, 여러 종류의 문서가 한 작업공간에 공존해도 서로의 공개 역사를 침범하지 않았습니다.
Reference monitor
공개 주소는 누구나 알 수 있으므로 주소를 안다는 사실이 변경 권한을 뜻해서는 안 됩니다. 보안 주체 집합을 \(S\), 객체 집합을 \(O\), 권한 집합을 \(P\)라고 하면 접근 정책은 \(A:S\times O\to2^P\)인 접근 행렬로 표현할 수 있습니다. 읽기, 수정, 공개, 비공개 전환은 서로 다른 권한이며 같은 조건으로 묶을 이유가 없습니다.
모든 민감한 연산은 reference monitor를 통과해야 합니다. 고전적인 조건대로 monitor는 완전 매개되어 우회할 수 없어야 하고, 자신의 정책이 임의로 변조되지 않아야 하며, 충분히 작고 명확해 검증 가능해야 합니다. 권한 검사를 여러 처리 단계에 흩어 놓으면 한 경로에서 누락될 가능성이 커집니다. 반대로 하나의 정책 경계가 모든 상태 변화를 지배하면 시스템의 보안 불변식을 증명하기 쉬워집니다.
검사 순서도 안전성의 일부입니다. 권한 판정 전에 관측 가능한 부작용이 일어나면 최종적으로 요청을 거부하더라도 이미 시스템 상태가 달라졌을 수 있습니다. 따라서 안전한 전이는 \(precondition\Rightarrow effect\)의 순서를 지켜야 하고, 판정을 확정할 수 없는 경우에는 허용 집합보다 거부 집합에 들어가야 합니다. 이것이 fail-closed 원칙입니다.
공개 여부는 정체성의 존재와 다른 보안 상태입니다. 비공개로 바뀌었다고 문서의 역사까지 사라지는 것은 아니고, 존재한다고 해서 누구나 관측할 수 있는 것도 아닙니다. 가시성 격자를 \(private\preceq public\)으로 두면 공개는 정보 흐름의 상승이고 비공개는 외부 관측 경로의 제거입니다. 이 구분을 적용해 게시와 취소, 복구의 권한 경계가 일관되게 유지되도록 완성했습니다.
Relational metadata
공개 문서의 메타데이터는 바이너리 본문보다 작지만 정체성과 검색 가능성을 결정합니다. 이를 하나의 거대한 레코드로만 보면 어떤 값이 무엇에 함수적으로 종속되는지 알기 어렵습니다. 관계 \(R\)에서 \(X\to Y\)라는 함수 종속성이 있다면, 같은 결정자 \(X\)를 가진 두 튜플의 \(Y\)는 같아야 합니다. 이 규칙이 문서, 사용자, 공개 이름과 시간 정보의 관계를 정리하는 기준이 되었습니다.
정규화의 목적은 테이블을 많이 만드는 것이 아니라 갱신 이상을 막는 것입니다. 한 사실이 여러 위치에 반복되면 일부만 바뀌는 순간 모순이 생깁니다. 반대로 항상 함께 읽히는 값을 지나치게 쪼개면 결합 비용과 실패 지점만 늘어납니다. 정체성에 관한 사실, 표현 스냅샷, 큰 자원에 대한 참조를 의미에 따라 구분하고 각 사실이 하나의 권위 있는 위치를 갖게 했습니다.
시간도 하나의 값이 아닙니다. 최초 생성 시각은 문서 역사의 시작이고, 최근 수정 시각은 현재 버전의 신선도를 나타냅니다. 둘을 같은 규칙으로 덮어쓰면 재게시할 때마다 문서의 기원이 바뀝니다. 불변 시간과 가변 시간을 분리하면 정렬, 캐시, 감사 기록이 각자의 의미를 유지할 수 있습니다.
로컬 편집 상태와 공개 상태가 다를 때 무엇을 믿을지도 명확해야 합니다. 여러 복제본이 있는 분산 시스템에서는 모든 사본을 동시에 권위로 삼을 수 없습니다. 공개 여부처럼 외부에 영향을 주는 사실은 하나의 authoritative relation에서 결정하고, 나머지 상태는 그 사실을 빠르게 보여주는 투영으로 취급했습니다. 이 원칙 덕분에 새로고침과 재접속 뒤에도 공개 상태가 모순 없이 복원되었습니다.
Observable shell
공개 문서는 실행 코드가 모두 준비되기 전에도 최소한의 의미를 가져야 합니다. 검색 엔진과 공유 미리보기, 보조 기술은 완성된 대화형 화면과 다른 방식으로 문서를 관측합니다. 따라서 초기 응답은 제목과 설명, 대표성 있는 자원, 정규 주소처럼 문서의 외부 의미를 제공하고, 이후의 실행 환경이 점진적으로 상호작용을 추가해야 합니다.
이를 단조적 향상으로 볼 수 있습니다. 초기 관측 정보 집합을 \(O_0\), 실행 뒤의 집합을 \(O_1\)이라고 하면 \(O_0\subseteq O_1\)이어야 합니다. 기능이 추가되더라도 처음 전달한 제목이나 문서 정체성이 뒤집혀서는 안 됩니다. JavaScript 실행 여부에 따라 서로 다른 문서가 되는 대신, 같은 문서가 더 풍부한 연산을 제공하게 만드는 것입니다.
문자열을 여러 언어 문맥으로 옮길 때는 문맥별 인코딩도 필요합니다. HTML 본문, 속성, URL, 스크립트 데이터는 허용 문법이 서로 다르므로 하나의 escape 함수로 모두 처리할 수 없습니다. 값이 들어갈 목적 언어의 문법을 기준으로 안전한 표현을 만들어야 경계를 넘어온 데이터가 구조 자체로 해석되지 않습니다. 공개 문서의 안전성은 이런 언어 경계의 엄밀함에서도 결정됩니다.
첫 화면의 배경과 기본 기하처럼 빠르게 관측되는 값도 문서 의미의 일부로 보았습니다. 본문이 준비되기 전 잠깐 나타나는 임의의 화면조차 독자에게는 실제 결과입니다. 초기 관측과 최종 관측 사이의 시각적 불연속을 줄이고, 상호작용이 없어도 문서의 정체성과 접근 경로가 남도록 공개 화면을 정리했습니다.
Behavioral equivalence
에디터의 미리보기와 공개 리더가 같다는 말은 코드 문자열이 같다는 뜻이 아닙니다. 두 시스템을 라벨이 붙은 전이계 \(M_1=(S_1,A,\to_1)\), \(M_2=(S_2,A,\to_2)\)로 보면, 같은 사용자 행위에 대해 서로 대응하는 상태로 이동하고 같은 결과를 관측할 수 있어야 합니다. 이것은 동작 동등성의 문제입니다.
두 상태 사이의 관계 \(\mathcal{B}\subseteq S_1\times S_2\)가 있어 한쪽의 전이 \(s_1\xrightarrow{a}s'_1\)마다 다른 쪽에도 \(s_2\xrightarrow{a}s'_2\)가 존재하고 \((s'_1,s'_2)\in\mathcal{B}\)라면 두 시스템은 bisimulation 관계에 있습니다. 페이지 이동, 장 선택, 화면 조건 변화와 테마 전환이 이 관계를 유지하면 내부 환경이 달라도 독자는 같은 문서를 경험합니다.
공개 리더는 편집 연산을 제공하지 않으므로 두 전이계의 연산 집합이 완전히 같을 수는 없습니다. 공개 모드는 편집 전이계에서 읽기 연산만 선택한 부분 대수로 볼 수 있습니다. 삭제된 것은 문서 의미가 아니라 상태를 바꾸는 권한입니다. 관측과 이동에 필요한 연산은 그대로 닫혀 있어야 합니다.
화면을 비슷하게 만드는 두 구현을 유지하는 대신, 같은 의미 함수가 두 환경에서 성립하는지를 기준으로 검수했습니다. 반응형 경계, 페이지 비율, 장 선택과 전환 결과가 모두 대응 관계를 유지했고, 한쪽의 개선이 다른 쪽의 의미를 깨뜨리지 않는 구조로 안정화되었습니다.
Deterministic boot
공개 리더의 부팅은 여러 자원을 동시에 불러오는 일이지만, 결과는 실행 속도의 우연에 좌우되어서는 안 됩니다. 부팅 상태를 \(B_0,B_1,\ldots,B_n\)으로 두면 각 전이는 필요한 선행 조건이 충족되었을 때만 다음 상태로 이동해야 합니다. 독립적으로 준비할 수 있는 작업은 병렬이어도 되지만, 관측 가능한 화면의 확정은 하나의 일관된 상태에서 이루어져야 합니다.
결정론은 모든 사건의 순서를 고정한다는 뜻이 아닙니다. 독립 사건의 순서가 달라도 최종 상태가 같아야 한다는 합류성에 가깝습니다. 두 전이 \(a,b\)가 독립이라면 \(a(b(s))=b(a(s))\)가 성립하고, 의존성이 있는 경우에만 선후 관계를 둡니다. 이 성질을 지키면 네트워크와 장치 성능이 달라도 같은 문서가 만들어집니다.
화면 크기 변화도 연속적인 잡음과 의미 있는 상태 변화를 구분해야 합니다. 임계점 근처에서 작은 변화가 반복되면 두 모드가 계속 왕복하는 채터링이 생길 수 있습니다. 서로 다른 진입·이탈 경계를 두는 hysteresis나 일정 시간의 안정 구간을 사용하는 방식은 이런 불안정을 줄이는 일반적인 제어 이론의 해법입니다.
최종 노출 시점은 상태 기계가 수렴하고 필수 자원의 폐포가 준비된 뒤로 잡았습니다. 동시에 일부 비필수 자원의 지연이 전체 시스템을 영원히 막지 않도록 활성 조건도 유지했습니다. 다양한 네트워크 지연과 화면 전환을 반복해도 첫 장과 읽기 순서, 기하 상태가 같은 결과로 부팅되는 것을 확인했습니다.
Persistent publication
재게시에서 중요한 것은 새 파일의 생성보다 문서 정체성의 지속입니다. 문서 \(i\)의 버전들을 \(v_0,v_1,\ldots,v_n\)이라고 하면 공개 주소는 특정 버전보다 버전 계열 전체를 가리켜야 합니다. 독자는 같은 이름으로 최신 유효 버전을 보고, 시스템은 필요할 때 각 버전의 시간적 관계를 구분할 수 있어야 합니다.
이 구조는 persistent identifier의 원리와 같습니다. 이름은 위치나 바이트 배열의 함수가 아니라 문서 정체성의 함수여야 합니다. 내용이 바뀔 때마다 이름이 변하면 외부 참조가 끊기고, 서로 다른 문서가 같은 이름을 공유하면 참조 무결성이 무너집니다. 안정된 이름과 가변 payload를 분리하면 수정과 외부 인용을 동시에 보존할 수 있습니다.
캐시는 이 시간 모델을 모르면 오래된 관측값을 계속 보여줄 수 있습니다. 논리적 버전 \(v\)를 관측 키에 포함하면 같은 정체성을 유지하면서도 새 상태가 이전 상태와 구분됩니다. 중요한 것은 무조건 캐시를 없애는 것이 아니라, 언제 두 표현을 같은 값으로 볼 수 있는지 동등성 관계를 명확히 하는 일입니다.
흐름형 EPUB과 고정판형 문서, 신규 게시와 같은 주소의 갱신, 필수·선택 자원의 실패, 모바일과 데스크탑, 공개와 비공개 전환, 권한 거부, 오래된 스냅샷의 정규화와 캐시 갱신을 모두 반복 검수했습니다. 편집기와 공개 페이지의 내용, 읽기 순서, 레이아웃 제약과 상호작용이 같은 의미를 유지하는 것을 확인했습니다. 편집한 책을 변환 손실 없이 웹 문서로 공개하는 퍼블리셔 시스템은 완전하게 구현되고 안정화되었습니다.
이전글
목록으로
다음글
저작권 고시
Copyright Notice
본 웹사이트의 모든 디자인 결과물 및 영상에 대한 저작권은 Abstract Cloud에 있으며, 저작권법 및 관련 법령에 의해 보호받습니다. 웹, 영상, 본문, 표지, 내지 디자인을 포함한 모든 콘텐츠는 저작권자의 자산으로, 사전 동의 없이 무단 복제, 배포, 2차 저작물 제작, 온라인 공유 등을 금지합니다. 이를 위반할 시, 저작권법에 따라 민형사상 책임을 질 수 있습니다. 정당한 구매와 저작권 보호는 창작자의 권리를 지키며, 더 나은 작품으로 보답할 힘이 됩니다.
저작권자: Abstract Cloud | 대표자: 배창규(uragen)
© Abstract Cloud. All Rights Reserved.
HOME
FAQ
이용 약관
개인정보 이용방침
help@opkle.app
010-2747-3403
상호 :
추상적 형상 디자인(Abstract cloud) |
대표자 :
배창규
사업자등록번호 :
249-74-00533
통신판매업 신고번호 :
2025-의정부송산-0634
주소 :
경기도 의정부시 부용로 49, 108동 402호
웹의 모든 콘텐츠, 디자인, 소스 코드에 대한
저작권은 Opkle에게 있습니다.