Jindorry-Album [html, css, js] | Step 3.

진도리·2022년 3월 15일
0

Jindorry-Album

목록 보기
3/5
post-thumbnail

Process

  1. 어떻게 삭제 기능을 구현할지 ?
  2. API
  3. JS

index.html, index.css 는 달라진 부분이 없음!



1. 이미지 삭제

대부분의 갤러리앱에서 이미지를 삭제할 경우

  • 편집 -> 이미지 다수 선택 -> 삭제
  • 이미지 선택 -> 삭제

위 두 가지 과정이 보편적임

로컬서버에 이미지가 몇개 없기도하고, 이미지 각 별개로 삭제기능을 추가하는 것이 좀 더 구현하기 편할 것 같아서 이미지 선택 -> 삭제 의 방법으로 구현해 보기로 했음

└ 이미지를 받아오고 삭제하기까지의 과정

'onmouse' 이벤트로 인해 보여지는 삭제 아이콘을 클릭하면 해당 이미지를 삭제요청함



2. API

메소드경로요청데이터응답데이터설명
1GET/fileListyy:년도, mm:월fileList: 파일리스트서버에서 파일마다의 절대경로를 받아옴
2GET/fileidx: 인덱스fileList[idx]: idx번째 파일순서대로 파일을 하나씩 받아옴
3DELETE/fileidx: 인덱스fileList[idx]: idx번째 파일해당하는 파일을 삭제


3. JS

이미지에 마우스를 올리면, 이미지가 옆으로 옮겨지면서 숨겨진 아이콘들이 보여지게 하고 싶었음

└ 구상한 구조, 아래의 imgCard() 가 리턴하는 element

tag구분을 className 기준으로 한 것 처럼 보이는데, 실수로 아래 js 코드의 document.createElement()로 할당한 변수이름을 기준으로 tag를 구분했네요🤦‍♂️...🙇‍♂️🙇‍♂️🙇‍♂️

└ 실제 동작

위를 구현하기 위해 z-index로 z축을 설정하고, 'onmouse' 이벤트마다 <img> 의 위치를 변경해 주었음

받아온 fileList의 수 만큼 아래의 imgCard()로 요소생성

index.js 📝

const imgCard = (fileList, item, idx) => {
  let trashIcon = 'fa-solid fa-trash fa-2xl';
  let extenseIcon = 'fa-solid fa-up-right-and-down-left-from-center fa-2xl';
  let card = document.createElement('div');
  let space = document.createElement('div');
  let movingBlock = document.createElement('div');
  let img = document.createElement('img');
  let hiddenSpace = document.createElement('div');
  let hiddenDiv1 = document.createElement('div');
  let hiddenDiv2 = document.createElement('div');
  let hiddenIcon1 = document.createElement('i');
  let hiddenIcon2 = document.createElement('i');

  card.setAttribute("idx", idx);
  hiddenIcon1.className = trashIcon;
  hiddenIcon2.className = extenseIcon;
  hiddenDiv1.appendChild(hiddenIcon1);
  hiddenDiv2.appendChild(hiddenIcon2);
  hiddenSpace.append(hiddenDiv1, hiddenDiv2);

  img.src = URL.createObjectURL(item);
  img.alt = `loaded image num ${idx + 1}`;
  movingBlock.append(img, hiddenSpace);
  card.append(space, movingBlock);

  hiddenDiv1.className = 'hidden-div';
  hiddenDiv2.className = 'hidden-div';
  img.className = 'loaded-imgs';
  card.className = 'img-card';
  space.className = 'space';
  movingBlock.className = 'moving-block';
  hiddenSpace.className = 'hidden-space';

  card.style =
    'display : flex;position: relative;margin: 10px;width: 250px;height: 200px;z-index: 1;';
  space.style = 'width: 50px;';
  movingBlock.style = 'width: 220px; margin-right: 20vw;';
  img.style =
    'position: absolute;left: 50px;width: 200px;height: 200px;z-index: 2;object-fit: fill;border: 1px solid #000;';
  hiddenSpace.style =
    'position: absolute;left: 200px;width: 50px;display: flex;flex-direction: column;height: 100%;';
  hiddenDiv1.style =
    'display: flex;flex: 1;justify-content: center;align-items: center;margin-left: 5px;';
  hiddenDiv2.style =
    'display: flex;flex: 1;justify-content: center;align-items: center;margin-left: 5px;';
  movingBlock.addEventListener('mouseover', function () {
    this.firstChild.style =
      'position: absolute;left: 0px;width: 200px;height: 200px;z-index: 2;object-fit: fill;border: 1px solid #000;';
  });
  movingBlock.addEventListener('mouseout', function () {
    this.firstChild.style =
      'position: absolute;left: 50px;width: 200px;height: 200px;z-index: 2;object-fit: fill;border: 1px solid #000;';
  });
  hiddenIcon1.addEventListener('mouseover', function () {
    this.style = 'color: red;';
  });
  hiddenIcon1.addEventListener('mouseout', function () {
    this.style = 'color: black;';
  });
  hiddenDiv1.addEventListener('click', function(){
    if(confirm("정말로 이 사진을 삭제하시겠습니까?\n")){
      removeFile(fileList[idx]).then((result) => {
        	console.log(result);
        })
      });
    }
  });
  hiddenIcon2.addEventListener('mouseover', function () {
    this.style = 'color: red;';
  });
  hiddenIcon2.addEventListener('mouseout', function () {
    this.style = 'color: black;';
  });
  // 여기는 this를 통해 태그 속성을 이용하기위해 arrow 가 아닌 일반함수로 선언
  return card;
};

// 이미지 삭제
const removeFile = async (filePath) => {
  const response = await fetch(baseUrl + 'file', {
    method: 'DELETE',
    headers: {
      path: filePath,
    },
  });
  if (!response.ok) {
    alert("Error : Function Name 'removeFile'");
  }
  return response;
};
.
.
.


Conclusion

  1. 결론
  2. TakeAway
  3. Next Step?


1. 결론

  • 동적으로 화면을 변경하는 대부분의 로직이 js에 과부화 되어있음

    • 특히 스타일을 적용하기 위한 css 하나하나 element.style = '~'로 적용해주기 때문에 코드의 길이가 길어져 좋지 않은 코드가 되었음
    • index.js의 코드길이가 169줄이나 되니 가독성도 너무 떨어짐
  • 무엇보다 이미지를 삭제하면, 새로고침해서 다시 해당 년/월을 받아와야 이미지가 사라진것을 볼 수 있음

    • 받아온 이미지들의 상태를 반영해서, 상태가 변경될 때 마다 해당 컴포넌트를 업데이트 할 수 있는 형태로의 변경이 필요해보임
  • 모듈화를 통해 독립적인 동작별로 js 파일을 나누고, 본격적으로 CSR(Client Side Rendering)에 맞는 코드를 구성하려함


2. TakeAway

  • 삭제 아이콘 클릭이벤트로 이 사진을 정말로 삭제할 것인지 아닌지 체크하는 메세지 박스를 띄우려 했음

index.js 📝 ( 삭제 아이콘 클릭이벤트 부분만 )

hiddenDiv1.addEventListener('click', function(){
    if(confirm("정말로 이 사진을 삭제하시겠습니까?\n")){
      removeFile(fileList[idx]).then((result) => {
        console.log(result);
      });
    }
  });

위 아이콘을 클릭하면

이렇게 메세지 박스가 뜨는데 위 어느 버튼을 클릭하더라도

위 처럼 [Violation] 경고가 뜬다.

위 사진에서의 '1263ms', '1682ms' 는 위 'click' 이벤트로 실행되는 confirm() 의 메세지 박스에서 '확인' 또는 '취소' 버튼을 누를때 까지 걸리는 시간이었다.

그냥 무시해도 겉으로 보기엔 문제가 없겠지만 이러한 잔 경고라도 안뜨게 하고 싶었다.

문제를 해결하기 위해 해당 오류를 검색해보니, 리턴받는데 시간이 걸리는 함수는 비동기 함수로 작성해서 스크립트의 속도를 조금이라도 높이라는 의미였고,
크롬 브라우저의 개발자 모드에서 웹 개발자로 하여금 조금 더 웹의 성능을 향상시키도록 돕는 기능이었다. 경고라기 보단 약간 제안같은 느낌이랄까...?

confirm() 이 내 웹의 다른 동작을 막거나 지연시키는 것은 아니라 생각이 들어서 그냥 그대로 두었지만, 만약 위와 같은 [Violation] 이 발생하면 어떤 부분에서 발생한 것인지 체크해볼 필요는 있는 것 같다.



3. Next Step

  • 모듈화 및 사진 확대기능 추가

profile
매일 작은 보폭이라도 앞으로.

0개의 댓글