3개의 문 만들어보기

조 은길·2022년 5월 13일
0

Html & CSS

목록 보기
62/66
post-custom-banner

완성 작품

진행시 시행착오

  1. img 태그의 부모 태그인 img-box에 overflow: hidden; 을 줘서, 이미지가 움직일 때, 문의 영역 밖으로 이동하면 안 보이도록 하려고 했다.
    그런데, 여기서 예상치 못한 문제가 발생했는데 다음과 같다.

이렇게 3개의 문을 감싸고 있는 box-container 밖으로 나가면, overflow: hidden; 속성들이 먹히지 않았다.

그래서, box-container나 각 문의 영역을 담당하고 있는 box1, box2, box3들에게 overflow: hidden;을 줘봤는데, 이 경우 3D로 움직여야할 문이 영역 밖에서는 다 잘린다. => 문을 담당하는 div인 red-door에 overflow: visible;을 줘봤지만 먹히지 않았다. !important까지 먹여봤지만, 여전히 효과를 보지 못했다.

  • 해결방안
    결국, 이것저것 다 해보다가 img 태그의 부모 태그인 img-box에 overflow: hidden;과 함께 position: absolute;을 줘봤는데, 위와 같은 현상이 발생하지 않고 제대로 작동한다.
    솔직히, 그냥 해보다가 얼떨결에 된 거라... 왜 이게 되는지는 잘 모르겠다.
  1. 초창기 문을 담당하는 .red-door, .green-door, .blue-door을 만들 때, width:100% 와 height:auto;를 적용했었다. 이렇게 하면, width:100%에 맞게 height가 자동으로 조정된다고 해서 해봤더니, height: 0;로 출력됐다.
    => 왠만하면, auto 기능은 사용하지 말아야겠다. 문 레이아웃들이 출력이 안 되서 원인을 찾느라, 한참 걸렸다ㅠ

DOM 처리시 시행착오

  1. 배경화면이나 다른 문을 클릭시, 열려있는 문이 있다면, 닫히고 이미지가 사라지게 하는 작업을 해줘야했다.
    그래서 맨 처음 접근한 방식은 배경을 클릭하면, classList.remove를 통해 열여있는 문이 있으면 닫히게 하는 방식을 사용해봤다.

if( container.classList.contains("container") ){
 	door.classList.remove("door-open"); 
  ... 이런 식으로
}

문제는 이 if절 구문이 작동하지 않았다. ! 표를 써서 반대로도 실행해봤으나, 작동되지 않아서 고민 끝에 다른 접근법을 사용했다.

  • 문제 해결법
    for문을 돌려서, img태그와 door 클래스를 가진 태그들을 다 짚어서, 내부에 door-open이나 img-open이 있다면, 지워주는 방식을 사용했다. 결과는 성공적이었고, 문제를 해결할 수 있었다.

1차 리펙토링

for 문을 2번이나 돌려서 해결하는 방식은 쿼리로 잡아야하는 태그의 갯수가 많아지면 많아질 수록 로딩을 느리게하는 원인이 된다.

그래서, for문을 사용하지 않는 방법으로 바꿔봤다.

중요한 점은 문은 항상 딱하나만 열려있다는 점이다.

  • 기존 코드
function remove_class() {
  const doorAll = document.querySelectorAll(".door");
  for (let i = 0; i < doorAll.length; i++) {
    const element = doorAll[i];
    if (element.classList.contains("door-open")) {
      element.classList.remove("door-open");
    }
  }

  const imgAll = document.querySelectorAll("img");
  for (let i = 0; i < imgAll.length; i++) {
    const element = imgAll[i];
    if (element.classList.contains("img-open")) {
      element.classList.remove("img-open");
    }
  }
}
  • 리펙토링한 코드

function remove_class() {
  const Currentdoor = document.querySelector(".door-open");

  if (Currentdoor) {
    Currentdoor.classList.remove("door-open");
  }

  const Currentimg = document.querySelector(".img-open");

  if (Currentimg) {
    Currentimg.classList.remove("img-open");
  }
}

또한, 기존에 전역변수로 선언되있던 변수들을 전부 익명 실행함수로 만들어줘서 접근할수 없게 만들었다.

2차 리펙토링

DOM에 접근하는 거는 연산 속도가 가장 느린 것 중에 하나이다.

그런 이유로, 다른 방법으로 리펙토링 해보는 것도 좋을 것같다.

ClassList에 의존하는 방법이 아닌, 좀 더 범용성이 높은 방법을 찾아보자!!

(function () {
  const container = document.querySelector(".container");

  let Currentdoor;
  let Currentimg;

  function container_control(e) {

    remove_class(Currentdoor, Currentimg);

    const nearest_door = e.target.closest(".door");
    if (!nearest_door) return;
    const nearest_img = e.target.nextElementSibling.firstElementChild;
    if (!nearest_img) return;

    nearest_door.classList.add("door-open");
    // 쿼리셀렉터를 쓰지않고, 열려있는 문을 잡아냄
    Currentdoor = nearest_door;

    nearest_img.classList.add("img-open");
    // 쿼리셀렉터를 쓰지않고, 잡아냄
    Currentimg = nearest_img;
  }

  container.addEventListener("click", container_control);
})();

function remove_class(Currentdoor, Currentimg) {
  // const Currentdoor = document.querySelector(".door-open");

  if (Currentdoor) {
    Currentdoor.classList.remove("door-open");
  }

  // const Currentimg = document.querySelector(".img-open");

  if (Currentimg) {
    Currentimg.classList.remove("img-open");
  }
}

3차 리펙토링

단일 책임 원칙 (Single responsibility principle)

단일 책임 원칙이란 하나의 객체는 반드시 하나의 동작만의 책임을 갖는다는 원칙이다.

모듈화가 강해질수록 다른 객체와의 의존/연관성이 줄어든다. 반대로 이야기하면 모듈화가 약해질수록 다른 객체와의 의존/연관성은 크게 늘어나며, 최악의 경우 어떠한 은닉화 정책도 존재하지 않아 모듈의 메소드에 무분별하게 접근할 수도 있게된다.

객체가 담당하는 동작. 즉, 책임이 많아질 수록 해당 객체의 변경에 따른 영향도의 양과 범위가 매우 커진다. 단일 책임 원칙은 특정 객체의 책임 의존성 과중을 최대한 지양하기 위한 원칙이다.


이 단일 책임 원칙으로 현재 코드를 바라보면, 하나의 이벤트 리스너 함수가 너무 많은 역할을 담당하고 있다.



이벤트 리스너 함수는 최대한 간결하게 작성하자!!
그래야 코드가 유연해진다.

즉시실행 익명함수

(function () {
   코드 내용...
})();

팀원들과 변수명이나 함수명의 중복을 막기 위해, 미리 이름을 정해놓으면 크게 문제가 없기는 하지만, 그런 경우가 아니라면, 전역 변수 사용을 최소하기 위해서, 즉시실해 익명함수를 사용하는 습관을 들이자!!
=> 이 로직을 사용한 이후로, 어지간한 전역 변수 사용은 막을 수있었다.

해당 github 링크

profile
좋은 길로만 가는 "조은길"입니다😁
post-custom-banner

0개의 댓글