반복되는 HTML_insertAdjacent()

Rock Kyun·2023년 10월 5일
0
post-thumbnail

Front-end 부트캠프 2일 차

오늘은 본격적으로 팀원들과 역할 분담을 하고 프로젝트를 진행했고,
내가 맡은 것은 상세페이지였다.

오늘의 첫 문제

  • 반복되는 HTML
  • 반복은 되는데 그 HTML 안에 수정해야 할 데이터가 존재.
  • 만약 뭉탱이가 10000개 라면 10000개를 수정해야 한다는 것.

그래서 오늘은 바닐라 자바스크립트에서 반복적인 HTML뭉탱이를 처리 할 방법을 공부했다.

생각해 본 접근 방식

리액트에서 Array 데이터를 사용해 JSX로 그려낼 때 Array.map() 을 사용했는데
바닐라 자바스크립트에서도 데이터는 map()으로 반복적인 것을 처리하되
처리 된 것을 HTML로 표현하는 게 가능하지 않을까? 하는 생각이 들었다.

이렇게 생각하고 찾아낸 insertAdjacent() 메소드

MDN 문서의 insertAdjacent() 설명

지정 된 텍스트를 HTML 혹은 XML로 파싱하고
결과 노드들을 지정된 위치의 DOM 트리에 붙여준다!

텍스트를 HTML로 파싱해준다는 것은 아래와 같은 텍스트를

let data = `<p>요런 텍스트 형태의 HTML</p>`

아래와 같이 만들어 준다는 거 같았다.

<div>
  <p>요런 텍스트 형태의 HTML</p>
</div>

적용

  • 목표는 프로젝트에서 아래와 같은 object 자료형이 여러 개 들어있는
    Array 자료형데이터를 사용할 때
    데이터의 개수만큼 유저의 프로필을 만드는 것.
  • 사용한 데이터 형태

  • insertAdjacent()를 적용한 코드

const wrapper = document.querySelector('.wrapper');

function drawPage() {
  profile.forEach(data => {
    wrapper.insertAdjacentHTML("beforeend",
`
 <div class="profile_comp">
   <div class="profile_container">
 	<div class="profile_image">
       <img src=${data.img} alt="user_image"/>
 	</div>
 <div class="profile_info">
   <div class="info_item">
 	<h5>FULL NAME</h5>
	<p>${data.name}</p>
  </div>
 <div class="info_item">
   <h5>GitHub</h5>
   <a target="_blank" href=${data.github}>
    ${data.github !== '' ? data.github + ' 👉' : `<p>커밍 쑨</p>`}
   </a>
</div>
					      .....이하 생략
`)
}

효과는 굉장했다

html을 보면 비어있는데 페이지가 로드 될 때
js의 함수가 작동되며 유저 프로필 UI가 그려지는 것이었다.

<div class="wrapper">
  <유저 프로필 UI> // 실제 html 코드에는 안 보임
  <유저 프로필 UI> // 실제 html 코드에는 안 보임
  <유저 프로필 UI> // 실제 html 코드에는 안 보임
         .
         .
         .
</div>

코드를 요약하면 아래와 같다.

wrapper.insertAdjacentHTML("beforeend", text 형태의 html)
= wrapper 안의 자식들 중 '맨 뒤'에 'text 형태의 html'을 파싱해서 그려주세요

insertAdjacentHTML()의 첫 인자가 파싱된 것을 놓을 위치인데
MDN 문서를 참고하길 바란다.
insertAdjacentHTML - MDN 문서


두 번째 문제

  • 위에서 유저 프로필 UI를 데이터 개수대로 생성했지만
    Array 자료형 속에 또 다른 Array 자료형이 있었다.

생각해 본 접근 방식

  • insertAdjacent()의 두 번째 인자 안에서 또 반복문을 사용할 수 있나? 였다.
    template literal 을 사용하여 변수도 바인딩 하는데
    안될 게 있겠나 싶었던 것이다.
  • 그래도 생각대로 풀리지가 않아 튜터님께 질문하고 설명을 들었다😅

Template Literals

  • 문자열을 백틱( ` ) 기호로 감싸서 사용
  • 백틱으로 감싸진 문자열 안에는 ${ } 를 사용해 변수 바인딩 가능.
  • 띄어쓰기 또한 작성한 그대로 적용
<예시>
	let data = '사과'
	console.log(`나는 오늘 ${data}를 먹었다`) // 나는 오늘 사과를 먹었다.

해결

  • 먼저 함수로 작성하는 것이 깔끔할 거 같아 함수를 작성했다.
<insertAdjacent의 text 부분>
  
<section class= "profile_hobby" >
  <h1>My Hobby</h1>
  <div class="hobby_list_container">
    <ul class="hobby_list">
      // 기존의 데이터를 순회하며 UI를 만들다가 
      // 기존 데이터 속 hobby 데이터를 drawList()의 인자로 전달
      ${data.hobby !== '' ? drawList(data.hobby) : '<h3>아직 취미가 없어요🥹</h3>'}
    </ul>
  </div>
</section >


<전달 받은 인자의 개수대로 text 형태의 <li>를 생성하는 함수>
  
function drawList(data) { 	// Array 데이터 전달
  // Array 데이터를 돌며 text 형태의 <li>를 return
  // return 된 text 형태의 <li>는 list라는 변수에 저장
  let list = data?.map(item => {
    return ( 			    
      `<li>					
        <p>${item.icon}</p>
        <h4>${item.text}</h4>
      </li>`
    )
  })
  
  // 최종적으로 return 된 list
[
`<li>
  <p>${item.icon}</p>
  <h4>${item.text}</h4>
</li>`,
`<li>					
  <p>${item.icon}</p>
  <h4>${item.text}</h4>
 </li>`,
`<li>					
  <p>${item.icon}</p>
  <h4>${item.text}</h4>
 </li>`
]

// 반환하려는 변수 list에 중간 중간 쉼표(,)가 있어
return list.join(' ') // join()으로 쉼표를 공백으로 제거하고 []를 벗겨서 return 
}

세 번째 문제

  • emoji를 HTML로 표현
  • 데이터에서 가져오는 이모지가 HTML에 적용되었을 때 깨질까봐 고민했던 문제.

접근방식

  • 구글링

해결

  • emoji를 여러 코드로 표현 가능한데
  • 태그 안에 &#<hexCode || DecCode>; 형태로 표현 할 수 있다.
<p>I will display &#128052;</p> // 말 emoji (Dec code 사용)
<p>I will display &#x1F434;</p> // 말 emoji (Hex code 사용)

배운 것

  • JS로 text를 파싱하여 HTML의 요소 안에 그려주는 메소드 insertAdjacent()
  • map과 forEach 작동 방식
  • 이중반복문에 대한 편견 사라짐
    오늘 UI를 그리는 코드의 구조는 이중 반복문인데
    그동안 이중 반복문이 성능에 안 좋은 영향을 미치기 때문에 지양했는데
    이런 고민을 튜터님께 말씀드리니
    이중 반복문이 불가피한 부분은 분명히 있기 때문에 불필요하게 남용하는 것을 지양하는 것이 좋다고 하셨다.

궁금하게 된 것

  • 이중반복문을 사용해도 성능을 조금이나마 지킬 수 있는 방법이 있나? 궁금해졌다.

결과물

  • 상세페이지
  • 좌,우로 슬라이드 되는 프로필 UI
  • 데이터의 유/무에 따른 UI 변화


TIP

Array 자료형을 반복적으로 처리할 때 map과 forEach를 구별하자

  • map은 배열 자료를 순회하며 기존 값을 가공해서 만든 새로운 것을 return 할 때
    사용한다.
    예). 새로운 배열

0개의 댓글