이번에는 한 화면 내에서 페이지가 전환 되는 것 처럼 보이게 만들어보려고 한다. (SPA) 이전까지의 코드에서는 appendChild
로 삽입하는 코드만 있었는데 한 화면 내에서 화면전환이 일어나게 보이려면 원래 있던 콘텐츠를 새로운 콘텐츠로 overWrite 해줘야한다. 라우터를 만드는 단계흐름을 살펴보자.
container.innerHTML
에 새롭게 덮여씌여 지는 구조를 만들어 준다. 추가적으로, 코드를 작성하는 사람이 직관적으로 알아 볼 수 있도록 creatElement 를 이용해 구조를 만드는 것이 아니라 문자열을 사용해서 구조를 수정 해주었다.
const newsList = [];
newsList.push('<ul>');
for(let i = 0; i < 10; i++) {
newsList.push(`
<li>
<a href="#${newsFeed[i].id}">
${newsFeed[i].title} (${newsFeed[i].comments_count})
</a>
</li>
`);
}
newsList.push('</ul>');
container.innerHTML = newsList.join('');
문자열을 사용해서 만들 때 위와 같이 ul 태그
에 li 태그
를 반복해서 넣어야 하는 구조라면 하드코딩으로 하게 되면 비효율적이 되게 된다. 그래서 반복문을 사용해야 하는데 이때 자주 사용하는 것이 배열구조를 많이 사용한다고 한다.
- 빈 배열을 하나 만들고
<ul>
을 넣는다.- 그리고 반복문으로
li
구조를 만들어서 배열에push
한다.- 마지막에
</ul>
를push
한다.- 그리고 DOM 에 그려 줄 때에는 배열에 담긴 요소들을 하나로 합쳐서 그려줘야 한다.
join
을 사용하게 되는데 이때 기본적으로 합칠 때,
로 합쳐지게 되는데,
는 필요없으니 빈값을 넣어준다.
window.addEventListener('hashchange', function() {
const id = location.hash.substr(1);
const newsContent = getData(CONTENT_URL.replace('@id', id))
container.innerHTML = `
<h1>${newsContent.title}</h1>
<div>
<a href="#">목록으로</a>
</div>
`;
});
가장 간단한 게시판 구조를 생각해보자. 게시글 목록이 나오고, 사용자가 게시글을 클릭하면 상세 게시글을 보게 된다. 그리고 뒤로 돌아가기를 눌렀을 때 다시 목록화면이 나와야 한다.
이렇게 화면을 왔다갔다 할 수 있게 중계(전환)하는 것을 라우터 라고 한다. 라우터를 만들기 위해서는 하나로 묶여 있는 코드 즉, 함수를 실행시켜야 하는데 현재의 코드는 함수로 묶여 있는 코드가 아니다. 그래서 기능별로 함수로 분리를 시키자.
함수는 기능을 알아 볼 수 있도록 직관적으로 작성하는 것이 좋다.
function newsFeed() {
const newsFeed = getData(NEWS_URL);
const newsList = [];
newsList.push('<ul>');
for(let i = 0; i < 10; i++) {
newsList.push(`
<li>
<a href="#${newsFeed[i].id}">
${newsFeed[i].title} (${newsFeed[i].comments_count})
</a>
</li>
`);
}
newsList.push('</ul>');
container.innerHTML = newsList.join('');
}
상세페이지 피드는 이벤트 핸들러에 묶여 있었다. 그래서 함수로 만들고 따로 분리를 시켜 주었다.
function newsDetail() {
const id = location.hash.substr(1);
const newsContent = getData(CONTENT_URL.replace('@id', id))
container.innerHTML = `
<h1>${newsContent.title}</h1>
<div>
<a href="#">목록으로</a>
</div>
`;
}
window.addEventListener('hashchange', newsDetail);
이제 화면 전환을 구현해보자.
function router() {
const routePath = location.hash;
if (routePath === '') {
newsFeed();
} else {
newsDetail();
}
}
window.addEventListener('hashchange', router);
router();
location.hash
를 잡아서 그 값에 따라 어떤 화면을 보여 줄 지 나뉘었다. 화면 전환이 일어나는 이벤트에는 라우터 함수를 연결해주면 newsDetail 함수로만 고정되지 않게 된다.
const container = document.getElementById('root');
const ajax = new XMLHttpRequest();
const content = document.createElement('div');
const NEWS_URL = 'https://api.hnpwa.com/v0/news/1.json';
const CONTENT_URL = 'https://api.hnpwa.com/v0/item/@id.json';
function getData(url) {
ajax.open('GET', url, false);
ajax.send();
return JSON.parse(ajax.response);
}
function newsFeed() {
const newsFeed = getData(NEWS_URL);
const newsList = [];
newsList.push('<ul>');
for(let i = 0; i < 10; i++) {
newsList.push(`
<li>
<a href="#${newsFeed[i].id}">
${newsFeed[i].title} (${newsFeed[i].comments_count})
</a>
</li>
`);
}
newsList.push('</ul>');
container.innerHTML = newsList.join('');
}
function newsDetail() {
const id = location.hash.substr(1);
const newsContent = getData(CONTENT_URL.replace('@id', id))
container.innerHTML = `
<h1>${newsContent.title}</h1>
<div>
<a href="#">목록으로</a>
</div>
`;
}
function router() {
const routePath = location.hash; //화면을 전환하는 기준 값
if (routePath === '') {
newsFeed();
} else {
newsDetail();
}
}
window.addEventListener('hashchange', router);
router();
뭔가 강의를 듣다 보면 처음부터 함수로 작성하는게 아니라 약간 원시적인 코드부터 시작해서 점점 발전하는 코드를 보여준다. 함수를 사용하면 왜 좋은지, 이런 코드 보다 저런 코드는 어떨지 등등의 생각포인트를 알려주는데 좋은 것 같다. 해커뉴스 클론코딩 시리즈 말고 이전에 작성했던 리액트 30 시리즈에서는 사실 너무 깔끔한 코드로 코딩을 하는데 나같은 아직 비기너들은 음 그렇군의 수준이기 때문이다. 뭔가 처음부터 바로 그런 코드를 작성하기 까지는 시간이 꽤 걸리는 데 이때 이런 코드의 흐름을 알고 가면 정말 좋을 것 같다. 결론은 이 강의 좋고 시간 아깝지 않다. !