FE 개발자로 일한지 2년정도 되는 요즈음 문득 이런 생각이 들었다
"나 잘하고 있는거 맞나?"
일은 하고 있는데 동료 개발자도 거의 없다시피 작은회사에서 쌓은 시간이라 객관적으로 나를 측정하고 싶었다
그렇게 항해플러스를 시작했다
2주차가 끝나는 지금 항해플러스에 합류한건 참 잘한 선택이었다. 자바스크립트의 본질에 대해 이해하고 배우는 좋은 시간이고 비슷한 연차에서의 나의 위치를 정확히 알 수 있었다. 비슷한 고민을 하는 개발자들 사이에서 과제 뿐 아니라 생각을 교류하는 좋은 환경과 커리큘럼이라고 생각한다. 이런 것들을 나누면서 자연스레 좋은 개발자, 함께 일하고 싶은 개발자가 뭔지 알듯하다.
갓 1년차가 되었을 때부터 항해플러스를 신청할까 말까 고민을 많이했다. 그러다 끝내 신청하지 못했던건 가격적인 측면도 있었지만 '코어 자바스크립트에 대한 것, 아키텍쳐도, TDD도 지금 사용을 안하는데 궂이 해야되나?' 싶었다
그것도 지금은 잘못 생각했다고 느끼는게 코어 자바스크립트도 아키텍쳐도 내가 모르니까 사용을 안했구나 싶다.
물론, React 환경에서 지금 배우고있는 DOM 조작과 class문법 사용 등은 지양되고 있지만, React 라는 프레임워크 기저에는 이런 것들이 다 녹아져있었고 알면 기술이지만 모르면 마법이라는 생활코딩님의 말이 종종 생각나는 시간을 보내고있다.
그래서 요번주에 뭘했냐면
자바스크립트로 React만들기
자바스크립트로 React처럼 화면전환이 가능하게 route를 구현하고 가상돔과 diff 알고리즘을 만들어 변경되는 node만 업데이트해주는게 기본 골자다.
위의 기능을 위해서 아래의 구현이 필요하다
1. 라우팅
자바스크립트에서 기본으로 제공하는 history api를 이용해 페이지를 새로고침 하지 않고 URL 을 변경한다.
여러 메서드들이 있는데 하나씩 알아보자.
- pushState
기본 골자는 이렇다. history.pushState(state, title, url);
State : 브라우저 이동 시 넘겨줄 데이터 (popstate 에서 받아서 원하는 처리를 해줄 수 있음)
Title : 변경할 브라우저 제목 (변경 원치 않으면 null)
Url : 변경할 주소
아래 예시를 보자.
// html
<nav>
<div id="navi">/</div>
<div id="navi">/about</a>
</nav>
document.querySelector("nav").addEventListener("click", (e) => {
if (e.target.id === "navi") {
history.pushState(null, "", e.target.innerText);
}
});
위와 같이 사용하면 새로고침 없이 "/" 와 "/about" url로 변경할 수 있다.
이때 각 링크에 따라 html만 변경해주면 SPA처럼 동작한다.
아래 예시를 보자
// main.js
class Router {
constructor() {
this.routes = {};
}
addRoute(path, handler) {
this.routes[path] = handler;
}
navigateTo(path) {
history.pushState(null, "", path);
this.handleRoute(path);
}
handleRoute(path) {
const handler = this.routes[path];
if (handler) {
handler();
} else {
console.log("404 Not Found");
}
}
}
// router 등록
const router = new Router();
router.addRoute("/", () => renderPage(mainPage()));
router.addRoute("/about", () => renderPage(aboutPage()));
// 페이지 이동 시 router.navigateTo() 호출
document.querySelector("nav").addEventListener("click", (e) => {
if (e.target.id === "navi") {
router.navigateTo(e.target.innerText);
}
});
// URL에 따라 html을 갈아준다
function renderPage(page) {
document.getElementById("app").innerHTML = page;
}
function mainPage() {
return `
<h1>메인 페이지입니다</h1>
`;
}
function aboutPage() {
return `
<h1>About 페이지입니다</h1>
`;
}
요약하면 아래 순서로 진행된다.
1. addRoute 함수로 사용할 route를 등록하고 ("/", "/about")
2. navigateTo함수로 새로고침 없이 url을 변경하고 (history.pushState)
3. 2를통해 url 변경이 일어나면 등록한 route의 콜백함수를 실행해준다
4. 이때 콜백함수는 html을 render 해주는 함수
여기서 아래 코드를 추가하면 뒤로가기 앞으로가기를 통해 변경되는 url을 대응할 수 있다
class Router {
constructor() {
this.routes = {};
// (New!)
window.addEventListener("popstate", this.handlePopState.bind(this));
}
addRoute(path, handler) {
this.routes[path] = handler;
}
navigateTo(path) {
history.pushState(null, "", path);
this.handleRoute(path);
}
// (New!)
handlePopState() {
this.handleRoute(window.location.pathname);
}
handleRoute(path) {
const handler = this.routes[path];
if (handler) {
handler();
} else {
console.log("404 Not Found");
}
}
}
위의 과정을 통해 SPA 처럼 페이지 이동이되게 했는데 이벤트는 어떻게 관리하지?
2. 이벤트 주입 (아키텍쳐를 곁들인)
element가 존재해야(이하 $el) $el에 이벤트를 주입할 수 있다.
그러면 html을 먼저 파싱하고 그 후에 이벤트를 주입해야 되는건데 요 과정에서 아키텍쳐에 대한 중요성을 배웠다
그동안은 react로만 구현해서 몰랐는데 자바스크립트로 구현하자니 코드가 많아지고 관리하기가 힘들었다
(선언형과 명령형의 차이 +exp)
...컴포넌트 기반 구조 설계를 위한 아키텍쳐 구성은 곧 추가하겠습니다!🙌