5가지의 목표를 두고 프로젝트를 시작하였고, 정확히 지켜진건 5번 하나 뿐이다..ㅠㅠ ㅋㅋㅋㅋ
우선 설계가 끝날때까지 키보드에 손을 아예 대지 않았다. 최대한 꼼꼼하게 설계하여 코드를 작성하다가 막히더라도 데이터의 흐름이 잘못되거나, 순환 참조로 인해 무한 루프에 걸리거나, 데이터를 잘못 받아와지는 실수는 하고 싶지 않았기 때문이다(설계에만 도대체 몇 시간을 썼는지 모르겠다 ㅠ).
최대한 루트에서 시작해서 데이터를 하위 컴포넌트로 뿌려주는 식으로 데이터 흐름도를 그렸고, 콜백에 콜백에 콜백에 콜백에... 콜백에.. 콜백 지옥이 발생하지 않도록 데이터와 코드의 흐름을 잘 파악하기 위해 리액트에서 발생하는 PropsDrilling을 최대한 만들지 않기 위해 많은 고민을 했다.
SPA 형태로 프로젝트를 만들기 위해 History API를 사용했으며, 루트 App.js에서 API를 호출하고 하위 App.js에 뿌려주며 각 App.js는 API를 호출하고 뿌려주는 역할을 하고, document를 클릭해 페이지가 변경되면 url이 변경되고 변경된 url의 pathname을 루트의 App.js가 확인하여 다시 데이터를 내려주는 방식이다.
이 부분이 가장 시간이 오래 걸렸던 부분이다. 편집기에 작성한 텍스트에 마크업 문법을 적용하기 위해 contenteditable = true
를 설정한 div 엘리먼트의 innerText를 모두 TextScan 파일내 별도의 함수의 매개변수로 넘겨주어 별도의 함수에서 split으로 구분하고 정규식을 통해 리턴해주는 로직을 작성하였다.
여기서 겪은 난항은 마크업 적용이된 텍스트를 다시 수정하여 마크업을 적용할때가 문제였는데, 이 부분을 해결하기 위해 div가 focuson이 되면 벨로그처럼 마크업 문법이 다시 텍스트에 나타나고 그 위에 수정을 하고 TextScan 파일내 별도의 함수로 다시 보내면 마크업이 적용되게끔 작성하였다.
이때 focuson 이벤트가 한번만 실행되게 해주고싶어 아래와 같이 이벤트 핸들러를 작성하였다.
// 마크업 제거 함수
export const removeMarkup = ($target) => {
$target.addEventListener(
"focusin",
(e) => {
// 중간 코드 생략
},
// 이 부분이 이벤트 핸들러가 한번만 동작하게 해준다.
{ once: true }
);
};
addEventListener의 세번째 인자로 { once: true } 를 적용해주면 이벤트가 한번만 실행이 되는데 이번 프로젝트에서 유용하게 사용했다 ㅎㅎ
노션의 메뉴바를 클릭하여 늘리거나 줄일 수 있는데, 이번 프로젝트에서 직접 적용을 해봤다.
엘리먼트 Resizing은 처음 시도해보았는데, 대충 이런 구조로 작성했다.
총 3개의 엘리먼트 -> left, center, right를 만들고 center 엘리먼트가 mousedown 될 때, 현재 e.clientX의 좌표를 구하고 mousemove 될 때 초기 clientX 값과 이동중인 clientX의 값을 계속 비교하여 크기를 늘리거나 줄이고 mouseup 될 때 등록된 프로퍼티와 이벤트를 제거해주면 메뉴바가 늘어나거나 줄어드는 형식으로 구현했다.
프로젝트를 진행하며 겪었던 어려움과 해결 과정은 추후 포스팅 할 예정입니다 😁