[코드 리뷰] 2주차 tick tack toe

Soozynn·2021년 8월 2일
0

[프렙] 코드 리뷰

목록 보기
2/6

<내가 받은 피드백>

  • 어떠한 메소드를 사용하기 전에 그 메소드가 어떤 메소드인지 mdn에서 검색하고 읽어본 뒤에 사용하기

  • 급하게 코드 짜지 않기 => 들여쓰기, 공백 주의하기
    코드를 짜고, 중복되는 것은 없는지, 어떤식으로 더 개선하면 좋을지 계속해서 생각하기

  • 코드 스타일 항상 유의하기
    (공백, 띄어쓰기, 들여쓰기, 명확한 변수 & 함수명, Javascript에서 사용되는 통상 규칙 적용 등
    => 가독성, 코드 품질에 영향)

  • 점진적으로, 차근차근 작은 것부터 풀어나가기

  • 콘솔이나, 에러, 오류 메세지 자세히 읽고 어느 부분에서 어떤 오류가 뜬 것인지 확인하기

  • 로직 작성이나, 수정 완료 시 마지막에 코드 스타일을 정리하는 시간 꼭 가지기

  • 과제가 제시 되었을 때, 한번 더 진행방식에 대한 로직에 대해 다시 한번 정리를 해보는 것 필요
    글로 로직을 정리해보시지 않았을 시 꼭 정리를 해보고 코드짜기

  • 구현해야 할 사항에 대해 먼저 집중하고 시간이 남을 시에 다른 기능을 추가해보기

  • 항상 기본문법인 띄어쓰기 주의하기
    (특히 이퀄, 콤마, 블록 스코프에서)

  • 따옴표와 쌍따옴표 섞어서 쓰지 않기

  • function 선언문, if 구문 끝에 세미콜론 x

  • 코드 스타일과 관련해 공백, 띄어쓰기, 들여쓰기, 명확한 변수 & 함수명 진짜 다 하나같이 너무 기본이..





setTimeout에 대하여

이 메소드가 코드를 나중에 실행시켜준다는 것은 알았지만, 올바른 문법이 무엇인지 모르고 사용했었다.
다음에는 새로운 메서드를 쓰게 된다면 mdn을 통해 정확히 올바른 문법과 여러가지를 파악한 뒤에 써볼 것.

내가 setTimeout을 썼던 이유는 시간차를 두고 스트링을 색칠하기 위함이었는데 이는 자바스크립트가 아닌 css 효과를 통해 설정하는 것이 좋으며 이런식의 코드 작성은 옳지 못하다. 호출하는 방식 또한 잘못되었다.

// 내가 작성했던 코드 ❌
 setTimeout(function () {
    selectXButton.style.color = "black";
    selectOButton.style.color = "blue";
    text.style.display = ""; 
    }, 500);

// 올바른 사용 방법 ✅
function delayedAlert() {
  timeoutID = window.setTimeout(slowAlert, 2000);
}

function slowAlert() {
  alert("That was really slow!");
}

// 올바른 사용 방법 2✅
function sayHi(who, phrase) {
  alert( who + ' 님, ' + phrase );
}
//아래와 같이 함수에 인수를 넘겨줄 수도 있다.
setTimeout(sayHi, 1000, "홍길동", "안녕하세요."); // 홍길동 님, 안녕하세요. 출력

이 외에도 자바스크립트에서 css 스타일 꾸미는 코드는 지양하기.

html은 html에서, css요소는 css에서, 자바스크립트는 자바스크립트 상에서 코드 작성하기

setTimeout()

=> 코드를 나중에 실행하기 위한 용도로 사용

타이머 (설정해 놓은 시간) 가 만료된 뒤 함수나 지정된 코드를 실행한다

문법)

setTimeout(func|code, [delay], [arg1], [arg2], ...)

  • func|code
    실행하고자 하는 코드로, 함수 또는 문자열 형태입니다. 대개는 이 자리에 함수가 들어갑니다. 하위 호환성을 위해 문자열도 받을 수 있게 해놓았지만 추천하진 않습니다.

    함수를 실행하지 말고 넘겨라.
    무슨 뜻이냐면 setTimeout에 함수를 넘길 때, 함수 뒤에 () 을 붙이지 말라는 것. 괄호를 붙여서 전달하면 함수 실행 결과가 전달되어 버리기 때문이다
// 잘못된 코드
setTimeout(sayHi(), 1000);
  • delay
    실행 전 대기 시간으로, 단위는 밀리초(millisecond, 1000밀리초 = 1초)이며 기본값은 0입니다.
  • arg1, arg2…
    함수에 전달할 인수들로, IE9 이하에선 지원하지 않습니다.


위처럼 const 변수 선언 시 이어쓰기 위한 콤마 지양하기
세미콜론, 콤마의 오사용으로 오작동이 일어날 수 있음
에어비엔비 표준 스타일 가이드 참고


익명 함수에서 인자값 브라켓은 보통 function 구문 사이에 띄어쓰기

반대로,

기명 함수의 경우 인자 브라켓은 아래와 같이 붙이는 걸 추천




Element.classList

자바스크립트 상에서 직접 스타일을 제어하는 것은 한줄마다 브라우저 랜더링이 되기 때문에 권장하지 않는다. 성능과 자바스크립트와 스타일 사이의 역할 분리를 위해
css class를 통해서 제어하시는 걸 추천한다고 피드백 받았다.


지양하는 코드❌

고친 코드 ✅

<요소에 스타일을 적용할 수 있는 방법>

  1. <div class="..."> : 외부 스타일 시트
    html에서 class 값을 넣고, CSS에서 스타일 적용하기
  2. <h1 style="color:red;"> : 인라인 스타일
    태그에 직접 CSS코드를 기술하는 방식
    => html에 디자인적 요소가 섞임으로 정보로써의 가치가 떨어져 권장하지 않음
  3. 내부 스타일 시트
    html <head> 태그 사이에 <style></style> 태그를 삽입해서 그 안에 css 코드 작성

자바스크립트상에서도 클래스 수정이 가능한데,
style 보다 CSS 클래스를 수정하는 것을 더 우선시해야 하며, style클래스를 '다룰 수 없을 때’만 사용해야 한다.

클래스 속성 값 전체를 바꾸고 싶을 때는 className 을, 개별 클래스를 조작하고 싶을 때는 classList 를 사용하면 되는데 보통 classList를 많이 사용하는 듯 하다

classNameelem.className 에 무언가를 대입하면 클래스 문자열 전체가 바뀌고
속성 값 전체를 바꾸려는게 아닌 클래스 한나만 추가하거나 제거하고 싶은 경우에는 classList 를 사용하면 된다


Element.classList란?

element.className을 통해 엘리먼트의 클래스 목록에 접근하는 방식을 대체하는 간편한 방법이다.

html에서 class를 선언하지 않아도 classList를 사용해서 추가할 수 있다.

메서드

  • classList.add(String) : 클래스를 필요에 따라 삽입

  • classList.remove(String) : 클래스를 필요에 따라 제거

  • classList.replace(oldClass, newClass) : 존재하는 클래스를 새로운 클래스로 교체

  • classList.contains(String): 지정한 클래스 값이 엘리먼트의 class 속성에 존재하는지 확인
    이를 변수로 선언하여 값이 있는지 체크하고 , if 조건문을 사용하여 두가지 클래스를 공존 시킬 수 있음

  • classList.toggle(): 클래스값이 있는지 체크하고 없으면 더하고 있으면 제거, 위에서 말한 과정을 한번에 처리가능하다




style.cssText 이란?

element.style 은 객체이고 읽기 전용이기 때문에 div.style="color: red; width: 100px같은 방식으론 전체 스타일을 설정할 수 없다

문자열을 사용해 전체 스타일을 설정하려면 style.cssText 를 사용하여야 한다

element.style.cssText = `color: red;
    background-color: yellow;
    width: 100px;
    text-align: center;
  `;

style.cssText 를 사용하면 기존 스타일에 스타일을 추가하는 게 아니라 전체를 교체해버리기 때문에 잘 쓰이지 않는다. 사용하고 있는 스타일이 실수로 지워진다는 위험이 있을 수 있다.

아니면, div.setAttribute('style', 'color: red...') 를 사용해 속성을 설정해도 style.cssText 과 같은 효과를 볼 수 있다고 한다



그렇다면 Element.setAttribute() 는 무엇일까?

  • 지정된 요소의 속성 값을 설정하는데 사용된다
    속성이 이미 있는 경우 값이 업데이트 되고 그렇지 않으면 지정된 이름과 값으로 새 속성이 추가된다

속성의 현재 값을 얻으려면 getAttribute()
속성을 제거하려면 removeAttribute()를 호출하면 된다

Element.setAttribute(name, value);
name : 속성의 이름을 지정
value : 속성에 할당할 값을 쓴다. 문자열이 아닐 경우 자동으로 문자열로 변환된다

=> 속성을 제거하거나 없애기 위해 값으로 null을 설정하면 속성 값은 비문자열을 문자열로 반환하기 때문에 "null"이 된다. 때문에 제거를 원하면 removeAttribute() 를 호출해야한다

참고해서 보면 좋을 문서



함수로 만들면 재사용이 가능하기 때문에 다시 실행이 가능
되도록 하나의 함수에서는 하나의 역할만 하도록 분담해서 코드를 짜보는 습관 기르기

이번 과제 에서도 코드가 길어지지 않게 끊어서 효율적이게 작성하도록 노력하기
여러 상황을 함수를 응용해서 많이 만들어보는 습관 가지기

참고 문서) MDN


마지막으로 고쳐봐야하는 코드)

1)
누구의 턴인지 브라우저에 표시된 텍스트 컬러를 의존해 턴을 결정하는 방식은 dom 요소를 잡고 style에 매번 접근하기 때문에 다소 비효율적인 것 같습니다.

브라우저와 관계 없이, 최초 게임 시작시 누가 먼저 턴인지 미리 설정하고, 자바스크립트 내에서 true/false 변수를 사용해서 턴을 간단하게 제어할 수 있을 것 같습니다.

불리언 변수명에 대해서도 한번 더 체크하자 ❗❕

// 내가 작성했던 코드 ❌
function checkBox (event) {
  if (selectXButton.style.color !== "black") { 
	어쩌구 저쩌구..
    }
}

// 피드백 받은 코드 ✅
let isXPlayerTurn = true;

function checkBox(event) {
  if (isXPlayerTurn) {
    // ... Mark X player's symbol ...
    isXPlayerTurn = false;
  } else {
    // ... Mark O player's symbol ...
    isXPlayerTurn = true;
  }
}

2)
x, o 가 분명히 제대로 마크 되었는데도 승자판별에 대해 동작하지 않는 이유는 해당하는 구문이 다시 실행되지 않기 때문입니다.
즉, 현재는 localhost:1234를 들어가면 저 내용은 브라우저에서 딱 한번만 실행합니다.

// 수정 전 코드 ❌
if (result) {
  setTimeout(function () {
    restartAlert.textContent = `${result}님이 이겼습니다! 🎉`;
    restartButton.style.display = "flex";
      }, 300);
};

//수정 된 코드 ✅
let isXPlayerTurn = true;

function checkBox(event) {
  if (isXPlayerTurn) {
    // ... Mark X player's symbol ...
    isXPlayerTurn = false;
  } else {
    // ... Mark O player's symbol ...
    isXPlayerTurn = true;
  }

  const result = calculateWinner(squares);

  if (result) {
    restartAlert.textContent = `${result}님이 이겼습니다! 🎉`;
    restartButton.style.display = "flex";
    resetGame(); // 게임의 승자가 결정났기 때문에 게임이 리셋되어야하는 함수가 필요합니다.
  }
}
  • 승자판별이 다시 실행되려면 어떻게 해야할까요?
    -> 함수로 만들면 재사용이 가능하기 때문에 다시 실행할 수 있습니다.

  • 그럼 언제 승자판별이 다시 실행해야할까요?
    -> 물론 게임의 흐름을 보시면 두 플레이어 중 한명이 심볼을 마킹했을 때입니다. 즉, 해당 로직은 작성하신 checkBox함수에 들어가서 실행되어야합니다.


3) 로직에 대해서 다시 한번 정리해보는 것이 필요

예를 들어,

  1. X, O 중 누가 첫번째 턴이 될지 미리 결정한다. (누구의 턴인지에 대한 정보는 자바스크립트 내에서 true/false 값을 이용하여 변수를 만든다)

  2. 게임 시작을 할 수 있는 startGame 함수가 발동된다.

  3. 게임 시작을 하면 startGame 함수로 인해 게임 시작 버튼은 사라지고, 각 박스에 박스를 마킹하는 이벤트 리스너를 붙인다 (이렇게 하면, 게임 시작 전에 박스에 마킹되는 것을 미리 방지할 수 있습니다)

  4. 플레이어 클릭으로 인해 이벤트 리스너에 있는 checkBox 함수가 발동되면 콜백 함수의 event 인자의 className 프로퍼티의 번호를 확인하여 해당 번호와 누구인지 squares 배열에 기록한다. 그리고 브라우저에 각 플레이어 턴에 맞게 심볼을 마킹을 하고, 수정된 squares배열을 calculateWinner 함수에 전달하여 승자가 나왔는지 체크를 한다.

3-1. 승자가 없으면 승자 메시지 출력은 패스하고 다음 플레이어 턴으로 넘어간다

3-2. 승자가 있다면 승자 메시지 출력을 하고 게임을 리셋하는 resetGame 함수를 발동한다 -> resetGame 함수가 발동되면, 모든 박스에 있던 체크 표시는 다 지우고, 등록되어있던 이벤트 리스너를 삭제하고, 플레이어 턴을 초기화하며, 게임 시작 버튼을 다시 보이게 한다.

  1. 1로 복귀

0개의 댓글