일일 아티클 읽기
January 01, 2022
하루에 하나씩 아티클 읽기!
jjuny 블로그에서 jjuny님이 하는거보고 재미있어보여서 시작했다…
2022년 6월
-
8월 8일 (월) 카카오웹툰은 CSS를 어떻게 작성하고 있을까?
- CSS-in-JS, CSS-Module의 차이점을 알아보고 어떤 특징을 가지고있는지 공부하다가 읽게되었음
- 어떤 기술이든 서비스의 종류와 목적에 따라 적절한 기술을 사용해야한다.
- 먼저 CSS-in-JS는 어떤 문제를 해결해주는가!!?
- class명이 빌드타임에 유니크하게 변경되기 때문에 별도의 명명 규칙이 필요치 않음
- CSS가 컴포넌트 단위로 추상화되기 때문에 CSS간 의존성 고려가 필요없다!
- 컴포넌트와 CSS가 동일한 파일내에 존재하기 때문에 수정 및 삭제가 용이하다!!(생산성이 높다!)
- 빌드 타임에 짧은 길이의 유니크한 클래스를 자동으로 생성하여 문서의 볼륨을 낮춰줌
- CSS 코드가 JS에 작성되므로 컴포넌트 상태 공유 가능(동적 CSS를 사용하기 좋다는 말 같음)
- CSS가 컴포넌트 스코프로 적용되므로 우선순위에 따른 문제가 없음.
- CSS가 컴포넌트에 격리되어 있기 때문에 상속 문제가 없음.
- CSS-in-JS방식은 온전치 못하다. 그래서 많은 개발자들은 기존의 CSS 방식과 CSS Module 를 병행해서 사용한다. 테마 등의 공통 영역, 일부 유틸리티 등은 CSS-in-JS로 쉽게 해결이 어렵기 때문이다.
- 또한 협업할때도 일반적으로 기존의 CSS 방식이나 CSS Module 방식이 좋다. 만약! 마크업 개발자가 있다면 CSS-in-JS 방식은 불편할 수 있다. 왜냐하면 마크업 개발자는 페이지 단위로 작업하고, 프론트엔드 개발자는 컴포넌트 단위로 작업하기 때문이다. 또한 CSS Module 방식도 컴포넌트 단위로 추상화가 가능하다
- 일반적으로 CSS Module 방식은 빌드타임에 온전한 CSS파일로 변환되므로 자바스크립트와 같이 변환이 필요한 CSS-in-JS 보다 속도가 빠르다.
- 카카오웹툰은 CSS Module로 시작했다가 디자이너와 협업이 필요한 상황, 애매모호한 상황이 많아지자 테일윈드(확장성 있는 부트스트랩(?))를 적용했다.
- 기존의 부트스트랩과는 다르게 확장성이 좋다. 필요에따라 CSS를 변경할 수 있다.
- 테일윈드는 사용하지 않는 클래스가 제거되어 번들 크기가 줄어드는 장점이 있다.
- 테일윈드는 rem 단위가 기본이기 때문에 px 단위 서비스라면 기본값을 바꿔줘야한다.
- 빌드 타임에 모두 생성되므로 동적 변수를 사용할 수없다.
애니메이션과 트랜지션 사용에 제약이 있다. 그래서 미리 만들어진 애니메이션만 제공하기 때문에 필요한 애니메이션을 추가해야 한다.
-
8월 9일 (화) Webpack 빌드에 날개를 달아줄 Esbuild-Loader
- 요즘 웹팩을 공부중인데, 흥미롭게 읽었음 다음 프로젝트는 ESbuild를 사용해봐야겠다.
- 웹팩은 프론트엔드 개발 환경에서 주로 사용되고 있는 모듈 번들러다. 웹팩은 기본적으로 자바스크립트 리소스만 읽고 처리할 수 있다. HTML, CSS, Image, Font와 같은 리소스도 모듈로 처리될수 있도록 하려면 별도의 전처리기가 필요하다. 이과정을 수행해주는 것이 로더다.
- 브라우저가 최신 자바스크립트 스펙을 따라오지 못하기 때문에 babel을 통해 낮은 버전의 자바스크립트로 트랜스파일을 거쳐서 실행된다. 웹팩에서 Babel-Loader로 설정한다.
- Webpack은 코드 한부분이 수정되면 다시 의존성 그래프를 구성하고, 리빌딩하는 과정을 거치고, Babel-Loader 전처리과정을 다시 수행하기 때문에 비효율적이다.
- ESbuild-Loader을 사용해서 빌드한 것이 Babel-Loader을 사용한것보다 속도가 2배나 빠른것으로 보인다.Esbuild가 빠른이유는 Go언어로 작성된 모듈 번들러이기 떄문이다. 기본적으로 자바스크립트와 Go언어 자체에서 퍼포먼스 차이가 발생한다. 자바스크립트는 인터프리터 언어이기 때문에 한줄한줄 인터프리터가 기계어로 변환하는 반면 Go는 프로그램 실행 전 컴파일 단계에서 미리 소스코드를 전부 기계어로 변환해놓기 때문에 속도에서 차이가 발생한다.
- 다중작업 능력에서도 차이가 발생한다. 자바스크립트는 싱글스레드라서 한번에 한파일씩 번들링하는 반면 Go는 공유 메모리 환경 아래에서 멀티 스레드 기반으로 동작한다. 즉 여러 파일이 동시에 번들링 된다.
-
8월 10일 (수) 웹 애니메이션을 구현하는 4가지 방법
- 자바스크립트 애니메이션, CSS 애니메이션에 관심이 있었는데 재미있게 읽었음
- CSS transition은 가장 많이 쓰이는 방식이다 단순한 클릭으로 요소의 위치나 크기를 변경할 떄 유용하다. CSS animation 방식은 transition과 용도가 조금 다르다. 여러 효과를 혼합하거나 연쇄적 동작처럼 더 복잡한 인터렉션을 구현할 때 사용한다. 코드 자체는 transition과 복잡해질뿐 방법은 크게 다르지 다르지 않다.
- SVG animaion은 2차원 벡터 그래픽을 표현하기 위한 XML 마크업 언어다. SVG는 JPEG나 PNG에 비해 다음과 같은 장점이 있다.
- W3C 표준과 호환되기 때문에, HTML 문서에 그대로 사용할 수 있습니다.
- 대체로 JPEG, PNG에 비해 용량이 작습니다.
- 확대하더라도 꺠짐 없이 선명하게 보입니다.
- SVG는 웹표준에 호환되기 떄문에 모든 브라우저에서 동작하지만 animateTransform 이라는 요소는 크롬이나 파이어폭스 같은 브라우저에서는 정상 동작하지만, 이외 브라우저는 확인이 필요하다.
- 마지막으로 Animation API입니다. JS로 애니메이션을 구혀하기 떄문에 자유도가 높아서 복잡한 인터렉션도 가능합니다. JS 변수를 활용하거나 함수를 만들어 재사용하기도 편하다. 음.. 이부분은 직접 써봐야 이해할 것 같다.
- 8월 11일 (목) 사용자 경험과 성능 개선 방법 in 카카오 웹툰
- 제목이 흥미로워서 읽었지만 양질의 정보가 있는 글이였음..
- CDN은 콘텐츠를 캐싱하여 사용자가 어디서 접속하던지 빠르게 전송해준다. 실제 서버에 부하도 거의 주지 않고, 서버의 위치와 상관없이 전 세계에서 서비스를 할 수 있다. 요즘 많은 클라우드 서비스들에서도 손쉽게 사용할 수 있도록 제공한다. 클로벌로 서비스를하는 카카오웹툰도 웹에서 보이는 수많은 리소스들을 CDN을 통해 제공하고 있다. 만약 콘텐츠가 변하지 않는다면, 정적 페이지로 만들어 리소스처럼 CDN을 통해 빠르게 제공할 수 있다. 하지만 사용자마다 달라지는 추천 영역이나 운영 또는 시간의 흐름에 따라 언제든 변경될 수 있는 페이지가 있다면, 그리고 이러한 페이지들이 중요도가 높아서 첫 진입시 빠르게 보여주기 위한 것과, 검색엔진 SEO가 필요하기 떄문에 Next.js를 사용해서 SSR을 사용하고있다.
- SSR로 첫 진입시 완성된 페이지를 제공한다는 장점이 생겼지만, 매 요청 마다 렌더링이라는 비용이 추가로 발생한다. 이를 위해 SSR 결과에 캐싱을 적용했다. 데이터의 변경이 실시간으로 반영될 필요가 없고, 동일한 요청이 빈번한 페지이들의 경우 SSR 결과를 캐싱해두고 일정시간마다 갱신하면서 재사용 하고 있다. 처음에는 요청이 오면 해당 캐시가 만료되었다면 바로 무효화하고 다시 렌더링을 해서 캐싱과 응답을 주도록 했는데, 이런 방법은 렌더링을 발생시킨 요청을 포함해 완료 전까지 들어온 요청들은 그만큼 지연이 발생된다.
- 그러나 SEO가 필요없고, 첫 진입시 보이는 영역을 곧바로 보여주지 않아도 된다면 해당 영역을 제외하고 정적페이지로 만들어 브라우저에서 갱신하도록 하는 것도 하나의 방법이다.
- 로딩이 존재한다면 Loading Shimmer(Skeleton 혹은 Placeholder)를 사용하여 자연 스러운 페이지 전환을 구현할 수 있다. 그렇다고 모든 영역에 적용해야 하는 것은 아니다. 필요한 화면에서 오래 걸릴 수 있는 작업에만 적용하고, 콘텐츠의 로드를 방해하지 않는 선에서 사용해야한다. 만약 React를 사용한다면 Suspense 컴포넌트 사용을 고려해보자Suspense와 선언적으로 Data fetching
- CDN을 통해 리소스를 제공하는 것과 더불어 최적화된 리소스를 사용하는 것도 중요하다. 더 적은 용량의 리소스를 사용하면 그만큼 더 빠르게 전송할 수 있다. 카웹의 경우는 이미지 요소는 SVG를 사용했지만 벡터이미지가 모든 경우에 효과적이지 않다. 그래서 WebP와 이전 버전의 safari 처럼 WebP를 지원하지 않는 브라우저를 위해 PNG를 함께 사용한다. 예를들면
- CDN을 통해 최적화된 리소스를 제공해도 한번에 많은 양을 내려받는다면 그 효과는 미미하다. 사용자는 보고있는 화면이 얼마나 빠르게 표시되는지가 중요하기 때문에 이와 무관한 영역의 리소스를 먼저 받으면 느리다고 인식한다. 또한 해당 리소스를 사용하기 전에 전환이 발생한다면 불필요한 리소스를 받는 상황이 생길 수 있다.
따라서 lazy loading을 통해서 최초에는 ATF (Above-The-Fold)에 포함된 리소스를 먼저 내려받로고 하고, 인터렉션이나 전환 시에는 그때마다 필요한 리소스를 미리 받아서 보여주도록 하는게 좋다.하드웨어 가속과 intersectionObserver
- requestAnimationFrame()을 사용하면 프레임 생성 시작에 맞춰 자바스크립트가 실행되기 떄문에 프레임 누락이 없는 부드러운 애니메이션 표현이 가능하다.
-
터치나 휠 괕은 이벤트 리스너가 등록되어 있다면 preventDefault() 호출을 통해 기본 동작인 스크롤을 막을 가능성이 있다. 그래서 컴포지터는 바로 합성을 하지 않고 메인 스레드로부터 해당 정보가 올 때까지 기다리게된다. passive옵션을 사용하면 해당 리스너에서 preventDefault()를 호출하지 않을 것이라고 판단하고 스크롤 시 바로 화면을 합성하고 부드러운 스크롤이 동작한다.하지만 모든 브라우저에 적용이 안될뿐더러 크롬, 파이어 폭스는 기본값이 true라서 반대의 경우에는 false로 설정한다.
-
8월 12일 (금) Mitakes | 주니어 리액트 개발자인 내가 실수하고 있었던 것
- 제목부터가 재미있어 보여서 읽었다.
- 새로운 상태는 이전 상태에 기반한 setState를 만들어서 업데이트 해야한다. setState는 비동기적으로 작동을 하기때문에 상태값을 batch(일정 시간 동안 변화하는 상태를 일괄 처리)로 변경하기 때문이다.
const [isState, setState] = useState(false)
const toggleBtn = () => setState(!isState)
const toggleBtn = () => setState(isState => !isState)
- 상태 객체 얇은복사 주의해야함
- value가 undefined나 null인 경우 OP operator을 많이 사용하는데 주의해야한다. 0도 결국 undefined, false와 같다.
- JSON mock data 만들때 JSON.stringify써서 편하게 복사가 가능하다
- 컴포넌트에 전달하는 props가 true일 경우 따로 true를 표시하지 않는다.
- 비동기처리 병목현상 Promise.all, Promise.allSettled 사용하기
- 삼항 연산자 쓰기보단 미리 조건문으로 리턴해주기
- 8월 14일 (금) 웹사이트 최적화 방법
- 최적화에 관심이 많았는데 제목부터가 흥미를 끄는 글이라 읽었다.
- 디지털 이미지는 일반적으로 브라우저에서 어떻게 렌더링 되느냐에 따라 레스터 이미지 타입과 벡터 이미지 타입, 그리고 이미지 손실을 어느 정도 허용하는지에 따라, 무손실 이미지 타입과 손실 이미지 타입으로 구분된다.
- 레스터 이미지는 흔히 아는 픽셀에 표현하고자 하는 색상을 그려서 이미지 형태로 표현하는 방식, 주로 개발자들이 사용하는 JPEG, PNG, GIF가 있으며, 여러 픽셀이 모여서 하나의 이미지를 만들기 떄문에 사이즈가 크거나 품질이 좋은 이미지를 만들기 위해서는 그만큼 정보를 담은 픽셀을 추가해야 하기 떄문에, 사이즈가 커지면 커질수록, 이미지의 용량도 늘어나고, 렌더링 속도도 현저히 떨어진다.
- 벡터 이미지는 픽셀값으로 그리는게 아닌 이미지 안에 수많은 수학적 방정식을 퐇마하고 있는 이미지 형태다. 그래서 사이즈가 커지거나 작아져도 이미지가 깨지거나 정보가 달라지지 않는다. 즉 항상 같은 이미지 품질을 유지할 수 있다. 하지만 이미지가 복잡하면 복잡할 수록 수학적 정보는 계속 늘어나고, 이미지 용량 또한 같이 늘난다. 주로 아이콘, 폰트에 사용
- 무손실 이미지는 원본 이미지에서 이미지를 렌더링하는데 필요하지 않은 정보들을 제거한 이미지를 말한다. 따라서 무손실 이미지는 원본 이미지보다 용량이 줄어들 수 있다. 예를들면 GIF,PNG가 있다.
- 손실 이미지는 무손실 이미지의 화질을 감수하면서도 사이즈를 줄여 빠른 렌더링할 수 있는 이미지다. 일반적으로 사람이 품질 저하를 눈치채지 못하면서 낮을수 있는 퍼센트는 100% ~ 75%다. 페이스북은 85% 손실 이미지를 사용한다. 손실 이미지는 무손실 이미지보다 빠른 렌더링 가능, 꼭 필요한 이미지가 아닌 경우 사용 대표적으로 JPEG
- WebP는 구글에서 개발한 이미지 포맷, 손실 압축과 비손실 압축을 모두 지원한다. 25% ~ 35% 압축이 가능한 이미지 포맷이다. 또한 투명, 애니메이션 기능을 제공하므로 GIF, PNG, JPEG 등의 상용 이미지 포맷을 대체할 수 있다. 하지만 디바이스 사양에 따라서 상용 이미지 포맷보다 더 높은 리소스 필요, IE를 지원X,Progressive Image 지원X라는 단점이 있다.
- AVIF은 WebP와 마찬가지로 GIF, PNG, JPEG등의 상용 이미지 포맷을 대체할 수 있다.. 또한 애니메이션기능이 있고, 압축 효율이 WebP보다 뛰어나지만, 최신 포맷이기 때문에 AVIF를 지원하는 뷰어가 적고, 브라우저 지원율이 낮다는 단점이 있다.또한 단순한 패턴의 이미지를 압축하는 경우 PNG보다 낮은 압축률을 보인다.
- 데스크톱과 모바일의 이미지 용량은 다를수밖에없다. 그렇기 때문에 사용자는 필요 이상의 이미지를 다운받기 때문에 리소스가 낭비된다. 그러므로 태그의 srcset속성,
- 웹사이트의 이미지는 최대한 사용자가 보이는 부분부터 로드되도록 처리하며, 사용자가 보이지 않는 부분은 Lazy Loading을 적용하여 사용자 경험 저하를 막을 수 있다. 즉 사용자가 보이는 부분만 로드함으로써 로딩 시간을 줄일 수 있다.
- 이미지 CDN은 이미지 변환, 최적화 및 전송을 담당하는 서버로, 이미지 CDN을 사용하면 이미지 다운로드 속도를 40%~80%로 줄일수 있습니다. 또한 Image CDN에서 로드된 이미지의 경우 이미지 URL에 따라 다양한 이미지를 요청할 수 있다. 또한 HTTP 캐시를 이용한 이미지 캐싱이 가능하다. 물론 CDN을 활요한 캐시는 적절한 캐시정책이 필요하다.
- CSS image Sprite는 여러 개의 이미지를 합친 하나의 이미지 셋을 말한다. 첫 페이지 로딩 속도를 줄여주는 가장 대표적인 방법이다. 실제로 10번의 이미지 요청을 1번의 요청으로 해결할 수 있으며, 대표적으로 아이콘이나 버튼 같은 이미지들을 하나로 합쳐 배경 이미지를 만들어 놓고 position 값으로 각각의 이미지들을 잘라서 사용하는 방식이다.
- 8월 16일 (금) 누구나 원하는 개발자되기
- 나에게 필요한 내용같아서 읽었다.
-
주요 역량 항목
- 어떤 프로젝트를 경험했는지
- 어떤 도구/프레임워크를 사용했는지
- 어떤 개발 방법론을 사용했는지
- 프로젝트에 어떤 책임으로 참여했는지 개발자인지 개발리더인지
- 팀이나 회사에 프로젝트외에 어떤 기여를 했는지
- 프로젝트에서 발생한 기술적인 문제를 어떻게 해결하는지
- 리더쉽, 협업, 커뮤니케이션 스킬
- 이력서를 주기적으로 업데이트하면서 반서과 동기부여를 가지는 시간을 갖자.
- 단순히 경험을 적기보다는 역량을 어필할 수 있는 포인트를 하나 이상 적자.
-
단순 기술 보다는 “성과”라는 스토리를 담으려고 노력하자!
- 효율적인 기술들을 검토해서 스택을 결정하고 팀에 전파
- 난이도가 높은 기술을 사용했거나 직접 개발 했던 경험
- 개발 환경이나 구조를 구축
- 레거시 코드를 포팅하거나 새로운 코드로 교체
- 월등한 성능 개선
- 익숙하지만 노후된 프레임워크를 본인의 설파와 계몽을 통해 새로운 프레임워크로 변경
- 본인이 개발한 모듈에 대한 자랑거리(성능, 적은 코드, 구조, 가독성) 등등..
-
사전과제 코딩테스트
- 효율적인 구조
- 컴포넌트나 모듈의 책임과 역할
- 코드의 일관성, 가독성, 유지보수성
- 변수, 함수, 클래스등의 네이밍
- 안티 패턴에 대한 이해
- 성능에 대한 이해
- 모던 개발 환경에 대한 이해
- 정상 동작은 기본이고, 꼭 하고 싶었던 것 을 20%정도만 첨가해보자
- 로깅 코드나 주석, 필요없는 코드를 제거하자
- node_modules와 빌드 결과물은 제거하고 제출하자 package.json, 환경 설정파일, 코드만 제출하는게 좋다
-
면접
- 사용한 프레임워크에 대해서 기술적인 질문에 답을 할 수 있어야한다.
- 자신있는 기술일수록 더 잘 준비해서 설명하자.
- 괜히 모르는 것을 설명하려고 하지말자.
- 과정을 어필해라 내가 무엇을 경험하고 무엇을 배웠는지
-
8월 17일 (금) 신입 프론트엔드 개발자를 위한 면접 조언
- 신입은 어마어마한 기술적 소양을 물어보기보다는 다루는 기술의 기본을 충실히 알고 있는게 중요하다. 본인이 잘 안다고 생각하는 것들을 다시 확인해보자
- 처음부터 끝까지 잘 설명할 수 있는지 스스로 확인해보자.
- 포트폴리오는 가능하면 GitHub같은 호스팅 서비스에 올려두자.
- .gitignore파일에 .idea 폴더나 npm-debug.log 같은 불필요한 파일은 포함되지 않게 설정하자.
- 커밋 메시지는 의외로 많은 것을 말해준다. 신경써서 작성하자.
- 포트폴리오 쓸 때 기술은 나열 하되 강조는 하지않는게 좋다.
- 테스트 케이스는 성의껏 작성하자. 좋은 인상을 줄 수 있다.
-
8월 18일 (금) 고무오리 문제 해결 방법
- 나는 이런 상황을 겪어본적이 있나?
- 문제가 있다.
- 그 문제를 스택 오버플로우에 올리기로 한다.
- 내 질문을 엉성하게나마 적어서 올린다.
- 내 질문이 말이 되지 않는다는 사실을 발견한다.
- 어떻게 질문해야 하는지에 대해 15분 가량 고민해본다.
- 내가 완전히 엉뚱한 방향에서 문제에 접근하고 있었다는 사실을 깨닫는다.
- 처음부터 다시 시작하다가 금방 해답을 얻는다.
- 질문을 던지기 시작하는 것은 실제로 자신의 문제를 스스로 디버깅하는데 도움을 준다.
- 물론 옆에 코딩친구가 있다면 좋겠지만 만약 없다면 고무오리 해결법을 통해 자신의 문제를 해결해보자.
-
8월 19일 (금) 리액트 useEffect: 개발자가 알아야 할 네가지 팁
- 리액트 훅을 사용할 때 복수의 useEffect 함수를 사용할 수 있다. 하지만 클린 코드 관점에서는 함수는 한 가지 목적을 가지고 있어야한다. useEffect를 작고 단순한 단일 목적의 함수로 분리한다면 의도치 않은 이펙트 함수의 실행을 방지할 수 있다. 물론 디펜던시 배열도 잘 사용해야한다.
- 가능하다면 커스텀훅을 사용해서 상태 변수를 독립적으로 만들자.
- 조건부 useEffect를 사용할 떄 이상적인 방법은 함수의 초기에 조건문으로 바로 반환하는 것이다.
- useEffect 안에서 사용하는 모든 변수들을 디펜던시 배열에 추가한다. 그래야 테스트하기 수월해지고 발생할 수 있는 문제를 쉽게 탐지할 수 있다.
-
8월 20일 (토) 버튼에 타입을 쓰는 이유
- 되게 인상적인 글이다…
- button 태그는 type을 3가지 지정해줄 수 있는데, 각각 submit, reset, button 이고, 만약 아무런 값을 지정하지 않았다면 기본값은 submit이 된다.
- 그래서 form 안에서 버튼을 클릭했을 때 새로고침 되는 이유가 바로 이것 떄문이다. 만약 어떤 이유로 특정 영역을 form 태그로 감싸게 되면, 그 안에 있던 타입 명시 없는 버튼은 모두 submit 버튼으로 동작한다.
- IE 10 이하에서, form 태그에 속하지 않은 input에서 엔터키를 누르면 submit을 실행하는 이슈가 있다.
- 마크업 측면이나, 의미론적으로 단순 버튼에는
type = "button"
을 명시해주는 것이 좋다.
- input는 한계가 있다. 다양한 이미지나 텍스트가 들어간 버튼을 표현할 수 없다.그래서 버튼 태그가 등장했다.
- 결국 버튼 태그도 기존의 문제를 해결하기 위해서 등장했구먼… 요즘은 div도 버튼으로 만들어버린다…
-
8월 21일 (일) Preload의 개념, 그리고 올바른 사용법
- 그전에 책에서 읽은 Preload, prefetch 내용이 떠올라서 읽었다.
- 웹 사이트를 방문하면, 필요한 리소스 자원을 서버에 요청할 때 여러 자원을 동시에 요청하게 되고 서버에서는 요청 순서에 상관없이 준비가 되는대로 응답한다. 이때 빠르게 로딩하도록 우선순위를 부여하는 방법이 Preload다.
- 불필요한 리소스에 Preload를 걸지 않는게 중요하다. Preload로 선언되는 순간, 해당 소스가 실제로 사용하든 하지 않든 무조건 서버로부터 요청하여 다운로드를 하기때문에, 잘못 사용하면 오히려 로딩 성능을 저하시키는 역효과를 발생시킬 수 있다.
- 비즈니스에 맞게 전략적으로 사용해야한다. 초기 로드에 필요한 리소스에만 Preload를 걸어주었다고 해도, 무조건 전부 다 Preload를 하는 것을 올바르지 않다. 전부 Preload를 걸게 되면 결국 우선순위 없이 모든 리소스를 요청하고, 다운로드 후 브라우저엣서 렌더링 시 메인스레드가 분산되어 Preload 역할의 이미가 없어지게 된다.
- 예를들어 SEO가 중점이라면 큰 영역을 차지하는 이미지에만 PreLoad를 걸어 다른 소스보다 먼저 요청을 시도하도록하는 것으로 비즈니스적 큰 이점을 얻을 수 있고, 만약 SEO가 중점이 아닌 일반 블로그 같은 페이지에서는 이미지보다는 WebFont에 Preload를 많이 걸곤한다.
- Preload는 전체적인 웹 성능을 빠르게 하기위해 사용되는 속성이 아니다. 비즈니스에 따라 빠르게 로딩해야 하는 특정 리소스를 위해 사용되는 속성이다.
-
8월 22일 (월) SVG 아이콘 백그라운드 이미지로 돌려 쓰기
- 같은 아이콘이지만 색이 다르고 크기도 다른 것들을 사용하고 싶을 떄, SVG를 사용하면 좋다. 백터 그래픽이라 다양한 크기로 표현할 수 있고, 코드이기 떄문에 색상값을 필요할 때마다 달리 줄 수 있다.
- SVG는 “백터 그래픽을 표현하기 위한 XML 기반의 포맷이다. JPEG,PNG 등 픽셀 기반 이미지와는 다르게 SVG는 “읽을 수 있는 코드” 이므로 정보 접근성이 좋다. 또한 필요하면 코드를 수정하여 이미지를 수정할 수 있다. 하지만 IE에서 몇가지 지원 이슈가 있을 수 있다.
- 웹 SVGOMG을 사용하면 SVG에서 필요없는 코드를 제거하고, 압축할 수 있다.
- SVG 코드를 “Data URI”라는 형태로 변환할 수 있다. Data URI는 작은 파일을 인라인으로 임베드할 수 있다. 이렇게 임베드된 데이터에는 HTTP 요청 밑 헤더 트래픽이 필요하지 않다. 결국 이미지를 긴 코드로 바꿔서 넣어줘야한다는 것이다. 물론 JPEG와 PNG도 Base 64 인코딩을 거쳐 Data URI로 제공할 수 있지만 인코딩 과정에서 크기가 기존보다 커지게 된다.(6bit당 2bit의 오버헤드 발생), 또한 캐싱을 못한다. 단순 코드이기 때문에 HTML이나 CSS가 요청될 떄마다 다운로드한다.
- SVG 코드를 Data URI로 바꿔주는 URL-encoder for SVG를 통해 URI 값을 얻을 수 있다.
-
,<> 문자는 크로스 브라우징 문제가 있으니 치환해서 사용하는게 좋다.
- 이밖에도 색상이나 선 굵기등 다양한 인터렉션을 줄수 있다.
-
8월 22일 (월) 좋은 커밋을 작성하는 법
- 팀원들이 변경 내용을 쉽게 알 수 있다. 누군가가 코드를 변경할 떄 마다 모든 팀원이 이를 숙지하는 것을 무리다. 그러나 커밋 메시지를 잘 작성해 놓는다면, 자신이 보지 못한 사이에 소스코드에 어떤 변화가 생겼는지를 쉽게 알 수 있다.
- 코드의 의도를 알 수 있다. 커밋 메시지가 잘 작성되어 있다면 코드를 읽을 때 상당한 도움을 받을 수 있다. git에는 코드의 라인별로 커밋메시지를 보여주는 blame이라는 기능이 있다.
- 리뷰가 쉽다. 팀 작업을 하다보면 머지를 하기전에 팀원이 코드리뷰를 해주는 경우가 많다. 커밋을 잘 작성하면 개발자의 의도를 이해하기 쉽기 때문에 코드리뷰가 수월하다.
- 좋은 커밋을 작성하기위해서는 “간결함”과 “분명함”이라는 2가지 상반된 과제를 동시에 달성해야한다. 들어가야할 텍스트가 너무 많다면 제목과 본문을 나누어 적을 수 있다. 커밋 메시지에 빈줄을 하나 추가하면 빈 줄 위의 내용은 제목, 밑의 내용은 본문이 된다.
- 꼭 필요한 변경 사항만 커밋한다. 예를 들어 코드의 테스트를 하느라 잠깐 설정 파일의 내용을 변경했다면, 설정 파일의 변경 사항은 커밋이 되면 안된다.
git add -all
, git add .
와 같은 명령어를 쓰지 않는게 좋다. 꼭 필요한 파일만 지정해서 커밋하자. 같은 파일의 변경 사항이더라도, 의도되지 않은 것이라면 커밋하면 안된다. ex(빈줄, 공백)
- 이슈 트래커의 티켓 번호를 기록한다. github에서 자동으로 링크를 만들어준다. #뒤에 이슈번호를 붙이도록하자. 나중에 이슈를 close하더라도 어떤 커밋을 통해 이슈가 해결되었는지 쉽게 알 수 있다.
- 테스트를 거친 코드만 커밋한다. 작동하지 않는 코드를 커밋하면 안 된다. 이런 실수를 방지하는 제일 좋은 방법은 자동화된 검증 과정을 넣는 것이다. ex(git hooks)
- 내가한 과정을 문서로 남기는것은 너무나 중요한것!!
-
8월 23일 (화) 프론드엔드 아키텍처의 가장 최근 트렌드는?
- 제로님이 추천해주신 글
- 웹은 HTML, JS, CSS가 순서대로 탄생했고 각자의 방식대로 성장했다. HTML은 서버가 작성하는 영역이었고, JS는 간단한 동작과 CSS는 화면을 관리했다.
- Ajax의 탄생으로 서버에서는 HTML을 만들지 않고 데이터만 교환하는게 가능해졌다. 그래서 jQuery와 같은 Ajax와 DOM을 잘 다룰 수 있는 도구를 통해 개발했다.
- 시간이 지날수록 JS와 HTML을 함께 다루는 것으로 변했다. 그러면서 자연스레 화면 단위가 아니라 컴포넌트 단위로 발전하게 된다.
- 매번 데이터 변경때마다 템플릿 방식으로 HTML을 작성하는 방안이 연구되었고, 이를 자동화하는 과정에서 Knockout.js와 angaulr.js등을 바탕으로 웹 서비스를 개발하는 MVVM 아키텍처가 만들어진다. 이후 React, Vue, Angaulr를 비롯한 수많은 프레임워크가 이런 방식으로 만들어지기 시작한다.
- 데이터가 많아지고, 로직이 흩어지면서 컴포넌트는 점차 복잡해졌다. 그렇게 컴포넌트의 재사용성이 떨어지면서 보여주기만하는 readonly 스타일의 ‘Presenter형 컴포넌트’와 데이터 조작을 다루는 ‘Container형 컴포넌트’를 분리하기로 했다.
- Props Drill 문제로 FLUX와 Redux가 등장했다. 이떄부터 비즈니스 로직을 컴포넌트에서 분리하고, 별도로 관리하는 도구들이 주류가 됐으며, 이러한 개념을 “상태 관리” 라고 부르게 된다.
- 하지만 Redux는 너무 많은 보일러플레이트가 필요했다. 과한 문법체계를 가지고 있었기 때문에 대형 프로젝트가 아니라면 중소규모에서 대부분 오버엔지니어링 되었다. 이떄부터 간결하게 사용할 수있도록 Hooks, Context를 통해서 대안방법을 찾게되었고, 그이후도로 Recoil같은 새로운 대안이 제시되고있다.
- 대부분의 프론트엔드에서 전역적인 상태관리가 필요한 이유는 서버와 API에 있다. 그래서 백엔드와 직접 연동해 기존 상태관리에서 로딩, 캐싱, 무효화, 업데이트 등을 복잡하게 진행하던 로직들을 단순하게 만들어주는 방식도 생겨났다. (React Quert, SWR, Redux Query)
- 프론트엔드 아키텍처의 방향성을 요약 정리하자면 재사용이 가능한 독립적인 컴포넌트를 조립하여 서비스를 구성하는 기존 구조와 달리 현재 프론트엔드 아키텍처 방향성은 View와 비즈니스 로직을 완전히 분리하여 생각하고있다.
-
8월 23일 (화) DOM 소개
- DOM 이란 문서 객체 모델(The Document Object Model)로 HTML, XML 문서의 프로그래밍 interface이다. DOM은 문서의 구조화된 표현을 제공하여 그들이 문서 구조, 스타일, 내용을 변경할 수 있게 돕는다. 우리는 자바스크립트를 통하여 DOM을 수정, 삭제등 다양한 작업을 할 수 있다.
- DOM은 프로그래밍 언어가 아니다. DOM이 없다면 자바스크립트 언어는 웹 페이지 또는 XML 페이지 및 요소들과 관련된 모델이나 개념들에 대한 정보를 갖지 못하게 된다. 문서의 모든 element - 전체 문서, 헤드, 문서를 위한 document object model의 한 부분이다. 이러한 요소들을 DOM과 자바스크립트 같은 스크립팅 언어를 통해 접근하고 조작할 수 있는 것이다.
- 모든 웹 브라우저는 스크립트가 접근할 수 있는 웹페이지를 만들기 위해 어느정도의 DOM을 항상 사용한다.
-
8월 23일 (화) 리액트의 useCallback useMemo, 정확하게 사용하고 있을까
- 리액트 공식문서를 살펴보다가 useCallback, useMemo에 대해서 공부하다가 살펴본 글
- useMemo와 useCallback을 이용한 최적화의 비용은 공짜가 아니다.
- 리액트 컴포넌트 트리는 매우 클 수 있다. React DevTools를 열고 애플리케이션을 살펴보면, 한번에 많은 컴포넌트가 렌더링 되는 것을 볼 수 있다. 이 과정에서 한두개 정보 불필요한 useCallback, useMemo를 사용하는 것은 별 문제가 되지 않지만, 이 코드가 여기저기 존재한다면 문제가 될 수 있다.
- useCallback은 제공된 deps를 기준으로 반환된 함수 객체를 메모제이션 하는 것 뿐이다. 즉, 동일한 deps가 제공되면 동일한 함수 객체를 반환한다.
- host(호스트환경에 속하는 플랫폼 컴포넌트) 컴포넌트에 div,span,a,img를 전달하는 모든 항목에 대해 사용하지 말아야한다.
- leaf(DOM에서 다른 컴포넌트를 렌더링하지 않는 컴포넌트) 컴포넌트에는 쓰지 말아야한다.
- useCallback, useMemo의 의존성 배열에 완전히 새로운 객체와 배열을 전달해서는 안된다. 이는 항상 의존성이 같지 않다는 결과를 의미하며, 메모제이션을 하는데 소용이 없다.
- 전달하려는 항목이 새로운 참조여도 상관없다면, 사용하지 말아야 한다. 매번 새로운 참조여도 상관없는데, 새로운 참조라면 메모이제이션을 하는 것이 의미가 없다.
- 이럴떄 사용하면 좋다
- 하위 트리에 많은 Consumer가 있는 값을 Context Provider에 전달해야 하는 경우 useMemo를 사용하는 것이 좋다.
- 계산 비용이 많이 들고, 사용자의 입력 값이 map과 filter를 사용했을 떄와 같이 이후 렌더링 이후로도 참조적으로 동일할 가능성이 높은 경우 useMemo를 사용하는 것이 좋다.
- ref 함수를 부수작용과 함께 전달하거나, mergeRef-style과 같이 wrapper 함수를 ref를 만들 때 useMemo를 쓰자. ref 함수의 변경이 있을 때마다, 리액트는 과거 값을 null로 호출하고 새로운 함수를 호출한다. 이경우 ref 함수의 이벤트 리스너를 붙이거나 제거하는 등의 불필요한 작업이 일어날 수 있다.
- 자식 컴포넌트에서 useEffect가 반복적으로 트리거되는 것을 막고 싶을 떄 사용하자.
- 매우 큰 리액트 구조 내에서, 부모가 리렌더링 되었을 때 이에 다른 렌더링 전파를 막고 싶을 때 사용하자. 자식 컴포넌트가 React.memo, 퓨어 컴포넌트일 경우 메모제이션된 props를 사용하게 되면 딱 필요한 부분만 리렌더링 될 것이다.
- React DevTools PRofiler를 사용하면 컴포넌트의 리렌더링 속도가 느린 경우, 상태 변경이 일너았을 때 얼마나 렌더링 시간이 걸렸는지 조사할 수 있다.