서버에서 받은 데이터를 forEach() 이용해서 UI 반복 생성하기
이전까지 2~3개의 포스팅을 통해서, Javascript를 이용해서 동적으로 UI를 생성하는 과정을 정리해왔습니다. 기초적인 DOM 조작 및 Data 핸들링에 코딩 근육이 붙었으니, 이번에는 서버에서 받아 온 Data를 이용해서 좀 더 코딩스럽게 구현해보는 과정을 정리해보려고 합니다.
서버에서 Data를 내려 받은 후 해당 데이터를 이용해서 아래아 같은 UI를 동적으로 만들어보려고 합니다.
NETFLIX 비슷한 OTT 채널이라고 가정해봅시다. 좀비 영화만 주구장창 틀어주는 채널, ZomFLIX.
아주, 흥미진진하죠?
우선, 서버에서는 이런 정보를 전달 받았다고 가정해봅시다.
const zombies = [
{ id: 0, thumb: "zombie1.jpg", title: "좀비 1화", time: 48 },
{ id: 1, thumb: "zombie2.jpg", title: "좀비 2화", time: 59 },
{ id: 2, thumb: "zombie3.jpg", title: "좀비 3화", time: 55 },
];
그리고, 사용된 이미지는 아래 첨부합니다.
일단 1개를 표시하는 UI를 만들어보자
그리고 사용될 템플릿은 다음과 같습니다.
일단은 1화가 표시되도록 해두고, 이것을 반복하면 되는 것이겠죠?(Bootstrap CSS를 사용하고 있습니다!)
<div class="container text-center mt-5">
<h1 class="mb-5">ZomFLIX</h1>
<div class="row">
<div class="col">
<div class="card" style="width: 18rem">
<img src="zombie1.jpg" class="card-img-top" alt="..." />
<div class="card-body">
<h5 class="card-title">좀비 1화</h5>
<p class="card-text">러닝타임 : 48 분</p>
</div>
</div>
</div>
</div>
일단 1화를 표시하는 내용을 만들어봅니다. 그리고 나서는 반복문을 사용해서 반복해주면 되는 것일테니까, 처음부터 복잡한 결과를 구현하려 하지 말고, 단순하게 분해를 한 후 하나씩 만들어 나가보도록 해봅니다.
반복 사용되는 HTML 구문은 템플릿으로 만들어 재사용
가만 보면 Card 부분의 UI가 반복, 재사용되고 있는 것을 알 수 있습니다. 해당 부분을 변수에 담아 템플릿으로 만들어 둡시다. 그리고 그걸 div.row 엘리먼트에 붙여 봅시다.
전체 코드는 아래와 같이 변경했습니다.
<body class="bg-dark-subtle">
<div class="container text-center mt-5">
<h1 class="mb-5">ZomFLIX</h1>
<div class="row">
<!-- 생성한 카드가 표시될 위치 -->
</div>
</div>
<script>
const zombies = [ //서버에서 받은 데이터
{ id: 0, thumb: "zombie1.jpg", title: "좀비 1화", time: 48 },
{ id: 1, thumb: "zombie2.jpg", title: "좀비 2화", time: 59 },
{ id: 2, thumb: "zombie3.jpg", title: "좀비 3화", time: 55 },
];
const template = `
<div class="col">
<div class="card" style="width: 18rem">
<img src="zombie1.jpg" class="card-img-top" alt="..." />
<div class="card-body">
<h5 class="card-title">좀비 1화</h5>
<p class="card-text">러닝타임 : 48 분</p>
</div>
</div>
</div>
`;
</script>
</body>
자, 이제 저 template에 담긴 내용을 div.row에 갖다 붙여봐야겠죠?
그런데, 아직 자바스크립트가 무르익지 않은 초보 상태라면, 이 지점에서 여러 번의 삽질이 기다리고 있게 됩니다.
div.row에 붙이기 시도와 실패 - insertAdjacentHTML vs. appendChild
일단, 저는 insertAdjacentHTML() 메서드를 사용해봅니다. 왠지 기능이 멋져서요.
document.querySelector(".row").insertAdjacentHTML("beforeend", template);
결과는 성공! 제대로 잘 표시가 됩니다.
한번에 성공하면 왠지 이상한거죠? 내친 김에 appendChild() 메서드로도 바꿔서 실행해봅시다. 아마 안될걸요?
document.querySelector(".row").appendChild(template);
콘솔창에는 에러가 표시됩니다. 물론 좀비도 나타나지 않구요. 저도 처음에는 아주 삽질을 자주 하는 구간이었습니다.
Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
해석 : 에러! Node에서 appendChild' 실행 실패, 파라미터1은 'Node' 타입이 아님. 즐~
요점만, 정리하자면, 지금 appendChild로 붙이려는 게 Node 타입이 아니어서 안된다는 소리입니다. 이게 뭔 X.... 싶지만, 쉽게 말하자면 <p> 태그나 <img> 태그 등은 순수한 노드 타입인데, 지금 template을 `백틱`을 이용해서 문자열 구조로 만들었기 때문에, 넌 순수하지 않아! 붙일 수 없어! 라고 에러를 낸다고 생각해주세요.
insertAdjacentHTML은 노드가 아니라, HTML 타입으로 갖다 붙이는 거라 상관이 없는 것이구요.(그래서 insertAdjacentHTML을 사용하는 게 저는 더 편하더랍니다.)
어라? append 였던가? 생각하고 append(template)로도 바꿔서 실행해봅시다. 역시나 이상하게 될걸요?
document.querySelector(".row").append(template);
append(template)로 붙여보니, 에러는 발생하지 않았지만, 텍스트처럼 붙여져 버리는군요. 초보 입장에서는 이런 게 정말 미치고 팔딱 뛸 노릇인 지점이 되곤하죠. Javascript 라는 게 원래 그렇습니다.
저 차이점을 파고드는 건 지금 목표가 아니니, 아무튼 그렇게 일단은 암기를 해주시고 기억해주는 게 속 편합니다.
내친 김에 jQuery로도 코딩을 해봅시다! 왜냐구요? 코드가 보기 편하고 간단하니까요. 비교도 되구요.
div.row에 붙이기 시도 - jQuery
jQuery를 사용하기 위해서는 아래 호출 코드를 HTML문서 <head>에 붙여 넣습니다.
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
그리고 element를 붙여 넣는 JS 코드는 다음과 같이 수정했습니다.
$(".row").append(template); //유의! 여기의 append는 jQuery의 append 임.
jQuery로도 에러 없이 잘 수행됩니다. 어라? 아까는 append() 안되었는데??
같은 스펠링이지만, 서로 소속이 다릅니다. 똑 같이 생긴 녀석이 하나는 Vanilla JS 소속이고 다른 하나는 jQuery 소속입니다. 바로 이러한 점 때문에, Vanilla JS를 먼저 공부하라는 이유이기도 합니다. 초보 때는 늘 헷갈릴 수 밖에 없거든요.
자, 제대로 붙였으면 이제 반복을 해봅시다 - forEach() 등장
JS 코드 부분을 이렇게 수정해보았습니다. 별거 없습니다. forEach() 반복문 안에 넣은 것 밖에 없습니다.
zombies.forEach(function () { // forEach() 로 감싸준 것 뿐!!
const template = `
<div class="col">
<div class="card" style="width: 18rem">
<img src="zombie1.jpg" class="card-img-top" alt="..." />
<div class="card-body">
<h5 class="card-title">좀비 1화</h5>
<p class="card-text">러닝타임 : 48 분</p>
</div>
</div>
</div>
`;
$(".row").append(template);
});
일단 3개의 카드가 forEach()구문을 통해 잘 배치되었으므로, 성공입니다!
동일하게 나오는 저 것만, 변수 i 같은 걸 사용해서 배열의 순서에 따라 데이터를 뽑아내면 되겠군요!
뭔가 될 것 같아보이니, 당장 코딩해봅시다!
forEach() 메서드로 데이터를 뽑아내는 방법들
백틱기호(`) 사이의 문자열에서 변수를 설정하려면, ${ }를 사용합니다. 잘 아시죠?
forEach() 메서드는 배열의 원소를 하나씩 꺼내주니까, 막상 꺼낸 놈이 각각 오브젝트(객체)니까 쩜(.)을 찍어 key를 연결해주는 방법으로 데이터를 뽑아오도록 코딩을 변경했습니다.
const zombies = [
{ id: 0, thumb: "zombie1.jpg", title: "좀비 1화", time: 48 },
{ id: 1, thumb: "zombie2.jpg", title: "좀비 2화", time: 59 },
{ id: 2, thumb: "zombie3.jpg", title: "좀비 3화", time: 55 },
];
zombies.forEach(function (data) {
const template = `
<div class="col">
<div class="card" style="width: 18rem">
<img src="${data.thumb}" class="card-img-top" alt="..." />
<div class="card-body">
<h5 class="card-title">${data.title}</h5>
<p class="card-text">러닝타임 : ${data.time} 분</p>
</div>
</div>
</div>
`;
$(".row").append(template);
});
아싸! 성공!! 잘 꺼내서 잘 배치가 됩니다.
그런데, 여기서 잠깐 forEach() 메서드만의 독특한 점이 있습니다. 파라미터를 또 하나 사용할 수 있다는 것인데요, 다음과 같이 한번 찍어보시죠.
.zombies.forEach(function (data, i) // i 자리에는 0, 1, 2, 3.... 배열 원소의 개수 만큼 반복횟수가 남습니다.
그래서, 자바스크립트 코드는 다음과 같이 변경할 수도 있습니다.
zombies.forEach(function (data, i) {
const template = `
<div class="col">
<div class="card" style="width: 18rem">
<img src="${zombies[i].thumb}" class="card-img-top" alt="..." />
<div class="card-body">
<h5 class="card-title">${zombies[i].title}</h5>
<p class="card-text">러닝타임 : ${zombies[i].time} 분</p>
</div>
</div>
</div>
`;
$(".row").append(template);
});
결과는 역시 원하던 대로 잘 나타납니다.^^
그럼 둘 중에 어떤 걸 쓰면 좋냐구요? 그냥 맘에 드시는 걸로 사용하시면 됩니다!
마치며
이번 포스팅의 작업 과정을 곰곰히 관찰해보면, 막연하기만 했던 '서버'라는 괴상한 물건으로부터 정보를 받아서 처리가 되는 프로세스에 대한 이해도가 올라갈 것입니다. 뭔가 갈피가 좀 잡히는 것 같기도 하구요.
물론, 나중에는 서버단에서의 코딩에도 관심을 더 갖고 공부도 더 해보면서 실력을 쌓아 나가야겠죠.
모든 공부가 다 그렇겠지만, 코딩도 워낙 다루는 범위가 많다보니, 몇 달만 지나면 가물가물 해지는 부분도 있기는 합니다만, 그럴 때마다 공부했던 부분을 다시 들춰 살펴보면서 반복하다보면 점점 더 복습하는 시간이 짧아지더라구요. 그러다가 결국 머릿속에 남거나 체화가 되는 것 같습니다.
저도 뭐 그 반복의 일환으로 정리겸 블로그 포스팅을 꾸준히 진행하고 있는 이유이기도 합니다.
오늘도 즐거운 코딩하세요!
즐거운 코딩생활, 즐코딩.
KINcoding.com
'Javascript' 카테고리의 다른 글
콜백 함수(Callback Function)는 뭘까? Please Call Me (0) | 2023.02.25 |
---|---|
sort() 메서드로 상품 정렬 기능 만들기 (0) | 2023.02.24 |
객체(Object)에서 forEach()로 데이터를 꺼내보자 (0) | 2023.02.22 |
selectbox를 JS로 컨트롤 해보기 2 - 서버 Data 받아서 처리하기 (0) | 2023.02.21 |
JS document.createElement() 메서드 간단 정리 (0) | 2023.02.20 |
댓글