[ 자바스크립트 스터디 ] 세션 #3

Frontend Dev Diary·2020년 11월 11일
1

다음 내용은 프론트엔드 개발을 위한 자바스크립트 스터디의 세 번째 세션에서 배운 내용을 정리한 것입니다.

1. new 키워드를 통해 함수를 호출했는지 확인하는 방법

윈도우 객체인지를 확인하거나, instanceof를 통해 알아낼 수도 있지만, 부수적인 방법이다.
new.target을 이용해서 확인하는 것이 좋다.

function Foo() {
  if (!new.target) { throw 'Foo() must be called with new'; }
}

MDN new.target

2. innerHTML

innerHTML 속성을 변경할 때마다 reflow 과정이 계속 일어난다.
계산량을 줄이기 위해 한번만 업데이트 할 수 있게끔 코드를 작성하는 것이 좋다.

브라우저의 이해 #1 Reflow, Repaint에 대하여 알아봅니다.

3. 변수 및 상태를 immutable하게 관리하기

예측 가능한 동작을 하게 하기 위해서 var, let이 아니라 const만 사용해서 관리해야 한다. 즉, 새로운 값이 필요하면 아예 새로 const로 담아서 사용한다.
새로운 변수를 만들어내고 이전 변수는 버리면, 적당한 시점에 브라우저에서 가비지 컬렉션이 이루어지게 된다.

객체와 변경불가성

4. 상수를 따로 관리하기

함수 안에 상수를 넣어서, 불필요하게 계속 상수가 새로 만들어지게 할 필요는 없다. 파일의 최상단으로 올리거나, constants.js를 만들어 따로 관리하는 것이 좋다.

안 좋은 예시

function Foo() {
	const enterKey = 13;
  	...
}

5. localStorage

parse에서 에러가 나면 자바스크립트 런타임이 중지된다. 따라서 코드 전체를 try catch로 묶어줘야 한다.
localStorage가 꽉 차면 setItem을 할 때에도 에러가 날 수 있기 때문에 try catch로 묶어주는 것이 좋다.

다음과 같이 helper 함수를 만들어서 사용하면 좋다.

export const getItem = (key, defaultValue) => {
  try {
    const storedValue = window.localStorage.getItem(key)
    return storedValue ? JSON.parse(storedValue) : defaultValue
  } catch (e) {
    console.log(e.message)
    return defaultValue
  }
}

localStorage의 활용 방안

  • form에 글을 작성할 때 임시 저장 기능
  • 네트워크가 잘 연결되어 있지 않은 환경에서 localStorage에 저장을 해 두었다가, 인터넷이 연결되었을 때 싱크를 맞추기 등등 (한국에서는 해당사항이 거의 없겠지만...)

6. App 컴포넌트의 역할

각 컴포넌트의 관심사를 잘 분리해서 독립적으로 짜면 외부 의존성을 낮추고, 테스트가 용이하게 만들 수 있다.
또한 확장성, 재사용성이 좋은 코드를 작성할 수 있다.

App.js

App은 각각의 컴포넌트에게 App이 가지고 있는 데이터를 변경시킬 수 있는 함수(addTodo)를 파라미터로 준다.
addTodo같이 App에서 일어나는 데이터 변경은 모두 setState를 이용하게 된다.

this.components = [
    new TodoInput({
      onAddTodo: (text) => {
        const nextState = [
          ...this.state,
          {
            text,
            isCompleted: false,
          },
        ]
        this.setState(nextState)
      },
      $app,
    }),
    // 다른 컴포넌트들... 
  ]

app에서 setState가 불려질 때마다 app의 각 하위 컴포넌트들도 setState가 일어나게 된다.

this.setState = (nextState) => {
    this.state = nextState
    this.components.forEach(
      (component) => component.setState && component.setState(this.state)
    )
  }

TodoInput.js

$target(input DOM)에서 keydown 이벤트가 일어날 때 app이 전달해준 onAddTodo 함수를 이용하여 app의 데이터를 변경시킨다.

this.initEvent = () => {
    this.$target.addEventListener('keydown', (e) => {
      const { value } = e.target

      if (value.length > 0 && e.key === 'Enter') {
        this.onAddTodo(value)
        this.$target.value = ''
      }
    })
  }

7. 커스텀 이벤트

depth가 너무 깊은데 중간에 거쳐가는 component들이 굳이 그 파라미터를 알 필요가 없는 경우 커스텀 이벤트를 이용할 수 있다. 커스텀 이벤트를 활용하면 하위의 컴포넌트에서 상위의 컴포넌트에게 바로 접근할 수 있다.
단, 너무 빈번하게 사용하는 경우 웹 페이지의 변경을 추적하기가 힘들어진다.

커스텀 이벤트 만드는 법

8. Semantic Web

Semantic Web이 왜 중요할까?

  • 크롤러를 위해서. 기계가 잘 판단할 수 있어야 내가 만든 사이트가 가치있는 사이트라고 평가될 수 있다.
    SEO 최적화 + 좋은 컨텐츠 => 좋은 사이트!
  • 접근성: 인터넷은 누구나 사용할 수 있어야 한다. 저시력자를 위해서 사이트를 읽는 기계(스크린 리더)가 잘 읽을 수 있도록.

div 태그를 남발하지 말자! (내가 HTML은 무시하고 React 배우기에만 급급할 때 하던 짓🙄)

Semantic Web을 위한 요소들

스크린 리더가 무슨 언어로 읽을지 결정한다.

<html lang="en"> 

<h1> 태그를 이용해서 한 페이지를 표현할 수 있는 제목을 작성한다.

<h1> Todo List </h1>

<label>을 클릭하면 <input>으로 포커싱된다. (for attribute)
<fieldset>은 연관된 요소들을 그룹으로 묶을 때 사용한다.
<legend>을 이용해 그룹의 제목을 붙인다.

<form>
  <label for="todo-input"> 여기에 투두를 써 넣어보세요. </label>
  <input id="todo-input" type="text" />
  <fieldset>
    <legned> 생년월일 </legend>
    <select>
      <option></option>
    </select>
    <select>
      <option></option>
    </select>
    <select>
      <option></option>
    </select>
    <button type="submit"> 제출 </button>
  </fieldset>
</form>

<section>은 구역을 나눌 때 쓰인다.
Heading tag는 hierarchy에 맞춰서 <h2>을 사용한다.
이미지는<figure>을 사용해서, <figcaption>을 통해 제목을 넣는다.

이때 <img>의 alt 속성에 "이미지" 라는 말을 넣어선 안 된다.
스크린 리더가 읽을 때 "코딩하는 강아지 이미지 이미지" 라고 읽게 되어, 불필요한 정보를 주게 된다.

<section>
  <h2>
    todoList를 보여줄게
  </h2>
  <ul>
    <li> JS 공부하기 </li>
    <li> 과제하기 </li>
  </ul>
  <figure>
    <img src="puppy.png" alt="코딩하는 강아지"/>
    <figcaption> 이미지를 설명하는 중 </figcaption>
  </figure>    

<button>의 경우도 마찬가지로 스크린 리더가 "확인 버튼 버튼" 이라고 읽지 않게 "확인" 이라고만 적는것이 좋다.

<button> 확인 </button>

<article>은 독립적인 단위로 배포될 수 있는 경우 쓰인다.

<article>
  <h2> 제목 </h2>
  <section> 머릿말 </section>
  <section> 본문 </section>
  <section> 맺음말 </section>
</article>

<aside> 메인은 아니지만 한 쪽 사이드에 있는 의미있는 데이터 뭉치을 나타낼 때 사용한다. (ex 사이드바)

🔍 아이콘만 있는 버튼 같은 경우, 버튼에 대한 설명은 아래에 두고 overflow: hidden을 사용하여 가리면 접근성에 좋다.

navigation bar도 마찬가지로 메뉴에 대한 설명은 숨기더라도 heading 태그를 사용하여 정보를 표시해주는 것이 좋다.

<nav>
  <h2> Content Category </h2>
  <ul>
    <li>
      <a> Movie </a>
    </li>
    <li>
      <a> Drama </a>
    </li>
    <li>
      <a> Cartoon </a>
    </li>
  </ul>
<nav>

백그라운드 이미지를 위한 <div>인 경우 role과 aria-label을 작성해주면 좋다.

<div role="img"
     aria-label="Description of the image"
     title="Tooltip for users not using assistive technologies" />

백그라운드 이미지를 위한 <div>가 다른 내용을 포함하는 경우, 다음과 같이 작성하는 것이 좋다.

<div>
<span class="background-image" role="img" aria-label="[place alt text here]> </span>
[all the rest of my content]
</div>

Semantic Web을 위해 참고하면 좋은 사이트들

measure SEO
정보 접근성 가이드
웹접근성과 웹표준

profile
성장하는 프론트엔드 개발자

3개의 댓글

comment-user-thumbnail
2020년 11월 12일

👍👍

답글 달기
comment-user-thumbnail
2020년 11월 12일

\<article>은 독립적인 단위로 배포될 수 있는 경우 쓰이는데, 그렇게 빈번하게 쓰이지는 않는다.

보다는 제가 많이 써본적이 없다... 입니다

1개의 답글