오늘 한 일

  • 엊그제 만들어놓은 이벤트리스너가 겉보기엔 문제 없이 잘 동작하는데, 영상 몇 개가 재생되고 난 후 콘솔에 찍히는 로그를 보면 기함하게 된다. 동일한 단 하나의 타겟에 붙인 이벤트리스너가 여러 번 실행되면서 콜백함수에 넣어둔 console.log()가 거듭제곱으로 늘어난다. 소오름
  • 영양가 있는 해결책을 찾았지만 사실 근본적인 문제는 내가 짠 코드의 구조에 있었던 것 같다. 처음에는 once: true 옵션 덕에 해결됐다고 생각했으나, 그와 동시에 함수의 전체적인 구조를 바꾸고 나니 해당 옵션을 제거하고도 같은 개선된 결과가 나왔다.
  • 하지만 개선이라고 해봤자 거듭제곱은 아니더라도 영상 재생 1회당 이벤트리스너가 두 번 실행되는 정도.. 물론 거듭제곱보다야 낫다. 이건 좀 더 공부해봐야 할 것 같다.

오늘 배운 것

  • addEventListener(type, function, {once: true})를 나에게 알려주신 링크님
 

[자바스크립트] 한 번만 실행되는 Event Listener

가끔 onclick, onerror 등의 이벤트가 한 번만 실행돼야 할 때가 있습니다. 가령 이미지에 에러가 있을 때 그 이미지를 다른 이미지로 교체하는 함수를 만들었을 때, 교체된 이미지에도 에러가 있다

marshall-ku.com

  • MDN의 addEventListener()에 대한 설명. 근데 나 이거 분명 꽤 들여다봤는데, 그래서 options의 capture와 passive도 분명 봤는데, 그 둘 사이에 있던 once를 못 봤다고!? 진짜로!?ㅠㅠ
once
A boolean value indicating that the listener should be invoked at most once after being added. If true, the
listener would be automatically removed when invoked.
 

EventTarget.addEventListener() - Web APIs | MDN

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

developer.mozilla.org

오늘 하루종일 한 삽질과 함께 오늘 배운 것

  • 간단한 것부터 시작 사파리 브라우저에서 개발자 도구 열기
상단 메뉴바 -> Safari -> 환경설정 -> 고급 -> '메뉴 막대에서 개발자용 메뉴 보기' 체크 -> 상단 메뉴바에 생성된 [개발자용] 메뉴에서 '페이지 소스 보기' 클릭 또는 브라우저에서 마우스 우클릭 후 '페이지 소스 보기'
  • 지난 몇 주에 걸쳐 드문드문 작업한 결과 동영상 인코딩 라이브러리인 ffmpeg을 리액트에 잘 옮겨심었지만, 기본 브라우저로 사용하는 크롬에서만 잘 돌아가고 오늘 테스트 해본 사파리에서는 전혀 작동하지 않았다. 이건 다 사파리가 ffmpeg 작동에 필요한 sharedArrayBuffer를 지원하지 않기 때문이다.
 

Shared Array Buffer | Can I use... Support tables for HTML5, CSS3, etc

Type of ArrayBuffer that can be shared across Workers.

caniuse.com

  • sharedArrayBuffer가 궁금하다면, 솔직히 MDN 설명은 무슨 말인지 하나도 모르겠고, 그 아래 링크는 2017년도 글이지만 이해하기에는 더 좋을 것 같다. arrayBuffer와 sharedArrayBuffer의 느낌 차이를 잘 잡아준다. 사실 이 둘에 관한 설명은 생각날 때마다 구글링해보지만 아직 잘 모르겠다..
 

SharedArrayBuffer - JavaScript | MDN

SharedArrayBuffer 객체는 제네릭, 고정된 길이의 원시 바이너리 데이터 버퍼를 표현하는데 사용됩니다. ArrayBuffer 객체와 유사하지만, 공유된 메모리상의 뷰를 생성하는데 사용될 수 있습니다. Array

developer.mozilla.org

 

만화로 소개하는 ArrayBuffer 와 SharedArrayBuffer ★ Mozilla 웹 기술 블로그

이 글은 3부작 시리즈의 두번째 글입니다. 메모리 특강 만화로 소개하는 ArrayBuffer 와 SharedArrayBuffer Atomics 를 이용해서 SharedArrayBuffer 레이스 컨디션 피하기 지난 글에서는, JavaScript 같은 메모리 자

hacks.mozilla.or.kr

  • ffmpeg 깃허브 저장소를 들어가봐도 sharedArrayBuffer를 지원하는 브라우저에서만 작동한다고 적혀 있다. 지원하는 브라우저에서도 cross-origin isolation이 보장되어야만 정상적으로 기능한다. 
 

GitHub - ffmpegwasm/ffmpeg.wasm: FFmpeg for browser and node, powered by WebAssembly

FFmpeg for browser and node, powered by WebAssembly - GitHub - ffmpegwasm/ffmpeg.wasm: FFmpeg for browser and node, powered by WebAssembly

github.com

 

출처 간 격리를 이용하기 위한 가이드

출처 간 격리를 이용하면 웹 페이지에서 SharedArrayBuffer와 같은 강력한 기능을 사용할 수 있습니다. 이 문서에서는 웹사이트에서 출처 간 격리를 이용하는 방법을 설명합니다.

web.dev

  • cross-origin isolation은 헤더를 통해 설정할 수 있다고 한다. 아래 링크 게시글 작성자 분은 리액트를 nginx로 돌리면서 거기에 헤더를 설정했다.
 

How to fix SharedArrayBuffer is not defined error - TechKBlog

Came across this "SharedArrayBuffer is not defined" error in Firefox browser, while working on a react app of mine. This is how I fixed it.

techkblog.com

  • 난 nginx는 써본 적도 없었고, 인코딩 하나 때문에 그렇게까지 하고 싶지는 않았다. 이사님도 물론 같은 생각이셨고. 그래서 혹시 우리가 프론트 배포에 사용하는 aws s3로는 커스텀 헤더 설정이 가능한지 찾아보았다. 응 안돼
 

Custom headers on Amazon S3

Is it possible to have custom headers on Amazon S3 with arbitrary naming? For example, I am using a CDN pointing to Amazon S3 as the origin server, and in order to enable advanced functionality on ...

stackoverflow.com

  • 구글링하다가 나온 답은 netlify로 배포하는 거였다. netlify로 배포하면 커스텀 헤더 설정이 가능하다고 하며, 실제로 그렇게 사용한 사람들이 있다. netlify 공식문서에도 헤더 설정 방법이 적혀 있다. 희망이 보이는 듯했다.
 

Open Server To Avoid 'SharedArrayBuffer will require cross-origin isolation' - Ffmpegwasm/Ffmpeg.Wasm

Hi, thank you for your library, it's awesome, I want to ask is there any CDN like unpkg or cdn that has a custom header request Cross-Origin-Embedder-Policy: require-corp and Cross-Origin-Opener-Policy: same-origin? Thank you

issueexplorer.com

 

Custom headers

Netlify builds, deploys, and hosts your front end. Learn how to get started, see examples, and view documentation for the modern web platform.

docs.netlify.com

  • netlify로 배포하는 데만도 시간을 엄청나게 썼다. 누가 netlify 배포 쉽고 간단하다고 했어? 컴파일 에러부터 빌드 커맨드 에러, 아주 갖가지 에러를 다 만나고, 심지어 배포 시도하기 전에는 내 개인 저장소가 아니라고 배포 대상 저장소에 뜨지도 않았다. 결국 회사 저장소를 포크해서 내 저장소로 옮겨놓고 거기서부터 시작했다. 저장소가 두 개가 되니 git remote를 끊었다 연결했다 아주 난리도 아니었다ㅋㅋ 우여곡절 끝에 배포하고 나서 헤더 설정은 프로젝트 루트 디렉토리 내 netlify.toml 파일을 만들어서 그 안에 적어놔야 했다. 그런데 이거 프로젝트 루트 디렉토리에 넣어야 한다는 걸 왜 구글링해서 따로 찾아야 하는 거니ㅠㅠ
 

CORS issue with React App

Hi @hrishikesh, You are right to say that it is not in my repo. When building the app, it automatically removed it from the folder. What I did then, is to add it manually to the folder after the build operation. Seeing that it wasn’t working, I deleted i

answers.netlify.com

  • 파이어폭스 테스트 기준, 백엔드 서버에서 API 응답과 함께 내려주는 헤더에는 cross-origin isolation이 들어 있어도 sharedArrayBuffer가 제대로 기능하지 않는다. netlify에 따로 설정한 커스텀 헤더를 통해야만 진정한 isolation이 실현되는 것 같다. 그러나 사파리는 어쨌든 어떤 상황에서든 일관적으로 작동하지 않았다.

오늘 한 일

  • 타입스크립트 공부는 못했다ㅠㅠ
  • 웹페이지 메인에 동영상 띄우는 것과 관련해서 체크하고 넘어가야 할 것들이 꽤 있어서 하루종일 거기에만 시간을 쏟았다. 의외로 허무한 데서 해결되어 버린 게 있어서 시간을 투자한 만큼의 성과가 있었는지는 미지수다.
  • 자동재생으로 띄워놓은 영상이 종료되면 그 다음 영상 목록들을 뒤져서 재생 우선순위에 맞는 것을 찾아야 한다. video 태그에 id를 주고, 그걸 getElementById로 가져와서 변수에 할당한 다음, 거기에 addEventListener('ended', function) 형식으로 함수를 붙인다. 그러면 영상이 종료되는 'ended' 타입의 이벤트를 감지할 수 있다.

오늘 배운 것

  • ISO 8601 형식으로 나타내는 표준시는 아무런 처리를 하지 않는다면 국제표준시 기준으로 나온다. 당연한 건데 이걸 생각 못해서 삽질이 길어졌다...
 

Date.prototype.toISOString() - JavaScript | MDN

The toISOString() method returns a string in simplified extended ISO format (ISO 8601), which is always 24 or 27 characters long (YYYY-MM-DDTHH:mm:ss.sssZ or ±YYYYYY-MM-DDTHH:mm:ss.sssZ, respectively). The timezone is always zero UTC offset, as denoted by

developer.mozilla.org

 

오늘 한 일

  • 회사 웹페이지 1차 개편을 위한 막바지 작업을 하고 있다. 아니, 감히 막바지라고 말해도 되는지 잘 모르겠다. 아무튼, 아직은 기능이 별로 없어 환경에 따라 크게 달라지는 점은 없지만 환경별 설정 분기하는 코드도 좀 들여다보고, 기획자 분께 ip 주소 드리고 보여드리는 시늉이라도 조금 해보았다. 테스트를 포함한 모든 본격적인 건 내일부터 시작일 테지...
  • 저녁을 먹고 나서는 어제까지 이론적으로 열심히 공부한 타입스크립트를 기초적이나마 연습해보는 시간을 가졌다. CRA 없이 일단 타입스크립트만 설치해서 어떤 식으로 타입을 명시해줘야 하는지, 에러 로그는 어떻게 찍히는지, 또 그것들을 어떻게 활용할 수 있는지 직접 입력해보며 확인했다. 역시 직접 해보는 게 최고다.

오늘 배운 것

  • 프로젝트 디렉터리 내 package.json에서 환경별로 실행이나 배포 명령어를 따로 설정해놓을 수 있다는 걸 배웠다. 프로덕션 환경으로 진행하고 싶으면 해당 명령어를 입력하고, 그 명령어로 인해 콘솔 로그가 전부 숨겨진다든지 하는... 엄청난... 난 왜 몰랐을까
  • 타입스크립트 연습에 참고한 링크는 '벨로퍼트와 함께하는 모던 리액트'다. 평소에 많이 참고하는 링크지만 여기서 타입스크립트까지도 다루고 있는지 몰랐다.
 

1. 타입스크립트 연습 · GitBook

01. 타입스크립트 연습 타입스크립트에서 가장 기본적인 것들을 연습해보겠습니다. 먼저 새로운 자바스크립트 프로젝트를 생성해보겠습니다. 터미널에서 다음 명령어들을 입력하세요. $ mkdir ts-

react.vlpt.us

타입스크립트 핸드북(한글) 링크

 

타입스크립트 핸드북

 

joshua1988.github.io

주의 깊게, 다시 볼 부분

  • 여러 인터페이스를 상속받는다는데 두 번째 예시에서 왜 Developer는 Person만 extends하는가? -> Drinker가 그냥 빠진 것이었다니!
 

인터페이스 | 타입스크립트 핸드북

인터페이스 인터페이스는 상호 간에 정의한 약속 혹은 규칙을 의미합니다. 타입스크립트에서의 인터페이스는 보통 다음과 같은 범주에 대해 약속을 정의할 수 있습니다. 객체의 스펙(속성과 속

joshua1988.github.io

  • 딱 와닿게 이해되지 않는 제네릭 부분... 두 번 더 봐야겠다.
 

제네릭 | 타입스크립트 핸드북

제네릭(Generics)의 사전적 정의 제네릭은 C#, Java 등의 언어에서 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징입니다. 특히, 한가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트를

joshua1988.github.io

  • 순차적으로 코드를 깔끔하게 정리하는 과정이 너무나 인상깊었다.
 

맵드 타입 | 타입스크립트 핸드북

맵드 타입(Mapped Type)이란? 맵드 타입이란 기존에 정의되어 있는 타입을 새로운 타입으로 변환해 주는 문법을 의미합니다. 마치 자바스크립트 map() API 함수를 타입에 적용한 것과 같은 효과를 가

joshua1988.github.io

  • 모듈 부분은 (연습이든, 아니든) 실제로 프로젝트에 적용할 때 다시 한 번 찾아봐야 할 것 같다.
 

모듈 | 타입스크립트 핸드북

소개 타입스크립트에서 가리키는 모듈이라는 개념은 ES6+의 Modules 개념과 유사합니다. 모듈은 전역 변수와 구분되는 자체 유효 범위를 가지며 export, import와 같은 키워드를 사용하지 않으면 다른

joshua1988.github.io

오늘 한 일

  • 어제 오후부터 회원가입과 로그인 절차에 대한 전체적인 테스트를 (혼자) 해보고 있었는데, 퇴근 직전부터 회원가입 페이지에서 이메일을 입력하면 날아오는 인증메일이 발송되지 않았다. 회원가입 페이지를 완료한 지가 며칠이 지나서 그동안은 확인해볼 일이 없었는데 오랜만에 해보니 갑자기 안되는 것이었다. 메일은 오지도 않고 콘솔창에는 "Email address is not verified. The following identities failed the check in region US-EAST-1: id@email.address"라고 에러 메시지가 찍히는데 이것만 보고는 무슨 상황인지 이해할 길이 없었다. 구글링해봐도 다들 나와는 다른 상황인 것 같고 별로 참고할 만한 내용이 없었다. 무슨 에러인지 알고 나서야 뒤늦게 스택오버플로우에 있던 해결책이 보였다.
  • 사용자 인증을 AWS cognito를 통해 처리하고 있다. cognito에서 인증메일을 보내는 방식은 cognito 자체에서 보내주는 디폴트 설정과 AWS SES를 통해서 보내는 설정, 두 가지 중 선택할 수 있다. 처음에는 디폴트 설정으로 진행했었는데, 그러면 발신 주소가 no-reply@verificationemail.com이라는 별로 예쁘지 않은 걸로 자동 설정된다. 이사님이 이걸 좀 더 보기 좋은 계정으로 바꾸려고 하셨는데, 이 FROM email address를 바꾸려면 반드시 디폴트가 아닌 AWS SES를 이용해야 하기 때문에 이 설정을 바꾸셨다.
  • 디폴트로 설정을 돌려놓으면 다시 인증메일이 제대로 오기 시작하고, AWS SES만 선택하면 다시 에러가 떴다. 에러 메시지에 나온 것처럼 이메일 주소를 확인되게 하려면 AWS SES의 해당 리전에 접속해서 직접 처리해야 한다. 처리한 후에는 확인한 이메일 주소에 인증메일을 보낼 수 있게 된다.
  • 하지만 여기서 문제: 회원가입을 하고 싶어하는 사용자가 입력하는 사용자의 이메일 주소인데, 그리고 이건 불특정 다수에게 발송될 메일인데, 이 메일을 받을 그 모두의 이메일 주소를 등록해야 한다고? 그럴 리가 없다.
  • 이 문제의 근본적인 원인은, AWS SES를 처음 사용하면 계정이 샌드박스에 들어간다는 데 있었다. 누구에게 어떤 메일을 보낼지 알 수 없는 AWS 입장에서는 콘솔에서 인증 처리를 거치지 않은 이메일 주소에는 어떤 메일도 발송할 수 없게 제한해둔 것이었다. 물론, 메일을 보낼 발신자의 주소 역시 인증을 거쳐야 한다.
  • 한 마디로, 인증메일에서 no-reply@verificationemail.com이 발신자 주소로 찍히는 게 보기 싫어서 이 주소를 바꾸고자 한다면 반드시 AWS SES에 연결하고 + AWS SES 계정을 샌드박스에서 나가게 해야 한다. 여기에까지 이르느라 시간을 얼마나 썼는지

오늘 배운 것

  • 내가 맞닥뜨린 오류는 아래 링크에서 'Email address is not verified' 부분에 해당한다.
 

Amazon SES 이메일 전송 오류 - Amazon Simple Email Service Classic

Amazon SES는 여러 AWS 리전에 엔드포인트가 있으며 이메일 주소의 확인 상태는 AWS 리전마다 서로 다릅니다. 사용하려는 AWS 리전에서 각 발신자에 대해 확인 프로세스를 완료해야 합니다.

docs.aws.amazon.com

  • '이메일 계정 구성' 또는 '사용자 풀에 대한 이메일 구성' 항목에서 2단계(Amazon SES 샌드박스에서 계정 이동)를 참고하면 좋다.
 

Amazon Cognito 사용자 풀의 이메일 설정 - Amazon Cognito

이러한 단계에서 생성하는 리소스는 AWS 계정에서 공유할 수 없습니다. 예를 들어 사용자 풀을 구성한 한 계정을 다른 계정의 Amazon SES 이메일 주소로 사용할 수 없습니다. 여러 계정에서 Amazon Cogn

docs.aws.amazon.com

  • AWS SES에서 메일 주소 확인 처리를 할 때 참고하면 좋다.
 

Amazon SES에서 확인된 자격 증명 - Amazon Simple Email Service

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

  • 마지막으로, 이 모든 상황을 전부 파악하고 나서야 찾았던 스택오버플로우. 아는 만큼 보인다 했던가.
 

Email address is not verified (AWS SES)

I want to use Amazon's Simple Email Service to send emails. I verified my domain as well as the email address I want to send from. For both it says verified. Now when I use the Send Test Email f...

stackoverflow.com

오늘까지 한 일

  • 일이 엄청 많거나 너무 바쁜 건 아닌데, 그렇다고 하루하루 하는 일이 차근히 정리되고 있는 것 같진 않다. 사이트 개편 앞두고 일종의 마무리 작업 중이라서 그런 건지, 항상 느끼는 거지만 마치 깔끔하게 치워놓은 방이 어질러지듯이 처음엔 시작이 얼마나 정돈되었든 뒤로 갈수록 '일단 하고 본다'는 식의 임시방편성 코드가 많아지게 된다. 내 코드 내가 읽어도 정신이 하나도 없다.
  • 하루종일 허둥대며 코드를 짜다 보면 퇴근하고 나서는 생산적인 일은 별로 하고 싶지 않다. 그래서 요 며칠 TIL도 안 남기고 아무런 의미 없는 시간을 보냈는데, 또 다른 분들 글을 읽고 나면 나는 지금 뭐하나 싶다. 잠깐 해찰하며 여유를 가졌던 것에 만족해야겠다. 슬슬 다시 힘을 내야지.
  • 오늘은 동영상 인코딩 처리를 위한 큐를 구현하는 데 (완벽하게 성공했다고 장담할 수 없지만) 어떤 방법을 써야 할지 고민하면서 찾아봤던 반복문 사용의 차이점을 링크로 건다.

오늘 배운 것

  • for ... in 반복문에 대한 링크. for ... in 을 통해 직접적으로 가져올 수 있는 건 객체의 key-value 중 key이다. 객체의 요소들을 순서대로 가져온다는 보장이 없으므로 인덱스가 중요한 배열 등에 사용하는 것은 권장되지 않는다.
 

for...in - JavaScript | MDN

The for...in statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties.

developer.mozilla.org

  • for ... of 반복문은 문자나 배열에 사용한다. 배열 안의 요소 자체를 가져온다. 아래 링크에 예시 코드와 함께 for ... in 과 for ... of 의 차이점이 잘 정리되어 있다. 나중에 다시 한번 읽어봐야 할 것 같다.
 

for...of - JavaScript | MDN

The for...of statement creates a loop iterating over iterable objects, including: built-in String, Array, array-like objects (e.g., arguments or NodeList), TypedArray, Map, Set, and user-defined iterables. It invokes a custom iteration hook with statement

developer.mozilla.org

  • 반복문들의 차이점에 대해 "한글로" 잘 정리해둔 곳을 찾았는데 뭐가 문제인지 모르겠지만 지금은 안 열린다(?!) 혹시 나중에 잘 뜰지도 모르니 일단은 저장..

https://jsdev.kr/t/for-in-vs-for-of/2938

 

오늘 한 일

  • 사실 Amplify를 연계한 로그인, 회원가입 페이지 작업은 지난 주에 끝냈지만... 오늘은 동영상 인코딩 문제 때문에 하루종일 씨름만 하고 성취해 낸 건 딱히 없는 기념으로 뒤늦게 가져와 봤다. 아니 그나저나 도대체 왜 어떤 mov는 인코딩 속도가 느려?!
  • AWS Amplify 문서는 정말 너무 깔끔하고 너무 좋다. 괜히 자꾸 읽고 싶고 정독해야 할 것 같고 다른 키워드도 다 클릭해봐야 할 것 같고 저 오렌지 색도 예쁘고 막... 어제 올린 멀티파트 업로드 쪽 문서가 Amplify의 반만 됐어도 그렇게까지 애먹지는 않았을 텐데, 같은 AWS여도 워낙 서비스가 다양해서인지 참 다르다.

오늘 아니고 그때 배운 것

  • 지난 번에도 올렸던 링크다. 그때는 sign in/out만 구현했었고, 이번에는 sign up까지 완료했다. 아무래도 회원가입 페이지가 로그인보다는 만들 게 많으니까 뒤로 미뤘었다. 그리고 Amplify에서 제공하는 UI components를 사용하면 더욱 간단했겠지만, 무엇보다 뷰 자체는 회사 기획안에 맞추다 보니 시간이 좀 더 걸렸다.
 

https://docs.amplify.aws/lib/auth/emailpassword/q/platform/js/

 

docs.amplify.aws

  • 이건 로그인 화면 어딘가에 위치한 '비밀번호 찾기'에서 쓰이는 함수를 포함한 부분이다.
 

https://docs.amplify.aws/lib/auth/manageusers/q/platform/js/

 

docs.amplify.aws

  • 근데 문제는 이 공식문서에서 소개하는 함수들을 그대로 사용하다 보면, 회원가입 절차가 [아이디(이메일), 비밀번호 입력 -> 회원가입 -> 입력한 이메일로 인증번호 발송 -> 인증번호 입력하면 회원가입 절차 완료] 이런 식으로 가게 된다. 하지만 기획안대로라면 [아이디(이메일) 입력 -> 입력한 이메일로 인증번호 발송 -> 인증번호 입력해서 확인되면 비밀번호 입력 -> 회원가입] 순서여야 한다. 인증 메일은 회원가입이 되고 난 후에나 보내주는 것인데, 우리는 가입을 완료하지 않은 시점에서 이메일만 우선적으로 확인하고 싶은 것이다. 회원가입 절차 자체를 커스터마이징 해야 하는 거라 이건 추후 Lambda Trigger를 활용하거나 해야 할 것 같다. 아직은 안 해봄
 

Pre Sign-up Lambda Trigger - Amazon Cognito

If an alias with the same phone number already exists, the alias will be moved to the new user, and the previous user's phone_number will be marked as unverified. The same is true for email addresses. To prevent this from happening, you can use the user po

docs.aws.amazon.com

+ Recent posts