본문 바로가기

Project/개인 프로젝트

[JS] 바닐라 JS | 깃(git)과 함께 하는 테트리스 클론 코딩 일지 (1)

반응형

오늘, 내일 노마드 코더 챌린지 일정도 없고 강의도 이미 다 들은 거길래 이때가 기회다 싶어서 얼른 테트리스를 만들어 보기로 했다. 테트리스를 만드는 데에도 나름 버전 구분이 필요할 거 같아서 아직은 생소한 깃/깃허브 연습을 하기에 좋은 기회라고 생각했다.

 

그리하여 21.07.31 5PM! 깃(git)을 사용하여 테트리스 만들기 시작이다!

cod Scalper님의 https://youtu.be/1lNy2mhvLFk 영상을 보고 만들었다.

 

클론 코딩은 무작정 베끼면 아무 소용이 없다고 생각한다. 오래 걸리겠지만 이해하는 것을 주목표로 하고 열심히 따라가 보겠다. 

 

만들면서 생기는 궁금증은 이 인용 말풍선에 넣어보겠다.

원격 레파지토리와 로컬 파일 연결하기

원래 이건 손쉽게 될 거라고 생각했는데 조금 삐걱거림이 있었다. 기존에 쓰던 로컬 폴더인 project 폴더 내에 tetris라는 폴더를 만들어 놨는데 그렇게 하고 원격 repo.와 연결하니 몇 겹의 폴더가 되는 것이 보기가 싫었다. 더구나 위치가 헷갈리기도 했다. 결국 구글링 해보고 여러 번의 시도 끝에 연결할 수 있었다. hㅏ 약간 git이라는 것 자체로 오는 공포감이 있어서 뭐든지 쉽지가 않구만.

README.md 파일로 푸시앤풀 연습을 몇 번 하고 개발을 시작했다.

 

 

I. Score 부분 

이 부분 처리 후 한 섹션이 완성되었다고 생각하여 커밋을 했다.

 

II. 테트리스 진행되는 table

1. container 틀 잡기

작성한 코드에서는 container의 태그를 ul로 했다. 하지만 일반적이라면 div 태그를 사용할 것 같다. 왜 div를 안 쓰고 굳이 ul을 썼는지는 궁금하다.

 

우선 아직 HTML 구조는 이렇다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>테트리스</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>

  <body>
    <div class="wrapper">
      <div class="score">0</div>
      <div class="playground">
        <ul></ul>
      </div>
    </div>
  </body>
</html>

구조가 헷갈려서 component를 그림으로 표현했다.

왜 playground 박스에서 바로 처리하지 않고 그 안에 또 ul을 넣었을까?
마찬가지로 왜 li 박스에서 바로 처리하지 않고 그 안에 또 ul을 넣었을까?
헷갈릴 거 같은데... 왜 저렇게 했을까

2. JS에서 반복문으로 li element 생성하기

와 신기하다. JS로 for 문을 처음 써본다. 오오... 자아 일단 코드는 이렇다.

const playground=document.querySelector(".playground > ul");

console.log(playground);

for(let i=0; i<20; i++) {
  const li = document.createElement("li");
  const ul = document.createElement("ul");
  for (let j=0; j<10; j++) {
    const matrix = document.createElement("li");
    ul.prepend(matrix); /* ul에 matrix 넣는다. */
  }
  li.prepend(ul); /* li에 ul 넣는다. */
  playground.prepend(li);
}

 

처음 보는 문법이 등장했다. createElement()라는 신기한 함수는 무엇인가?

Document.createElement(tagName)

HTML에 지정한 tagName의 HTML 요소를 만들어 반환한다. 그러니까 return 값이 HTML의 element이다. 만약 이것을 A 변수에 할당한다고 치자. 그러면 A에 진행하는 작업은 모두 HTML Elements에 반영되는 것이다. 이해가 잘 안 가죠? 위의 코드를 이용하여 예를 들어보자. 

// 1.
const li = document.createElement("li");
// 2.
const ul = document.createElement("ul");

1번.  변수 li에는 실제 HTML에 새로 생긴 li element가 value로 할당된다. 그래서 변수 li를 console.log 해보면 HTML의 li element가 출력되는 것을 볼 수 있다. 따라서 li을 대상으로 하는 모든 코드는 HTML의 li element에 직접적으로 작용한다. (li를 HTML의 li element로 보고 작업하면 된다.)

2번도 마찬가지다. 변수 ul에는 실제 HTML에 새로 생긴 ul element가 value로 할당된다. 그래서 변수 ul를 console.log 해보면 HTML의 ul element가 출력되는 것을 볼 수 있다. 이하 생략.

 

처음에는 왜 저 함수를 li와 ul 변수에 할당하는지 이해가 안 됐는데 함수의 return값이 HTML element인 것을 곱씹으니까 이해가 되었다.

 

개쩌는 메소드다. JS를 이용해 HTML에 새로운 element를 추가할 수 있다니 미쳤다... 너무 신기하다. 이 함수를 이용하면 실제로 elements 검사를 해보잖아? 거기에 새로운 element가 추가된 것을 확인할 수 있다. 이렇게 추가하는 것을 element를 동적으로 추가한다고 하나보다.

 

그리고 prepend 함수에 대해 알아보자. 

element.prepend()

element에 ()안의 것을 넣을 때 사용한다. 단순하다.

 

그럼 이제 for 반복문을 이해해보자.

for 반복문

구조를 보면 이중 for 반복문임을 쉽게 알 수 있다. 논리를 말로 설명하기엔 무리가 있어서 정확하게 이해할 겸 한 번 그림으로 표현해봤다. 아래의 그림을 참고하자.

 

처음에 이놈들이 왜 반복문 안에 있어야 하는지 이해가 잘 안 돼서 반복문 위로 빼봤는데 바로 이해할 수 있었다.

저 무수한 li들이 보이는가... 그렇다. for 반복문이 끝나기 전에 ul과 li에 변형이 가해진다. 때문에 반복될 때마다 변수를 초기화 시켜줘야하는 것이다. 

 

자 여기까지 10x20 table의 form이 완성되었다. commit하고 가자!


이 이후로는 거의 처음 보는 함수와 처음 접하는 개념들이 등장하였다.... ㅠㅠ 그때마다 구글링으로 정보를 얻었고 아래에는 그 파편적인 정보들을 모아본 것이다. 진도가 안 나가서 힘들다. 그래도 재밌다.

 

spread operator(...)? (17:28)

펼침 연산자. 특정 객체 또는 배열의 값을 다른 객체, 배열로 복제하거나 옮길 때 사용.

이 코드에서 사용하는 이유는 스프레드 오페레이터를 쓰지 않고 = 을 이용해 할당하면(a=b), 할당한 이후에 b 값이 바뀌더라도 a에 적용이 된다. 이를 막기 위하여 spread operator(...)을 사용한다. 

이렇게 하면 movingItem 안의 값만 가져와서 tempMovingItem에 넣을 수 있다.

(https://joshua1988.github.io/es6-online-book/spread-operator.html#%EB%B7%B0%EC%97%91%EC%8A%A4%EC%97%90-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%B8-%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C-%EC%98%A4%ED%8D%BC%EB%A0%88%EC%9D%B4%ED%84%B0)

 

비구조화 할당(destructuring assignment) (20:00)

배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 자바스크립트 표현식(expression)

간단하게 정리하면 배열 [], 혹은 객체 {} 안의 값을 편하게 꺼내 쓸 수 있는 문법

이 블로그에 설명이 굉장히 잘 되어 있으니 참고하자.(https://yuddomack.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%AC%B8%EB%B2%95-%EB%B9%84%EA%B5%AC%EC%A1%B0%ED%99%94-%ED%95%A0%EB%8B%B9)

 

forEach()

foreach 반복문은 오직 Array 객체에서만 사용가능한 메서드. 배열의 요소들을 반복하여 작업을 수행할수 있다. foreach구문의 인자로 callback함수를 등록할수 있고, 배열의 각 요소들이 반복될 때 이 callback 함수가 호출된다. (출처: https://dydals5678.tistory.com/66)

 

Arrow Function

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/Arrow_functions

 

node?

http://tcpschool.com/javascript/js_dom_node

노드는 계층적 단위를 말한다.

 

 

element.childNodes()

element의 모든 자식 노드들을 선택한다.

 

흐아아앙앙 24분까지 완성!! 계속 붙잡았던 게 renderBlocks 함수의 구조가 너무 이해가 안 됐었다. ㅠㅠㅠㅠㅠㅠ

다차원 배열에다가 array.forEach(element=>{}) 반복문으로 array의 각각의 요소를 잡아서 arrow function을 실행하는 것이다. 훠우... 하 그림 그려서 완전히 이해했다. 대박대박 너어무 뿌듯하다! 그린 그림은 아래와 같다. 


 

현재 영상의 39분 정도까지 만들었다.
휴,,, 생각보다 좀 어렵다. 위에까지는 영차영차 이해하면서 잘 따라갔는데 그 뒤에 로직이 좀 어렵고 쓰이는 함수의 원리를 알기 위해서는 스택 같이 아직은 생소한 개념이 필요한 것 같다. ㅠㅠ 그래도 끝까지 따라가보고 싶다.
전반전은 여기서 마무리하고 조금 쉰 후 후반전으로 들어가야겠다. 파이팅!

반응형