[Day 11] JavaScript 주요 문법 (8)

송히·2023년 10월 3일
post-thumbnail

Today I Learn📖

  • Javascript의 코드 트릭 (강의)
  • HTML, CSS (강의)
  • DOM, Virtual DOM (강의)
  • id와 class의 차이, CSS 선택자 종류 (추가 학습)
  • 레이아웃 리플로우, 리페인팅 (추가 학습)
  • document.createDocumentFragment(추가 학습)

자바스크립트 코드 트릭

구조 분해 할당을 이용한 변수 swap

: ES6의 구조 분해 할당 문법을 통해 두 변수를 swap 할 수 있음

let a = 5, b = 10;
[a, b] = [b, a];
console.log(a, b); // 10 5

Spread 연산자를 이용한 객체 병합

: 두 객체를 별도 변수에 합쳐줄 수 있음

const person = {
	name: 'Ha-Song-Hee',
	familyName: 'Ha',
	givenName: 'Song-Hee'
};

const favoriteCafe = {
	name: 'TwoSomePlace',
	cause: 'CakeVeryGooood'
};

const Hasonghee = { ...person, ...favoriteCafe };
console.log(Hasonghee);
// {
//   name: 'TwoSomePlace'
// 	 cause: 'CakeVeryGooood'
//   givenName: “Song-Hee”
//   name: "TwoSomePlace" // 같은 키는 우선 순위에 따라 정해진다.
// }

&&와 || 활용

// 기본값을 넣어주고 싶을 때 || 사용
// name이 0 / undefined / 빈 문자열 / null일 경우 'Guest'로 할당
const name = name || 'Guest';


/// && => flag가 true일 경우에만 실행
flag && func();

// 객체 병합
const makeAvartar = (showGender) => {
  return {
    name: 'Songhee',
    ...showGender && { gender: 'woman' }
  }
};
console.log(makeAvartar(false));
// { name: 'Songhee' }
console.log(makeAvartar(true));
// { name: 'Songhee', gender: 'woman' }


HTML과 CSS

  • HTML (Hyper Text Markup Language)

    • 프로그래밍 언어 X
      => 로직이 실행되지 않기 때문 ! 그냥 문서의 연결 링크, 서식 등을 지정해주는 것

    • 문서 구조(Structure) & 의미(Semantic)의 역할 담당

  • CSS (Cascading Style Sheets)

    • HTML에서 표현, 내용, 스타일 등을 분리해서 별도 양식으로 지정한 것
      -> 그러다보니 HTML의 스타일 태그들은 점점 사라짐

    • 문서의 표현 역할 담당

    • 사용법

      1. <head> 태그 안에 <style> 태그를 넣고, 스타일 태그 내에서 CSS 문법 작성하기
      2. 인라인 속성 이용하기 -> HTML 태그 속에 style="~"으로 작성하기
      3. 외부 파일로 분리한 후, 링크 태그로 불러오기
      /* CSS 문법 */
      selector { /* 어디에 적용할지 */
        property: value;
        /* 어떤 스타일을: 어떻게 적용할지 */
        ...
      }
    • 참고 사이트: 코드펜

HTML 5

  • 기존 HTML이 점차 발전하는 웹을 따라잡지 못해, 2014년 10월 28일에 HTML 5 표준안 확정됨
    • 영상 & 음성 처리를 위한 멀티미디어 요소 추가 (audio, video, canvas)
    • 구조적인 요소 추가 (header, nav, article, section, aside, footer, ...)
    • 표현 담당 태그 삭제, 의미를 담은 태그 추가 (s → del, b → strong, ...)
  • HTML 사용 주의점

    1. 태그마다 가진 기본 스타일이 있음
      -> 맘에 안 들면 CSS 적용 안 해도 패딩 등의 스타일 적용될 수 있음
      => reset CSS로 기본 스타일 싹 삭제하면 됨

    2. 브라우저마다 기본 스타일이 다름
      -> Normalize CSS를 통해 브라우저간 차이점 통합 시키기 가능



DOM (Document Object Model)

  • 추상화 / 모델링: 현실에 있는 것을 특정 관점에서 바라보아서 객체로 만드는 것
  • 문서 객체 모델
  • HTML 태그를 모델링하여 만든 것
  • key-value 형태, 웹 UI의 상태, 기능, 속성 등을 객체로 뽑아낸 것
  • JavaScript가 탄생하며 DOM도 같이 등장
    • HTML 문서와 상호작용 가능해짐
    • 초창기엔 Form, Link 등에만 접근 가능했음 (접근 가능한 태그가 많지 않았음..)
  • 1998년에 표준안이 등장했지만 대다수의 브라우저에 적용되기까지 시간이 오래 걸림
    -> 점차 발전하여 지금은 HTML 문서 직접 수정도 가능 (동적인 일 가능해짐)

DOM 구조

  • 트리 구조: 최상위에서 하위로 뻗어나가는 구조

    1. 문서 노드: 최상위 노드, DOM 트리의 시작점, DOM에 접근하려면 여길 거쳐야함
    2. 요소 노드: HTML 태그 자체(HTML 문서 구조를 그대로 나타냄)
    3. 속성 노드: 요소 노드 옆에 따라오는 노드. 즉, 태그에 정의되어 있는 속성. 자식 노드 아님!!
    4. 텍스트 노드: 요소의 텍스트를 표현하는 것, 단말 노드
  • DOM 트리의 순회Pre Order(전위순회)로 이루어짐
    -> 루트 ➡️ 왼쪽 자식 ~ 오른쪽 자식

DOM 트리의 렌더링

  1. 브라우저가 HTML을 읽고 파싱 후, DOM TREE 구성
  2. 그 다음, 브라우저가 Style Sheet를 파싱한 후 DOM 요소에 스타일을 입힘 -> CSS OM TREE
    => 여기까지가 Attachment
  3. 위 두 트리를 결합해서 Render Tree 생성 => 레이아웃(/ 리플로우)을 통해 DOM 노드의 위치 정함
  4. 렌더 트리를 바탕으로 화면에 그림

    ↘️ DOM, CSSOM, RENDER TREE

DOM 관련 메서드

1. 자바스크립트 메서드로 DOM 선택

  • .getElementById("id")
    : DOM Tree에서 id로 요소 노드 찾음, 같은 id 존재할 경우 제일 먼저 찾은 요소 하나를 반환
  • .getElementsByClassName("class명")
    : DOM Tree에서 class로 요소 노드 찾음, 여러 개 존재시 일치하는 모든 요소를 리스트로 반환
  • .getElementsByTagName("태그명"): DOM Tree에서 태그로 요소 노드 찾음, 여러 개 존재시 일치하는 모든 요소를 리스트로 반환
  • .querySelector("아이디 / .클래스명")
    : DOM Tree에서 CSS Selector 문법으로 요소 노드 찾음, 같은 id 존재할 경우 제일 먼저 찾은 요소 하나를 반환
  • .querySelectorAll("아이디 / .클래스명")
    : DOM Tree에서 CSS Selector 문법으로 요소 노드 찾음, 여러 개 존재시 일치하는 모든 요소를 리스트로 반환
  • window.id / window[id]
    : id가 있다면 윈도우 객체로 찾음, 여러 개 존재시 일치하는 모든 요소를 리스트로 반환

2. 위 방법으로 선택한 DOM 탐색 -> 돔선택.메서드

  • .parentNode
    : 선택한 요소의 부모 노드를 불러옴 (document의 부모 노드는 null)
  • .firstElementNode
    : 선택한 요소의 자식 요소 노드 중 첫 번째를 불러옴 (없을 경우 null 반환)
  • .lastElementNode
    : 선택한 요소의 자식 요소 노드 중 마지막을 불러옴 (없을 경우 null 반환)
  • .children
    : 선택한 요소의 모든 자식 노드를 배열로 반환 (없을 경우 빈 배열 반환)
  • .nextElementSibling
    : 선택한 요소의 다음 형제 노드를 불러옴 (없을 경우 null 반환)
  • .previousElementSibling
    : 선택한 요소의 이전 형제 노드를 불러옴 (없을 경우 null 반환)


3. DOM 조작

  • class 접근 => .className, .classList
    : 선택한 요소 노드의 class 속성을 직접 불러오고 변경도 가능
  • .hasAttribute("속성명")
    : 선택한 요소 노드의 속성 존재 여부 확인 (boolean 값 반환)
  • .getAttribute("속성명")
    : 선택한 요소 노드의 속성 값 반환 (없다면 null 반환)
  • .setAttribute("속성명", "값")
    : 선택한 요소 노드의 속성 값 정의
  • .removeAttribute("속성명")
    : 선택한 요소 노드의 속성 제거
  • .textContent = "텍스트값"
    : 선택한 요소 노드에서 텍스트 노드에 접근, 변경 가능
  • .innerHTML = "<태그>변경할 값</태그>"
    : 선택한 요소 노드의 내부 HTML을 직접 수정, XSS 위험이 존재하므로 추천 X
  • .creatElement("태그명")
    : 요소 노드를 입력한 태그 이름으로 생성
  • .appendChild(생성한 요소 노드명)
    : 생성한 요소를 선택한 요소 노드의 마지막에 추가
  • .removeChild(요소 노드명)
    : 선택한 요소 노드의 자시들 중 원하는 요소 노드를 제거


Virtual DOM

  • 매번 돔을 수정 / 조작할 때마다 브라우저 렌더링이 일어나면 성능이 떨어짐
    -> 서비스 규모가 커질 수록 개발자가 일일이 최적화하기 어려움
    -> 가상돔 탄생

Virtual DOM (가상 돔)

  • 실제 DOM TREE에서 필요한 정보만 담아 자바스크립트 객체로 만든 것
    -> 돔을 직접 수정하지 않고, 가상 돔에서 바뀐 부분만 수정 후 렌더링
    => 브라우저 렌더링 프로세스가 줄어듦

  • 리액트 & 뷰에서도 가상돔을 사용함

  • React(=> Virtual DOM)이 DOM보다 빠른 것은 아님
    -> 페이지에 그려진 DOM이 많으면 느려지는 건 똑같음. 심지어 진짜 돔, 가상돔 2번 탐색해야하니까 탐색 & 메모리 사용이 2배여서 실제로는 더 느림 (가상돔은 브라우저 렌더링 횟수를 줄여주는 것, 속도는 X)
    -> 빠른 개발에는 성능 최적화보다 개발 편의성이 더 우선시되는데, 가상돔은 편하고 유지보수를 쉽게 만들어줌. 그리고 대부분의 상황에서 충분히 빠르니까 문제가 되지 않아 사용하는 것 !



id와 class

  • id: HTML 요소를 유일하게 식별하기 위해 사용
    -> 원칙적으로 하나의 id는 한 번만 사용되어야 함
    -> CSS에서의 선택자는 #
    -> JavaScript에서는 getElementById()이 가장 많이 쓰임 (querySelector(), querySelectorAll() 등으로도 선택 가능)

    // HTML
    <div id=“아이디명”>content</div>
    // CSS
    #아이디명 {
      background-color: blue;
    }
    // 자바스크립트
    const element = document.getElementById(“아이디명);
    console.log(element);
  • 동일한 id가 여러 개 사용될 경우
    -> CSS에서는 모든 요소에 해당 스타일이 적용될 수도 있음. 하지만 표준적이지 않은 방법
    -> 자바스크립트에서는 예상치 못한 동작 발생 가능 (에러 위험 높임)
    -> getElementById()에서는 여러 개여도 첫 번째로 등장하는 id만 반환


  • class: 여러 요소에 공통된 스타일 또는 기능을 적용하기 위해 사용
    -> 하나의 요소에 여러 개의 class 사용 가능 (재사용성 높음)
    -> CSS에서의 선택자는 .
    -> JavaScript에서는 getElementsByClassName(), querySelector() 등 사용 가능

    // HTML
    <div class=“클래스명1 클래스명2”>content</div>
    <div class=“클래스명1”>content</div>
    // CSS
    .클래스명1 {
      border: 1px solid black;
    }
    
    .클래스명2 {
      border-radius: 8px;
    }
    // 자바스크립트
    const elements = document.getElementsByClassName(“클래스명1);
    console.log(elements);

  • id와 class 차이점
구분idclass
유일성문서 내에서 유일해야 함여러 요소에 사용 가능
용도특정 요소를 정확하게 식별공통 스타일 및 기능 적용
우선순위높음낮음
CSS 선택자#아이디명.클래스명
JavaScriptgetElementById()getElementsByClassName()

CSS 선택자 종류

  • 기본 선택자
    /* 전체 선택자: 문서 내 모든 요소 선택 */
    * {
      color: blue;
    }/* 태그 선택자: 특정 HTML 태그 선택 */
    p {
      font-size: 16px;
    }/* id 선택자: 특정 id 요소 선택 */
    #아이디명 {
      color: blue;
    }/* class 선택자: 특정 클래스 요소 선택 */
    .클래스명 {
      color: blue;
    }
  • 복합 선택자
    /* 자식 선택자 (>): 바로 아래 자식 요소 선택 */
    div > p {
      color: blue;
    }/* 후손 선택자 (공백): 특정 요소의 모든 하위 요소 선택 */
    div p {
      color: blue;
    }/* 인접 형제 선택자 (+): 바로 다음 형제 요소를 선택 */
    h1 + p {
      font-size: 14px;
    }/* 일반 형제 선택자 (~): 특정 요소의 모든 형제 요소 선택 */
    h1 ~ p {
      color: blue;
    }
  • 속성 선택자: HTML 요소의 속성 기준 선택
    /* 특정 속성을 가진 요소 */
    input[type="text"] {
      font-size: 14px;
    }/* 특정 속성 값을 포함하는 요소 */
    a[href*=“99heesong] {
      color: blue;
    }
  • 의사 선택자, 의사 요소
    /* 의사 클래스(:): 특정 상태의 요소를 선택 */
    a:hover {
      color: blue;
    }/* 의사 요소(::): 요소의 특정 부분을 선택 */
    p::first-line {
      font-size: 14px;
    }


레이아웃 리플로우, 리페인팅

브라우저 렌더링 중, Layout 단계에서 화면에 변화가 발생하여 이 단계가 재실행되는 과정들. 웹 성능 최적화에서 중요한 역할을 함

Layout 단계: Render Tree를 기반으로 요소들의 위치와 크기를 계산하는 단계

  • 레이아웃 리플로우 (Layout Reflow): 요소의 위치와 크기를 다시 계산해야 할 때 발생하는 과정
    -> 브라우저가 모든 요소의 위치와 크기를 재계산해야 하므로 성능 부담 큼
    -> 모든 부모 & 자식 요소를 다시 계산해야 하므로 성능 저하의 주원인이 될 수 있음

  • 리플로우 발생 원인

    • 레이아웃에 영향을 주는 속성의 변경 (width, height, margin, padding, top, font-size, line-height`, …)
    • DOM 요소 추가 / 제거
    • 윈도우 리사이즈 (창 크기 변경)
    • 스크롤 이벤트
    • CSS의 display 속성 변경

  • 리페인팅 (Repainting): 스타일 변경으로 인해 요소가 다시 그려질 때 발생하는 과정
    -> 위치와 크기는 유지됨
    -> 리플로우보다는 아니지만, 브라우저 리소스를 사용하는 거니까 빈번하면 성능 저하 발생 가능

  • 리페인팅 발생 원인:

    • 요소의 스타일 변경 (색상, 그림자, 배경 등)
    • visibility 속성 변경 (display는 리플로우도 같이 발생)

리플로우과 리페인팅 차이점

구분리플로우 (Reflow)리페인팅 (Repaint)
발생 원인레이아웃에 영향을 주는 속성 변경스타일(색상, 배경 등) 변경
렌더링 과정Layout 단계 + Painting 단계 재실행Painting 단계만 재실행
성능 부담매우 큼성능 저하에 영향 줄 수 있음

document.createDocumentFragment

정말 빠른 성능이 필요해서 가상돔을 쓰지 않고 최적화할 때 사용
-> DOM 접근 횟수를 줄여 성능 최적화

  • DocumentFragment: 브라우저가 제공하는 가상의 DOM 노드 컨테이너
    -> 브라우저 성능 최적화를 위해 DOM 조작을 메모리에서 먼저 수행하고, 마지막에 한번에 실제 DOM에 추가함
    -> 실제로 화면에 렌더링되거나 DOM 트리의 일부로 간주되지 않음
    -> 하지만 실제 일반 노드처럼 동작함 (자식 요소 추가, 수정 가능)
    => 메모리 상에만 존재하는 임시 노드 개념

    // DocumentFragment 생성
    const fragment = document.createDocumentFragment();
    
    // 여러 개의 리스트 아이템 생성
    for (let i = 0; i < 5; i++) {
      const li = document.createElement("li");
      li.textContent = `아이템 ${i + 1}`;
      fragment.appendChild(li); // Fragment에 추가
    }
    
    // DOM에 한 번에 추가
    document.getElementById("myList").appendChild(fragment);
    
  • DOM을 조작하면 변경 사항이 화면에 즉시 반영됨 (리렌더링, 리플로우 & 리페인팅)
    -> 반복되면 성능 저하 유발
    => DocumentFragment 사용시 해결 가능

    1. DOM 접근 최소화: 메모리에서만 작업하기 때문에 리렌더링 없음 (브라우저 리소스도 소모 X)
    2. 한 번에 DOM 추가: 변경 사항을 DocumentFragment에 모두 적용하고, 한꺼번에 DOM에 추가해서 렌더링 비용 최소화됨
    3. 복사 비용 없음: 자식 노드를 이동시킬 때 복사되지 않고 참조만 이동됨 (새 노드 생성할 필요 X)

  • 가상돔과 DocumentFragment의 차이점
항목가상 DOMDocumentFragment
목적라이브러리나 프레임워크 사용시 UI 업데이트 최적화바닐라JS에서 DOM 조작 시 리렌더링 최소화
의존성프레임워크에 의존적 (React, Vue.js 등)브라우저 네이티브 API
동작 방식가상 DOM 트리를 메모리에 유지하고 비교메모리에서 DOM 요소를 먼저 조작 후 한꺼번에 이동
최적화 범위전체 DOM 트리의 변경 사항을 비교하고 업데이트특정 DOM 요소만 조작
비용가상 DOM 생성 및 비교에 메모리 비용이 발생메모링서만 작업하므로 리소스 비용 적음


😊오늘의 느낀점😊

코딩 테스트를 준비하며 마음가짐, 공부 방법, 좋은 코드 작성 방법 등에 대한 꿀팁을 많이 알려주셔서 도움이 많이 될 것 같다. 코딩테스트라고 하면 마음이 급급해지는데, 차분하게 메모하면서 풀기 기억..!
그리고 시간복잡도를 계산하고 유형을 추리해야한다는 것도 머리로는 알지만 실제로는 잘 안 됐는데, 좋은 점수를 위해 체화시켜야할 것 같다 ㅎㅎ

자바스크립트 코드 트릭을 여러 개 알려주셨는데 희미한 기억이거나 새로운 것들만 적어봤다. 얘네도 까먹지 않고 사용해야겠다 😃

HTML, CSS에 대해 복습할 수 있었다. 그리고 생소한 개념인 DOM과 가상돔에 대해 알게되고, 그 안의 메서드들을 보면서 자바스크립트의 사용법을 익혔다.

강사님 덕분에 코딩테스트 대비 갈피를 잡을 수 있었고, 프론트엔드 개발자로서의 기초 지식을 탄탄히 쌓은 느낌이다.
이선협 강사님 덕분에 많이 배웠습니다 !! 감사합니다 ㅎㅎ

profile
데브코스 프론트엔드 5기

0개의 댓글