본문 바로가기
스파르타코딩클럽/내일배움캠프

[TIL] 내일배움캠프 React 과정 2022.11.19

by heereal 2022. 11. 19.

Today I Learned

  • CSS BEM 표기법
  • Javascript로 하는 SPA 공부

 

CSS BEM(Block Element Modifier) 표기법

기본 구조

.header__navigation--navi-text {
  color: red;
}

이름을 연결할 때는 block-name과 같이 하이픈 하나만 써서 연결한다.


BLOCK 블록. block
재사용 가능하며 기능적으로 독립적인 페이지 컴포넌트. 한 페이지 안에 구현되는 요소들을 영역으로 구분 짓고 이에 따른 이름을 붙인다. 블록은 블록을 감쌀 수 있다.
ex) header, container, menu, input, button

Example

<!-- `header` block -->
<header class="header">
    <!-- Nested `logo` block -->
    <div class="logo"></div>

    <!-- Nested `search-form` block -->
    <form class="search-form"></form>
</header>


ELEMENT 요소 .block__element
엘리먼트는 블럭을 구성하는 단위이다. 블록은 독립적인 형태인 반면, 엘리먼트는 의존적인 형태이다. 자신이 속한 블럭 내에서만 의미를 가지기 때문에 블럭 안에서 떼어다 다른 데 쓸 수 없다.
ex) menu-item, headTitle, logo, searchbar, navigation

Example

<!--
    Correct. The structure of the full element name follows the pattern:
    `block-name__element-name`
-->
<form class="search-form">
    <div class="search-form__content">
        <input class="search-form__input">

        <button class="search-form__button">Search</button>
    </div>
</form>

<!--
    Incorrect. The structure of the full element name doesn't follow the pattern:
    `block-name__element-name`
-->
<form class="search-form">
    <div class="search-form__content">
        <!-- Recommended: `search-form__input` or `search-form__content-input` -->
        <input class="search-form__content__input">

        <!-- Recommended: `search-form__button` or `search-form__content-button` -->
        <button class="search-form__content__button">Search</button>
    </div>
</form>



Modifiers 모디피어스 .block__elemnet--modifier
블록 또는 요소의 모양, 상태, 동작을 정의하고 외관이나 상태를 변화시킨다. 블록 또는 요소의 크기는 어떤지, 다른 요소들과 차별점은 없는지, 어떤 동작을 하는지를 따져보고 집어넣는다. 가장 마지막 자리에 온다.
ex) disabled, highlighted, fixed, size-big, color-yellow, direction_left-top 등

Example

<div class="column">
  <strong class="title">일반 로그인</strong>
  <form class="form-login form-login--theme-normal">
    <input type="text" class="form-login__id"/>
    <input type="password" class="form-login__password"/>
  </form>
</div>
 
<div class="column">
  <strong class="title title--color-gray">VIP 로그인 (준비중)</strong>
  <form class="form-login form-login--theme-special form-login--disabled">
      <input type="text" class="form-login__id"/>
      <input type="password" class="form-login__password"/>
  </form>
</div>


참고
https://en.bem.info/methodology/quick-start/
https://getbem.com/introduction/
https://bomango.tistory.com/34
https://nykim.work/15


Javascript로 하는 SPA 공부

Javascript 비동기, Promise, async, await 이해하기

함수는 정의한다고 실행되지 않는다. 함수가 호출되어야 그 함수의 내용이 실행된다.

동기의 특징

  • 동시에 여러 작업을 수행할 수 없다.
  • 흐름을 예측하기 쉽다. 먼저 수행되고 나중에 수행되는 것들이 명확하다.

비동기의 특징

  • 동시에 여러 작업을 수행할 수 있다.
  • 흐름을 예측하기 어렵다. 즉 무엇이 먼저 완료될지 보장할 수 없다.


Promise 는 비동기 작업의 단위다.

then 메소드는 해당 Promise 가 성공했을 때의 동작을 지정한다. 인자로 함수를 받는다.
catch 메소드는 해당 Promise 가 실패했을 때의 동작을 지정한다. 인자로 함수를 받는다.

const promise1 = new Promise((resolve, reject) => {
  resolve();
});
promise1
  .then(() => {
    console.log("then!");
  })
  .catch(() => {
    console.log("catch!");
  });


Promise를 만드는 순간 비동기 작업이 시작되며, 비동기 작업을 성공으로 간주하고 싶을 때 resolve를 호출하고, 실패라 간주하고 싶다면 reject 함수를 호출한다. 이 비동기 작업이 성공했을 때 후속 조치를 지정하고 싶다면 then으로, 실패 시의 후속 조치는 catchcatch로 지정한다.

지금까지의 내용을 요약하자면

  1. 기다리기만 하면 되는 작업을 비동기로 처리할 수 있다. 동시에 여러 작업이 진행되어서 비교적 효율적이지만, 흐름 제어는 동기 코드보다 어렵다.
  2. Promise를 생성할 때에는 resolve, reject 함수를 적절히 호출하는 작업을 넣어주고, 이후 생성된 Promise에 대해 then, catch 메서드를 호출하여 후속 조치를 정해준다.
  3. new Promise(…)는 async 함수로 적절하게 변환할 수 있다.
  4. async 함수 내에서 Promise 에 대해 awaitawait을 걸어서 작업을 기다릴 수 있다.

출처 https://springfall.cc/post/7



SPA의 javascript 구조 이해하기
router.js

const route = (event) => {
     event.preventDefault();
     // event.target의 hash 값을 window.location.hash 값에 넣어라
     // event.target은 <body>의 a태그, 따라서 event.target의 hash 값은 #about이 됨
     // window.location.hash에 #about라는 값을 넣었음
     window.location.hash = event.target.hash;
   };
   
   const routes = {
     404: "/pages/404.html",
     "/": "/pages/mainpage.html",
     loginpage: "/pages/loginpage.html",
     mycontent: "/pages/mycontent.html",
     mypage: "/pages/mypage.html",
     writepage: "/pages/writepage.html",
   };
   
   // handleLocation = 화면을 띄워주는(바꾸는) 역할을 하는 함수!!
   // routes에서 맞는 값을 찾아서 main-page에 통째로 삽입함
   const handleLocation = async () => {
     // hash 값에서 #을 빈 문자열로 만든다 ex) #about -> about
     // 결론적으로 about라는 값이 path에 들어감
     let path = window.location.hash.replace("#", ""); 
   
     // "http://example.com/"가 아니라 도메인 뒤에 / 없이 "http://example.com" 으로 나오는 경우
     if (path.length == 0) {
       path = "/";
     }
     // route 변수에 routes[about]의 값, 즉 "/pages/about.html"라는 문자열이 담긴다
     // 이것이 html 파일의 위치를 '문자열로서' 알려주는 역할을 함
     const route = routes[path] || routes[404];
     // fetch(route).then((data) -> fetch API를 통해서 html '파일'을 알려준 위치에서 response 형태로 불러 옴
     // (response객체는 서버가 클라이언트의 요청에 응답하는 정보를 담고 있는 객체이다._
     // data.text() -> response 형태로 불러 온 파일을 text 메서드를 이용해서 string 값으로 바꿔 줌
     // 결과적으로 변수 html은 about.html을 담고 있는 string 값(문자열)이 됨
     const html = await fetch(route).then((data) => data.text());
   
     // html(문자열)을 main-page에 삽입함
     // temp_html 이용해서 문자열 삽입하는 방식과 동일함
     document.getElementById("main-page").innerHTML = html;
   };
   
   // hash 값이 바뀌면 handleLocation 함수를 실행함
   window.addEventListener("hashchange", handleLocation);
   
   // 처음에 랜더링 또는 새로고침 했을 때 DOMContentLoaded라는 이벤트가 발생함
   // html, css, js 파일을 정상적으로 다운 받았다면 handleLocation 함수를 실행함
   document.addEventListener("DOMContentLoaded", handleLocation);

JS로 하는 SPA 특강 튜터님 코드 리뷰의 거의 모든 내용을 주석으로 받아 적었다.

 

 

해결하는 경험

SPA 공부를 위해 우리 팀의 웹페이지를 간단하게 틀만 잡아서 만들어 보았다. SPA의 장점은 깜빡임 없는 자연스러운 페이지 이동이 가능하다는 것인데 다른 페이지에 들어갈 때마다 뭔가 새로고침하는 느낌이 든다... 알고 보니 페이지를 로딩하는 과정에서 css가 적용되지 않은 화면이 잠깐 빛났다가 사라지는 것이었다.

문제 해결을 위해 팀원 분들에게 도움을 요청하였고 문제를 해결할 수 있었다!

페이지가 깜빡임 없이 자연스럽게 넘어간다.

문제의 원인은 index.html에만 css 파일 이름이 틀리게 작성되어 있고 다른 html 파일에는 css 파일 이름이 올바르게 들어가 있었다는 것이었다. 이 문제를 해결하기 위해서 index.html에 삽입한 css 파일명을 바르게 수정하고 index.html 제외한 html 파일에서는 body 부문만 남겨두고 head 부분은 모두 지워버렸다.

참고로 폴더의 구조는 다음과 같다.

 

느낀 점

원래 오늘은 BEM 문법을 공부하고 나서 css class명을 먼저 수정하고 firebase를 공부하려고 했지만 팀원들이 코드 구조에 대해 얘기하는 것을 전혀 알아들을 수 없었기 때문에 일단 SPA와 firebase를 먼저 공부하기로 마음을 바꿨다. 그래서 오늘은 하루 종일 SPA 공부만 했다. 특강을 다시 듣고 내가 직접 SPA 구조의 웹페이지를 구현해 보며 어떤 방식으로 페이지가 이동되는 것인지 이해하기 위해서 노력했다. 주말인데도 불구하고 우리 팀의 출석률이 아주 좋아서(올출!) 다들 열심히 공부하시는 모습에 나도 자극을 받는다. 내일은 firebase를 공부할 예정이다. 그리고 오늘도 github과 싸웠다ㅎㅎ

댓글