일단 우여곡절 끝에 1차 배포를 한 후, 열흘쯤 전에 회사에 보다 더 가까운 곳으로 이사를 했다. 이사 후 뒷정리는 해도 해도 끝이 없어서 본의 아니게 이사 후 일주일은 아주 칼퇴를 해버렸다.
그러고 나서 주말에 좀 쉴까 했더니 우리집 고양이(라고 쓰고 읽을 땐 주인님)가 이사 후유증 때문인지 병을 얻으셔서 신경 쓰느라 주말도 순삭. 아니 다시 월요일이잖아!?
TIL 쓰는 건 고사하고, 일하면서 찾아낸 고귀한 링크들을 북마크만 해놓고 제대로 읽어보지도 못했다. 간단한 것이더라도 하나하나 차근차근 다시 풀어갈 생각이다.
회사에서는 2차 배포를 준비하고 있다. 사실 지난 주에도 쉬어가는 느낌으로 중간 배포를 한번 했어야 했는데 어쩌다 보니 작업이 계속 완결되지가 않아서 흐지부지 되고 말았다. 이번주는 좀 더 치열하게 해보자, 하고 시작했는데 그것도 참 마음대로 되지 않는다. 시도 때도 없이 맞닥뜨리게 되는 이 에러들을 능숙하게 핸들링할 그날이 언젠가는 올까..?
오늘 이전에 배운 것
오늘은 기억에 남아 있으면서 간단한 것부터 적겠다. 방법이야 정하기 나름이겠지만 클릭 같은 이벤트를 발생시키면 특정 텍스트를 클립보드에 복사하는 코드가 필요한 적이 있었다. 정확히 말하자면 내가 복사할 데이터는 브라우저 주소창에 들어가 있는 현재 페이지의 URL이었다. 페이지에 실제로 보여주지는 않을 가짜 input을 만들고 거기에 복사할 데이터를 넣은 다음, 그 데이터를 선택해서 복사한 후 만들었던 가짜 input은 바로 없애버리는 식으로 작동시키는 방법이다. 이 코드를 실행하고 나면 어디에 붙여넣기를 해도 내가 코드로 복사한 텍스트가 나온다.
근데 이걸 vscode에 입력하고 나면 자꾸만 경고창이 뜬다. Document.execCommand()가 존재하지 않는다고 했었나, 아무튼 쓸 수 없다는 것이다. 그래도 일단 작동은 하는데, MDN에 따르면 이미 적용되지 않는 브라우저가 있다고 한다. MDN의 Browser compatibility를 참고하면 클립보드로 복사하는 데 사용하는 copy command 정도는 아직 브라우저 상관없이 지원된다. 하지만 어쨌든 deprecated라는 것... 조만간 사용할 수 없게 되지 않을까 싶다.
그리고 MDN에서도 설명하듯이, execCommand 대신 Clipboard API를 사용하라고 한다. 아래 링크에서는 자바스크립트에서 제공하는 Clipboard API를 이용하는 방법을 설명한다. 하지만 이건 또 새롭게 등장한 방법이므로 역시 지원되지 않는 브라우저가 있고, 구버전은 당연히 지원하지 않는다. 현재로서는 execCommand와 Clipboard API를 병용하는 게 나을 것 같다.
일이 엄청 많거나 너무 바쁜 건 아닌데, 그렇다고 하루하루 하는 일이 차근히 정리되고 있는 것 같진 않다. 사이트 개편 앞두고 일종의 마무리 작업 중이라서 그런 건지, 항상 느끼는 거지만 마치 깔끔하게 치워놓은 방이 어질러지듯이 처음엔 시작이 얼마나 정돈되었든 뒤로 갈수록 '일단 하고 본다'는 식의 임시방편성 코드가 많아지게 된다. 내 코드 내가 읽어도 정신이 하나도 없다.
하루종일 허둥대며 코드를 짜다 보면 퇴근하고 나서는 생산적인 일은 별로 하고 싶지 않다. 그래서 요 며칠 TIL도 안 남기고 아무런 의미 없는 시간을 보냈는데, 또 다른 분들 글을 읽고 나면 나는 지금 뭐하나 싶다. 잠깐 해찰하며 여유를 가졌던 것에 만족해야겠다. 슬슬 다시 힘을 내야지.
오늘은 동영상 인코딩 처리를 위한 큐를 구현하는 데 (완벽하게 성공했다고 장담할 수 없지만) 어떤 방법을 써야 할지 고민하면서 찾아봤던 반복문 사용의 차이점을 링크로 건다.
오늘 배운 것
for ... in 반복문에 대한 링크. for ... in 을 통해 직접적으로 가져올 수 있는 건 객체의 key-value 중 key이다. 객체의 요소들을 순서대로 가져온다는 보장이 없으므로 인덱스가 중요한 배열 등에 사용하는 것은 권장되지 않는다.
for ... of 반복문은 문자나 배열에 사용한다. 배열 안의 요소 자체를 가져온다. 아래 링크에 예시 코드와 함께 for ... in 과 for ... of 의 차이점이 잘 정리되어 있다. 나중에 다시 한번 읽어봐야 할 것 같다.
반복문들의 차이점에 대해 "한글로" 잘 정리해둔 곳을 찾았는데 뭐가 문제인지 모르겠지만 지금은 안 열린다(?!) 혹시 나중에 잘 뜰지도 모르니 일단은 저장..
현재의 프로덕션 페이지에서는 파일을 첨부하면 즉시 s3에 들어가는데, 첨부한 파일이 사용자가 실제로 제출하기를 원치 않는 것이었다 할지라도 무조건 업로드 된다. 물론 오늘 구현한 기능도 첨부할 파일 목록에서 사용자가 삭제할 수 있는 것까지는 포함하지 않지만, 이것도 언젠가는 추가되어야 하지 않을까 추측해본다.
아무튼 이번에는 사용자가 파일을 첨부하면 파일 데이터를 리덕스에 저장해놨다가, 제출 버튼을 누르면 리덕스에 저장된 데이터를 이용해 그때서야 s3로 넘어가게 했다.
오늘 배운 것
오늘 하루종일 열심히 이용한 SDK란 무엇인가에 관한 링크
AWS SDK for JavaScript 링크. 여기서 Uploading a file to an Amazon S3 bucket 항목을 참고했다.
자바스크립트는 싱글 스레드 언어이므로 한 번에 한 가지 작업을 처리하지만, 비동기로 동작하면 동시에 여러 작업을 수행할 수 있다.
비동기 동작 원리
call stack에 함수가 추가되어 실행 → 브라우저가 제공하는 web API 호출 → call stack에 추가된 함수는 제거되지만 함수가 전달한 콜백함수가 callback queue에 추가 → event loop는 call stack을 계속 감시하고 있다가 call stack이 빈 것을 보고 callback queue를 확인 → event loop는 callback queue에 추가된 콜백함수를 발견하고 call stack에 추가 → 콜백함수 실행
이벤트 루프(Event Loop)
call stack이 비어 있을 경우, callback queue에서 함수를 꺼내 call stack에 추가한다.
한 요소에 이벤트가 발생하면, 최상단의 조상 요소까지 계속해서 부모 요소들의 핸들러가 동작한다.
거의 모든 이벤트는 버블링 된다.
이벤트가 발생한 가장 안쪽의 요소는 target이며, event.target으로 접근할 수 있다. event.currentTarget(=this)는 핸들러가 실제로 할당된 요소이다.
버블링 중단하기
이벤트 버블링은 target에서 시작해 document 객체 또는 window 객체를 만날 때까지 각 노드에서 모두 발생하며, 그 과정에서 모든 핸들러가 호출된다. 핸들러가 이벤트를 처리한 후에 버블링을 중단하도록 하려면, event.stopPropagation()을 사용한다. 하지만 반드시 필요한 경우가 아니라면 버블링을 막는 것은 권장되지 않는다.
이벤트 캡처링(Event Capturing)
이벤트 버블링 이외에도 이벤트가 하위 요소로 전파되는 단계인 캡처링이 있다.
캡처링 단계에서 이벤트를 잡아내려면 addEventListener capture 옵션을 true로 설정한다. capture 옵션의 값이 false(default 값)일 때에는 버블링 단계에서 동작한다.
elem.addEventListener(..., {capture: true})
// 아니면, 아래 같이 {capture: true} 대신, true를 써줘도 됩니다.
elem.addEventListener(..., true)
// 예를 들면, 이렇게!
elem.addEventListener("click", e => alert(`캡쳐링: ${elem.tagName}`), true);
elem.addEventListener("click", e => alert(`버블링: ${elem.tagName}`));
addEventListener(..., true)로 할당된 핸들러는 removeEventListener(..., true)를 같은 단계에 설정하면 지워진다.
현재 이벤트의 흐름 단계를 알고 싶다면, event.eventPhase로 반환되는 정숫값을 확인하면 된다. (1=캡처링, 2=타깃, 3=버블링)
기분이 너무너무 바닥을 쳤던 어제에 비하면 오늘은 컨디션이 그나마 나았다. 여세를 몰아서 상세 페이지에서 게시글을 수정하고 삭제하는 기능을 붙였다. 삭제할 때는 게시글 내용은 물론, 게시글과는 별도로 스토리지에 저장되는 이미지 파일까지 함께 삭제할 수 있도록 디스패치를 붙였다. 어제 실패했던 무한스크롤도 차근차근 다시 하니 언제 그랬냐는 듯 잘 작동했다. 답안 코드를 보고 거의 그대로 따라 작성하긴 했지만 상품마다 찜을 누를 수 있는 기능도 추가했다. 하지만 찜을 누르고 나면 회색이었던 하트 모양이 분홍색으로 변하기는 하는데, 컴포넌트 리렌더링 없이는 찜 개수에 1이 더해지지를 않았다. 불필요하게 리렌더링 할 필요 없이 하트가 들어있는 컴포넌트만 부분적으로 리렌더링 하고 부모 컴포넌트에는 영향을 미치지 않으면 좋겠는데 그게 생각처럼 쉽게 되지 않았다. 결국 찜을 눌렀으면 원래의 찜 개수에서 1을 더하는 식으로 조건문을 사용해서 표면적으로 해결하기는 했는데 이것도 꼭 시간 날 때 다시 구현해보고 싶다.
실시간 알림 및 알림 페이지를 보여주는 기능과 게시글을 작성할 때 게시글의 레이아웃을 미리 사용자가 고를 수 있게 하는 기능은 시간 문제로 과감하게 버릴 수밖에 없었다. ㅠㅠ 과제 필수사항도 전부 포함하지 못해 아쉬웠다.
지난번에도 그랬던 것 같은데, 이번에도 배포 전에 로컬에서 돌렸을 때는 특별한 이상이 없었고 그래서 미련 없이 배포를 했다. 배포가 완료된 후 시험 삼아 들어가 본 페이지에는 각종 CSS를 준 태그들의 위치가 뒤틀려 있었고, 잘만 돌아가던 무한스크롤마저 무한로딩에 걸려 다음 페이지를 불러오지 못하고 있었다.. 태그는 급히 수정했고, 무한스크롤도 한 번에 불러오는 게시글 개수를 일단 조금 늘려놓긴 했지만 아직도 마음이 아프다ㅠㅠ http://market-ob.shop/
내일 할 일
내일은 주특기 주간이 모두 끝나고 다시 새로운 협업 프로젝트 주간이 돌아오는 날이니만큼 프로젝트 진행에 대한 계획을 잘 짜야 할 것 같다. 주특기 심화 과제조차 온전하게 해내지 못한 내가 무슨 프로젝트를 한다는 건가 싶기는 하지만... 일단 열심히 해보자.