배포 링크
프로젝트 개요
- 기간 : 2021.08.29 ~ 2021.09.05
- 목표 : vanilla JS를 컴포넌트 방식으로 노션 클론 구현하기
- 내용 : 노션처럼 글 작성, 수정, 삭제를 할 수 있는 온라인 에디터 사이트입니다.
- 프로젝트 진행 시 문제점
- 유지보수 문제 - 노션이 생각보다 복잡한 UI로 이루어져 있었고, html에 태그를 작성하여 개발하는 환경이 아닌 오로지 JS로만 태그들을 생성하고 스타일링 해야하는 상황이기 때문에 복잡한 UI일 수록, 컴포넌트 코드의 길이가 길어지고 추후 유지보수의 문제가 생길 것 같다는 생각이 들었습니다.
- 컴포넌트 세분화 문제 - 컴포넌트를 너무 세분화를 시켜서 컴포넌트 갯수와 관계없이 이벤트를 계속 위로 올리는 형태의 구조가 되어 버렸습니다. 이러한 구조를 비효율적이라 생각을 했고 프로젝트에 잘못 접근했다는 생각이 들어 현재 React에서는 어떻게 관리하고 있는지 찾아보게 되었습니다.
- 프로젝트 문제점 해결 방법
- CSS도 고려하여 견고하게 설계 - 부트스트랩의 CSS명과 태그들의 구조들을 참고하여 컴포넌트들의 구조에 대한 큰 틀을 기획했습니다.
- 컴포넌트의 역할 구체화 - 각 컴포넌트의 역할과 구조를 분명히 정의함과 동시에 클래스 명까지 반영된 프로젝트의 초안을 작성했습니다.
- Vuex와 Event Bus 개념을 차용 - 여러군데에서 이벤트가 발생되기 때문에
store
를 이용해서 한 군데에서 이벤트와 로직을 관리하면 좋겠다 생각하여 해당 개념을 차용하였습니다.
- 느낀 점 및 배운 점 : 컴포넌트 방식의 바닐라JS로는 처음 프로젝트를 진행해보았는데
Vuex
나Eventbus
와 같은 개념들을 차용하여 직접 구현했다는 것이 너무 신기했고 많이 성장했다는 것이 느껴지는 프로젝트였습니다!
프로젝트 사용 기술
프로젝트 설명

데이터 흐름
emit
하위 컴포넌트에서 이벤트가 발생합니다. ( Child → Store)
on
Store에서 이벤트를 감지합니다. ( Store ← Child)
dispatch
gettersStore를 이용하여 해당하는 로직을 실행한 뒤, 결과가 반영된 데이터를 가져옵니다. (Store)
commit
변경된 데이터와 렌더링이 필요한 내용을 담아 App 컴포넌트에 전달합니다. ( Store → App)- APP 컴포넌트의 데이터는
commit
으로만 변경이 가능합니다.
- 비동기 통신 이후 처리될 렌더링관련 로직은
settesrElement
에서 실행됩니다.
- Store에서 전달받은 내용으로 APP 컴포넌트에서
state
와needRender(렌더링이 필요한 컴포넌트)
하위 컴포넌트로 전달합니다. (App → Child)
state
는 모두 업데이트되지만needRender
에 의해 필요한 부분만 다시 렌더링이 됩니다. (App → Child)
디렉토리 구조와 역할
main.js
: root에 App을 생성
App.js
: 최상위 컴포넌트- route 처리
- Store에서 데이터(nextState, needRender)를 받은 뒤, 하위 컴포넌트들에게 전달
api
: api관련 js 파일config
: api기본 설정 파일notion
: notion api 파일
assets
: style에 필요한 요소css
: css관련 파일 (index, reset, fontello)font
: 사용된 font (openSans, fontello)images
: 페이지 내 이미지 (index, 404)
components
: 페이지 내 하위 컴포넌트modal
Modal.js
: Modal 하위 요소 생성, 동기적인 UI 로직 실행 → Store에 이벤트 emitModalBody.js
: Modal의 Title,Content를 렌더링ModalHeader.js
: Modal 상단의 페이지로 열기, x 버튼 렌더링posts
PostsPage.js
: Posts 하위 요소 생성, 동기적인 UI 로직 실행 → Store에 이벤트 emitPostsPageBody.js
: document 렌더링PostsPageNoData.js
: index 렌더링sidebar
Sidebar.js
: Sidebar 하위 요소 생성, 동기적인 UI 로직 실행 → Store에 이벤트 emitSidebarHeader.js
: notion 타이틀 렌더링SidebarBody.js
: document 트리(navlist) 렌더링SidebarFooter.js
: 새 페이지 버튼 렌더링
pages
: 페이지 컴포넌트MainPage.js
: 하위 컴포넌트 (Sidebar, posts, modal)들을 가지고 있는 컴포넌트NotFoundPage.js
: 404 Error 페이지 컴포넌트
store
: App 컴포넌트 상태 저장소index.js
APP
컴포넌트의 상태 변경 (commit)- 하위 컴포넌트의 이벤트 감지 후 비동기 작업 진행 (dispatch)
gettersLi.js
: openedLi의 데이터를 가공하여 반환gettersState.js
: state의 데이터를 가공하여 반환settersElement.js
: 가공된 state를 이용하여 비동기적인 UI 로직 실행
utils
: 유틸 함수emitter.js
: on과 emit으로 이벤트를 관리- on : 이벤트를 바인딩 (감지)
- emit: 이벤트를 실행
render.js
: 렌더링에 필요한 함수 (Ex. 태그의 스타일, 컨텐츠 변경 등)selector.js
: 전역으로 사용되는 element 선택관련 함수templates.js
: 컨텐츠 없는 template 태그를 생성storage.js
: 스토리지 get, set 함수valid.js
: getters의 valid를 체크