스크랩북 2

FECONF 2022 [A4] 텍스트 에디터? 그게 뭘 만드는 건데?

내용

  • 에디터가 복잡한 동작을 한다는 것을 알려주는 예시

    • 커서, 커서가 움직임으로써 에디터가 사용자에게 어떤 것을 지원해야 하는지 (예를 들어, 현재 커서 아래에 이미지가 있다고 할 때 키보드 아래 방향키를 누르면 이미지에 Focus를 주는 동작)
    • 또한 위의 예에서 선택한 이미지에 이미지 도구 막대를 노출한다던가 같은 동작
    • 어쨌든 개발자가 일일이 처리해야 하는 동작이 상당히 많음. (☁️ 또한 개발자가 처리하는 동작과 함께, 사용자가 예상하는 동작, 브라우저가 지원하는 동작의 세 박자를 모두 고려하여 복잡한 에디터를 구현해야 함)
  • 스마트에디터로 살펴본 에디터의 발전

    • 1세대 : contenteditable 기반 → 문서를 HTML 그대로 저장
    • contenteditable 속성은 div 에 해당 속성을 true로 설정함으로써 사용할 수 있으며 사용자가 직접 DOM에 글을 입력할 수 있게 한다.
    • 단점 : 멀티 디바이스 대응이 어렵다

      • ☁️ 이 말은 브라우저마다 동작이 다르게 된다는 뜻인데, 예를 들어 safari에서 contentEditable에 대응하려면 user-select: text를 넣어줘야 하고, chrome의 경우 user-modify가 들어간다.
      • ☁️ 또한 HTML 그대로 저장되기 때문에 style 속성까지 함께 복사 붙여넣기가 되는 경우가 있음. 사실 이 경우는 syntax highlighting 지원안하고 코드 영역 지원안하는 경우 (한글 파일 보고서 쓸 때)에 유용하게 사용할 수 있을 것 같기도 하다. 실제로 color scripterpygments 와 같은 서비스가 있기도 하고..
    • 1.5세대 : 문서를 JSON으로 모델링(저장할 때도 json으로 변환해서 저장). 또한 문서 모델링을 용이하게 지원하기 위하여 편집을 블록별 편집으로 제한함
    • 노드 마다 다른 스타일 (☁️ 노션에 한 블럭 단위로 스타일 지정하는 것과 비슷하게 생각하면 될 듯)
    • json으로 저장되어 있으므로 해당 부분을 렌더링하면 되니까 멀티 디바이스 대응에 유연함
    • 단점 : selection을 확장할 수 없음 (☁️ 네이버 블로그를 했을 때, 개인적으로 가장 불편했었다. 당시에 주로 pc 환경에서 글을 작성했기 때문에 넓은 화면에서 내가 원하는 레이아웃 배치나 글자 아트 같은걸 하고 싶었으나 selection이 하나만 되서 항상 이전 버전으로 되돌려서 글을 썼던 기억이 있다.)
    • 2세대 : 가상 커서 + input buffer
    • 블록 선택도 가상 커서로 일어나게 함. 즉 블록 영역을 html element로 직접 화면에 그림
    • input buffer에 사용자 입력이 들어가고 그 다음에 렌더링 된다. 즉, 사용자가 보기엔 textarea 영역에 글이 작성되는 것 처럼 보이지만 실제로는 사용자가 보이지 않는 곳의 input buffer에 입력이 들어가고 이 후에 본문에 렌더링 처럼 보이게 되는 것
    • 단점 : 브라우저 네이티브 활용이 어렵다. (☁️ 브라우저의 모든 동작을 개발자에게 위임한 것과 마찬가지 이므로 모두 구현해야하는 것과 마찬가지인 방법. 이는 에디터가 돌아가는 환경이 브라우저 위에서 돌아간다는 것의 특수성에서 기인한다.)
    • 새로운 에디터 개발기
    • 사용한 기술 스택 : React, MobX, contenteditable
    • 목표 : 기존 에디터의 사용성 유지 + 브라우저 네이티브 활용

      • 특히나 IE가 사라지면서 브라우저의 지원 범위가 축소되었기 때문에 대응해야 할 브라우저가 줄어들었다.
    • 겪었던 문제점

      • Reactcontenteditable 의 충돌 : React의 경우, State 업데이트에 따라 vDOM을 만든 후, vDOM과 DOM을 비교하여 DOM을 변경하는 방식을 사용하나 contenteditable의 경우 사용자가 입력하면 즉시 DOM이 변경됨 ☁️ 즉, 서로 DOM을 업데이트하는 싱크가 맞지 않다는 의미 (사이클이 맞지 않다)
    • 해결 방안 : 직접 애플리케이션의 흐름을 제어하기로 함

      • DOM과 vDOM 싱크가 깨질 만한 상황을 나누어 관리
      • DOM에 의해 Store가 변경되는 상황을 Upstream으로 정의하고 (☁️ contenteditable 을 통해서 텍스트에디터 내부의 값이 변경, 앞에서 말했듯이 contenteditable은 DOM을 변경시키는 것이므로 React 반응을 임시 중단함), Store에 따라서 DOM이 변경되는 상황(☁️ React의 렌더링 동작을 생각하면 됨.) 을 DownStream으로 정의
      • ☁️ 텍스트 에디터에서 DOM의 구조가 바뀔 수 있는 동작을 따로 처리하는 것으로 생각한다. 예를 들어서 엔터를 친다는 것은 p태그가 추가 되는 것을 생각할 수 있다.

느낀점

  • 예전에 데브코스에서 만들었던 프로젝트 중 가장 아쉬우면서 다시 만들고 싶은 프로젝트가 Vanilla JavaScript를 이용한 Notion 클론 프로젝트였다. 특히나 최근에 관심을 가지고 있는 주제 중 하나가 “프론트엔드 기술을 통하여 애플리케이션 처럼 동작하는 무언가를 만들기” 였기 때문에 해당 발표가 정말 궁금하였다.
  • React 를 사용하면서 (특히나 Next.js와 결합할 때) React의 싱크와 개발자가 조작하는 DOM의 싱크가 맞지 않아 에러가 일어나는 일이 비일비재하였다. 특히나 DOM 요소의 동작에 의하여 DOM이 조작될 때, React 의 vDOM과 즉시 싱크로율이 맞지 않아 문제점을 겪은 점이 있던거 같은데 (희미한 기억이지만…) 이를 해결하기 위해서 React 동작과 DOM의 동작을 분리해서 각자의 역할에 따라 동작을 처리한 것이 인상적이였다.

    • 특히, 어떤 라이브러리를 사용한다고 무조건 React에 맞춰서 처리하지 않는 부분이 인상적이였다.
  • 또한, 텍스트 에디터를 구현하는데 생각하지 못했던 점은 기본적으로 브라우저 위에서 동작하기 때문에 텍스트 에디터의 동작과 함께 브라우저의 동작을 함께 생각해야한다는 것이였다. 가상 커서가 완벽한 솔루션이 될 수 없었던 이유를 생각해보자면, 이를 이용하는 vsCode의 경우 (거칠게 말하자면) OS에서 돌아가니깐 OS에서 지원되는 동작 + 개발자의 처리 라고 생각할 수 있지만 스마트에디터의 경우 OS + 브라우저의 동작 + 개발자의 처리 이기 때문에 어떻게 보면 중간에 계층이 하나 더 들어간 것이다.

FECONF 2022 [A5] Edge Computing으로 가져올 웹 개발의 변화

내용

  • 엣지 컴퓨팅 : 컴퓨팅 작업을 가능한 엔드유저와 가까운 곳에서 수행하는 것

    • 🌧 예를 들어서, Next.js의 SSG 를 생각해보면, 정적 페이지를 html을 만들고 사용자와 가까운 일종의 엣지 서버라고 볼 수 있는 CDN을 제공하는 것
    • 🌧 사용자와 물리적인 거리가 가까운 곳에서 작업을 처리하는 것이라고 생각할 수 있다. 즉, 사용자와 기계 사이의 (물리적인) 거리를 줄임으로써 이득을 볼 수 있는 부분은 엣지 컴퓨팅으로 이득을 볼 수 있는 부분이라고 생각할 수 있을 것 같다.
    • 🌧 프론트엔드와 엣지 컴퓨팅이 밀접한 관계를 왜 가지느냐… 결론은 서버 앞에 ‘엣지’를 두고 무언가의 작업을 해내는 것일 텐데 그렇다면 엣지를 ‘어디에’ 두느냐, 엣지에서 ‘무엇을’ 하느냐 에 대한 제어를 프론트엔드가 할 수 있는 것으로 보인다.
  • 엣지 컴퓨팅은 점점 복잡한 웹과 애플리케이션의 복잡성(문제)를 해결하기 위하여 또 다른 추상화 계층을 부여한 것.

    • 서버 / 네트워크 / 애플리케이션의 관심사를 서로 분리하면서 서로의 관점은 자기 자신만 집중할 수 있게끔 한다.

느낀점

  • 개인적으로는 네트워크 상에 중간에 프록시를 두어 프록시가 서버의 앞단에서 여러가지 기능을 수행하는 것과 비슷한 느낌이라고 생각했다.
  • 이러한 관점에서 생각해본다면.. 프론트엔드 단에서 중간에 네트워크를 만져서 성능을 최적화하거나 (react query, swr과 같은 라이브러리들) 혹은 next.js의 api를 “애플리케이션만을 위한 서버” 처럼 이용하는 기술들 역시 어쩌면 엣지 컴퓨팅의 일부라고 생각할 수 있고, 네트워크 영역이 애플리케이션 영역이라고 말씀하시는 것도 이러한 맥락에서 (나만의 생각) 이해할 수 있다.

어쨌든 이벤트 루프는 무엇입니까? (원제: What the heck is the event loop anyway?)

  • 브라우저에서 웹 애플리케이션의 동작 (브라우저에서의 자바스크립트 런타임) : JS 엔진 + WebAPI (브라우저에서 제공) + event loop, callback queue
  • 자바스크립트는 싱글 스레드 프로그래밍 언어

    • 싱글 스레드 런타임을 가지고
    • 한 번에 하나의 single call stack을 가짐 ⇒ 따라서, 하나의 자바스크립트 프로그램은 동시에 하나의 코드만 실행할 수 있다.
  • 간단하게 자바스크립트 프로그램의 실행은 다음과 같이 표현할 수 있다.

    • 코드가 실행되면 먼저 전역 실행 컨텍스트가 스택에 푸시되고, 코드가 실행되면서 함수가 실행될 때 해당 함수가 스택에 푸시되고.. 함수들이 스택에서 pop되면서 함수가 실행되는 형식
    • 에러 콘솔에서도 이러한 실행 방식을 확인할 수 있다. (에러 콘솔에서 나타나는 함수들은 일종의 stack tree라고 생각할 수 있다.)
  • Blocking 현상

    • 스택에 실행 시간이 느린 동작이 남아있어서, 이 동작이 실행되기 전까지 다른 함수의 실행을 blocking 하는 것
    • 이러한 현상이 네트워크 요청이나, 이미지 프로세싱 과 같은 동작에서 일어나므로 이 작업들을 비동기 콜백을 이용하여 해결하고자 하였다. (즉 어떤 코드를 실행하면 콜백을 받고, 나중에 실행하는 것)
    • ☁️ 이러한 아이디어는 CPU가 interrupt를 처리하는 루틴과 비슷하다. CPU가 intterupt 관련 작업을 수행하면, 해당 device에게 요청만하고 자신의 작업을 실행하다가 intterupt service routine이 완료되면 해당 작업물을 사용한다. 비슷하게 브라우저에서도 blocking 이 일어나는 작업이 발생하면, 자바스크립트 코드는 이를 브라우저에게 위임하고 자바스크립트는 자신의 코드를 실행하다가 blocking되는 작업이 끝나면 해당 작업의 콜백이 태스크 큐에 들어가게 된다.
  • 브라우저는 Web API와 같은 것을 지원하고, 이는 자바스크립트에서 호출할 수 있는 스레드를 효과적으로 지원한다.

    • setTimeout과 같은 비동기 함수는 자바스크립트 엔진에서 지원하는 함수가 아니라 JavaScript가 실행되는 런타임 환경에 존재하는 별도의 API이다.
    • 이러한 비동기 함수에 넘겨진 콜백은 비동기 작업이 끝난 후, 태스크 큐에 저장되었다가 이벤트 루프에 의하여 콜 스택이 비게 되면 스택으로 이동하여 함수가 실행된다.
  • 따라서 이벤트 루프는 콜 스택과 태스크 큐를 주시하다가 콜 스택이 비어있으면 큐의 가장 앞에 있는 콜백을 스택에 쌓아 효과적으로 실행할 수 있게 해주는 역할을 한다.
  • 비동기 콜백의 활용

    • 브라우저는 자바스크립트 코드에 의해 제약을 받는다. 즉 브라우저에서는 기본적으로 화면을 그려내는 (repaint) 작업을 일정 주기로 실행한다.
    • 하지만 콜스택에 다른 함수로 차있다면, 해당 작업에 제약을 받게 된다. 따라서 느린 자바스크립트 코드를 사용하게 된다면 렌더링에 영향을 줄 수 있다는 뜻이다.
    • 이를 해결하기 위해 렌더에게 각 함수 실행 요소 중간에 렌더가 끼어들 수 있는 기회를 준다. 태스크 큐를 async를 활용해서 쌓게 한다면 stack에 해당 작업이 들어가기 전의 지연 시간동안, 렌더 일어날 수 있다. (스크롤을 할 때 마다 큐에 엄청나게 많은 콜백을 쌓는다.)
    • ☁️ 이러한 기법은 흔히 스크롤 이벤트 처럼 아주 자주 일어나는 이벤트를 처리하는 기법으로 사용할 수 있다. 스크롤 이벤트에 스로톨링과 같은 기법을 사용하여 해당 이벤트가 렌더가 끼어들 틈이 있도록 발생하게 만들고 스로톨링을 하는 동안에 렌더가 일어나도록 하여 브라우저 렌더링을 최적화 한다.

Written by@AllSilver
철학적인 개발자를 꿈꿉니다.

GitHub