Giter Site home page Giter Site logo

serbi2012 / web-collage-backend Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 194 KB

웹페이지의 HTML DOM요소를 가져와 사용자가 원하는 형식으로 재구성할 수 있는 스크랩 크롬 익스텐션입니다.

JavaScript 100.00%
javascript nodejs

web-collage-backend's Introduction

Web Collage

웹페이지의 HTML DOM요소를 가져와 사용자가 원하는 형식으로 재구성할 수 있는 스크랩 크롬 익스텐션입니다.

Deploy(Chrome Web Store) : Web Collage



🗄 레포지토리 링크



❗️ 구현하며 염두해둔 부분

높은 가독성

해당 프로젝트의 첫 시작은 공부를 하며 리서치해 보던 공식 문서였다. 프로그래밍을 공부하기 위해 MDN, Jest, Redux 등 다양한 공식 문서를 찾아보는 일이 많았다. React처럼 필요한 정보만 직관성 있게 배치된 공식 문서가 있는 반면 여러 정보가 혼잡하게 배치되어 가독성이 떨어지는 공식 문서들도 있다. 이러한 웹페이지들에서 내가 필요한 정보만을 골라서 재구성할 수 있다면? 그리고 그렇게 재구성한 페이지를 저장하거나 다른 사람과 공유할 수 있다면 얼마나 유용할까? 하는 생각에서 본 프로젝트는 출발하였다.

때문에 본 프로젝트에서 가장 중요한 특징은 사용자가 원하는 형식으로 재구성하여 가독성을 높일 수 있어야 한다는 것이었다. 가독성을 높이기 위해서는 불필요한 정보를 제외하고 사용자가 원하는 정보만을 선택할 수 있어야 했다. 본 프로젝트에서 사용자는 Web Window를 통해 본인이 설정한 URL의 웹페이지를 볼 수 있다. 그리고 마우스를 올림으로써 본인이 드래그하면 어떠한 요소를 가져올 수 있을지 직관적으로 확인할 수 있도록 하이라이트 기능을 추가하였다. 이를 통해 사용자는 본인이 원하는 요소를 직관적으로 파악하여 가져올 수 있다. 사용자는 이렇게 Scrap 함으로써 불필요한 요소를 제외하고 본인이 원하는 HTML DOM 요소만을 가져올 수 있다. 그렇게 가져온 HTML DOM 요소는 사용자가 원하는 형식으로 배치할 수 있다. 복잡한 배경 이미지, 사이드바, 헤더를 제거하고 본문의 내용에 집중할 수 있게 재구성함으로써 사용자는 보다 가독성이 높아진 문서를 얻을 수 있다.

문서에 따라서는 혹은 개인의 취향에 따라서 흰색 배경에 검은색 글씨가 오히려 가독성을 해치는 경우가 있다. 밝은 배경에 눈이 쉽게 피로해지거나 이미지의 색상이 밝은 색이 많은 경우에 그러하다. 때문에 문서의 색상 테마를 변경하는 기능을 추가하였다. 이를 통해 사용자는 소위 다크 모드로 문서를 보거나 다양한 색상으로 문서를 볼 수 있게 되었다.



직관적인 UX

본 프로젝트는 일종의 편집기라고 볼 수 있다. 때문에 사용자가 큰 불편함 없이 본인이 생각한 대로 문서를 편집할 수 있어야 한다고 생각했다. 때문에 사용자가 직관적으로 이해할 수 있는 UX를 구성하는 것을 염두에 두었다.

Mac 환경에서는 시스템적으로 웹브라우저의 이미지를 드래그했을 때 해당 이미지를 복사하는 기능이 실행된다. 하지만 이 기능은 웹페이지에 구현된 여러 드래그 앤 드롭 이벤트의 실행을 막고 있었다. 본 프로젝트에서도 이미지에 상호작용하는 드래그 이벤트가 Mac의 이미지 드래그 이벤트에 덮어씌워져 실행되지 못하는 이슈가 있었다. 이러한 이슈는 사용자 경험에 큰 지장을 준다고 판단하였고 이미지를 Mousedown 하였을 때 이미지가 마우스 커서에 살짝 아래에 위치하도록 하여 Mac의 이미지 드래그 이벤트를 막았다.

또한 사용자가 가져온 HTML DOM 요소를 직관적으로 수정할 수 있도록 Edit Mode를 구현하였다. 본래 기획했던 Edit Mode는 별도의 input을 통해 선택한 HTML DOM 요소의 내용을 수정하는 것이었다. 하지만 이런 방식은 사용자가 복잡하게 느껴질 수 있다고 생각했다. 수정을 원하는 부분을 사용자가 해당 HTML DOM 요소에서 직접 지정하고 그 위치에서 바로 수정하는 것이 더욱 직관적인 UX라고 판단하였다. 때문에 ContentEditable 속성을 통해 직관적인 내용 수정이 가능하도록 구현하였다.

사용자가 어떠한 요소를 선택하고 그 요소를 가져오는 Scrap 기능에서 중요한 것은 사용자가 어떠한 요소를 선택하고 있는가를 직관적으로 알 수 있는 것이라 생각했다. 때문에 사용자가 HTML DOM 요소에 마우스를 올리면 해당 요소를 표현하는 테두리가 보이는 하이라이트 기능을 추가하였다. 이 기능을 통해 사용자는 현재 어떤 요소를 선택하고 있고 해당 요소를 어디에 놓을 수 있는지 직관적으로 파악할 수 있을 것이라 생각했다.



Box & Block 구조

본 프로젝트는 사용자가 시각적으로 HTML DOM을 직접 구성해나가는 Userflow를 가진다. HTML을 구성하는 과정에서 중요한 것은 부모와 자식 관계를 명확히 하는 것이라 생각했다. 때문에 사용자는 자신이 현재 어떠한 요소가 부모이고 어떠한 요소가 자식인지 직관적으로 이해할 수 있어야 한다고 판단했다. 이를 위해서 Box & Block 구조를 구현하였다.

Block은 하나하나의 개별 요소이며, Box는 그러한 Block을 감싸는 바구니와 같은 역할을 한다. Box는 또 다른 Box에 속할 수 있다. Box와 Block을 구분하는 가장 명확한 기준은 회색의 테두리이다. 테두리가 있다면 그것은 Box이고 없다면 Block이다. 이러한 Box & Block 구조를 통해 사용자가 어떠한 요소를 감쌀 때는 Box를 사용하고 개별적인 요소만을 나열하고 싶다면 Block으로만 구성한다는 것을 직관적으로 이해할 수 있도록 하고 싶었다.

이러한 Box & Block 구조를 통해서 사용자는 Box 안의 요소를 자유자재로 정렬할 수 있게 되었다. 하나의 Box 안에 어떠한 요소가 있는지 직관적으로 파악할 수 있기 때문에 이를 가로 정렬, 세로 정렬 시 어떠한 형태가 될 것인지 예측이 쉽게 가능해졌다.



🎥 기능 시연 영상

Scrap
Scrap.mov
Select Mode
Select.Mode.mov
Edit Mode
Edit.Mode.mov
Box Mode
Box.Mode.mov
Drawing Mode
Drawing.Mode.mov
Share Mode
Share.Mode.mov
Save Mode
Save.Mode.mov
Theme Mode
Theme.Mode.mov


💡 핵심 구현 사항

Web Window

Web Window는 사용자가 지정한 url에 해당하는 웹페이지를 보여주는 창이다. 사용자가 실제로 사용하는 웹페이지와 동일한 사용자 경험을 제공하기 위해서는 원본 웹페이지와 유사한 모습이어야 했다. 그리고 구현된 웹페이지에서 Dom 요소를 가져올 수 있어야 했다.

처음 선택한 구현 방법은 iframe 이었다. iframe의 src 속성에 사용자가 지정한 URL을 추가하여 해당 웹페이지를 구현하는 것이었다. 하지만 google, naver 등 x-frame-options이 허용되지 않는 사이트는 접근이 불가능한 이슈가 있었다. 하지만 본 프로젝트가 Chrome Extension이라는 특성을 살려 chrome.webRequest라는 Chrome API를 통하여 x-frame-options을 우회하는 방법으로 해당 이슈를 해결했었다. 하지만 이러한 방법에는 큰 문제가 있었다. 바로 XSS를 비롯한 보안 이슈였다. iframe은 악의적인 사용자가 치명적인 플러그인 실행, 사용자의 클릭, 키 입력 도용 등을 유발할 수 있다. 이러한 보안적인 이유의 연장선상으로 cross-domain 간의 iframe DOM 접근 또한 차단되어 있었다.

때문에 해당 웹페이지의 HTMLstring을 가져와 직접 구현하는 방향으로 선회하였다. 사용자가 지정한 URL을 axios를 통해 GET 요청을 하여 HTMLstring을 가져왔다. 그리고 해당 HTMLstring을 dangerouslySetInnerHTML을 통해 렌더링 하였다. 하지만 이 경우 Image, Video, Script, Link 등의 리소스를 제대로 불러오지 못하는 이슈가 있었다. 원인은 해당 리소스들의 경로가 상대 경로로 구성되었기 때문이었다. 때문에 cheerio를 통하여 HTMLstring 내에 상대 경로들을 source domain을 통한 절대 경로로 바꾸어주었다. 그 결과 정상적으로 Web Window가 구현이 되었다.



Dom 요소 드래그 앤 드랍

React 환경에서 드래그 앤 드롭을 구현하고 싶다면 다양한 방법이 있다. 그중 가장 편리하고 빠른 방법은 react-beautiful-dnd과 같은 라이브러리를 사용하는 방법이다. 하지만 단순히 기능 구연만을 하는 것이 아니라 그 기능이 어떠한 원리로 구성되어 있는지를 배워가는 것이 더 가치 있다고 판단하여 드래그 앤 드롭을 라이브러리 없이 직접 구현하기로 결정하였다.

드래그 앤 드롭은 크게 3가지의 단계로 나뉜다. mousedown, mousemove, mouseup 이벤트가 발생할 때이다.

mousedown이 발생하면 마우스 위치에 있는 요소 즉, event.target을 가져온다. 그리고 현재 드래그 중임을 나타내는 dragging 변수를 ture로 바꾼다.

mousemove가 발생하면 해당 요소의 top, left 속성을 마우스의 위치 clientY, X와 동기화시킨다.

mouseup 이벤트가 발생하면 현재 마우스가 위치한 Element에 드래그한 DOM 요소를 넣는다.

하지만 드래그 앤 드롭이 완료되면 Web Window에 있는 요소가 사라지는 현상이 발생했다. 원인은 insertAdjacentElement가 실행되면 2번째 인자에 해당하는 노드는 사라지기 때문이었다. 때문에 cloneNode(true)를 사용하여 해당 노드를 깊은 복사한 노드를 insertAdjacentElement 하도록 로직을 수정하여 해결했다.



ContentEditable

Edit Mode 구현에서 가장 중요한 점은 사용자가 수정을 할 때 해당 태그에 직접 입력 및 수정할 수 있어야 한다는 것이었다. 그리고 그 과정에서 해당 DOM 요소의 style 속성 또한 유지되어야 했다.

처음 선택한 구현 방법은 사용자가 선택한 요소를 innerText를 통해 수정하는 방법이었다. 사용자가 선택한 요소의 Text를 숨겨진 input을 통해 수정하는 방법이었다. 하지만 해당 방법으로 구현 시 커서의 구현이 어려웠다. 그리고 Edit Mode에서만 수정이 가능하도록 해당 input에 focus를 강제하는 로직 구현에도 난항이 계속되었다.

관련 레퍼런스를 리서치 중 ContentEditable이라는 속성을 발견하였다. ContentEditable 속성은 HTML 요소를 input이나 textarea처럼 텍스트를 작성하고 수정할 수 있는 상태로 만들어준다. ContentEditable의 이점은 단순히 텍스트를 추가, 제거하는 것만이 아니라 Bold, Underline 등 텍스트 중 일부분의 요소만 스타일을 변경하는 것이 가능하다는 것이다. 해당 속성을 적용함으로써 사용자가 Edit Mode 적용 시 텍스트 에디터를 사용하는듯한 사용자 경험을 제공할 수 있었다.



⚙️ 셋업 설명

Frontend

  1. 해당 Repository를 git clone을 한다.

  2. 환견변수 파일(.env)을 생성하고 아래와 같은 형식으로 입력한다.

    PORT=PORT
    SERVER_ADDRESS=SERVER_ADDRESS
  3. 해당 프로젝트 폴더 내에서 아래의 명령어를 실행한다.

    $ yarn install
    $ npm start

Backend

  1. 해당 Repository를 git clone을 한다.

  2. 환경변수 파일(.env)을 생성하고 아래와 같은 형식으로 입력한다.

    MONGODB_URL=MONGODB_URL
  3. 해당 프로젝트 폴더 내에서 아래의 명령어를 실행한다.

    $ npm install
    $ npm run dev


🛠 기술 스택

Frontend

  • React
  • Canvas
  • Socket io(Client)
  • Redux-Toolkit
  • Axios
  • Cheerio

Backend

  • Node.js
  • Express
  • MongoDB
  • Mongoose
  • Socket io(Server)

Depoly

  • Chrome Web Store (Frontend)
  • AWS Elastic Beanstalk (Backend)



🗓 프로젝트 기간

2022년 11월 7일 ~ 11월 27일

  • 11월 7일 ~ 11월 12일 : 아이디어 기획, 기술 검증 및 구현 방법 리서치, 목업 작성, 칸반 작성
  • 11월 13일 ~ 11월 27일 : 개발 진행, 배포, 테스트 작성



web-collage-backend's People

Contributors

serbi2012 avatar

Stargazers

공재혁 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.