1. 브라우저 이벤트 루프(Event Loop)이벤트 루프가 처리하는 작업은 Task와 Microtask로 나뉘는데 이 Task가 일반적으로 Macrotask라 불리는 작업이다. WHATWG 명세에는 Macrotask라는 용어가 존재하지 않음에 유의하자.Event Loop Processing Model #1. Task Queue에서 작업 `oldestTask`을 하나 꺼낸다.2. `oldestTask`을 Event Loop의 currentlyRunningTask로 설정하고 처리한다. (Microtask는 여기에서 처리되는 task가 아니다!)3. currentlyRunningTask를 `null`로 되돌린다.4. Microtask 체크포인트 실행한다. i. Event Loop의 microta..
1. Renderer와 Reconciler #처음 React는 오직 DOM을 위해서만 개발되었지만 React Native와 같은 네이티브 플랫폼을 지원하게 되면서 Renderer와 Reconciler라는 개념이 생겨났다. 상태가 업데이트되어 UI가 업데이트되어야 한다고 했을 때, DOM과 Native에서 UI를 변경하는 방법은 다르다. 하지만 UI가 아닌 React 트리 구조가 어떻게 업데이트되어야 하는지는 두 플랫폼에서 동일한데 이것은 Reconciler의 역할이다. 정리하자면 Renderer는 React 컴포넌트 트리를 어떻게 각각의 플랫폼에 맞는 호출로 변환해 처리할 것인지를 결정한다면, Reconciler는 플랫폼에 상관없는 React의 컴포넌트, 상태, 생애주기 메서드 등이 일관되게 동작할 수 ..
/app/packages├── /hook├── /type└── /componenttsconfig.base.json이러한 모노레포 구조의 프로젝트(npm workspace + Vite + React + TypeScript)가 있다고 해보자. `packages/*`에 있는 개별 패키지를 `/app`이나 다른 패키지에서 가져다 쓰고 싶은 경우 `package.json`, `vite.config.ts`, `tsconfig.json`은 어떻게 작성해야 할까? 우선 `packages/*`에서 `extends`할 `tsconfig.base.json` 파일은 아래와 같이 설정한다.// tsconfig.base.json{ "compilerOptions": { "baseUrl": ".", "target": "..
const obj = { all: ['all'], list: () => [...obj.all, 'list'], detail: (id: string) => [...obj.all, 'detail', id],}이런 JavaScript 객체를 생각해보자. 이 객체의 list 속성의 함수는 내부에서 객체 `obj`를 참조하고 있는데 `obj`가 초기화되지 않은 상태에서 정의되는데 문제가 없을까? 놀랍게도(?) 객체 `obj`가 선언 및 초기화되는 것도, `obj.list()`가 실행되는 과정에서 아무런 에러가 발생하지 않는다. 함수 본문에서 참조하고 있기 때문에 문제가 없는 것 같기도 한데 JavaScript 함수에서 변수가 어떻게 참조되길래 이 코드가 정상적으로 선언되고 실행될까? 1. 실행 컨텍스트..
1. 문자열 인코딩의 역사A. ASCII 코드1960년대, 다양한 통신 시스템들이 각각 고유한 문자 인코딩 방식을 사용했기 때문에 서로 다른 통신 시스템 사이에 문자를 교환하는 것이 무척 까다로웠다. 이러한 문제를 해결하고자 통신 시스템에서 사용하는 문자 인코딩 방식을 통일하기 위해 미국 표준 협회(ANSI)는 아스키(ASCII; American Standard Code for Information Interchange)라는 표준 인코딩 방식을 개발하였다. ASCII 코드1. 7비트로 제어문자, 영문자 및 숫자, 일부 특수문자를 표현(총 128개 문자)2. 당시 많은 시스템, 장비들이 7비트를 기본으로 처리해 ASCII 코드에서도 7비트를 사용해 메모리를 절약하고, 1비트는 데이터의 오류를 확인하기 위한..
1. app 폴더 구조 #A. 기본 폴더 구조Next에서는 /app 폴더 내부에 각각의 경로 세그먼트(route segment)에 해당하는 폴더를 만듦으로써 라우팅이 가능하다. 예를 들어, /app/dashboard/page.js 컴포넌트는 www.mypage.com/dashboard 페이지로 연결된다. 이러한 방식으로 중첩 라우팅이 가능한데, /app/dashboard/setting/page.js 컴포넌트는 www.mypage.com/dashboard/setting 페이지에 해당한다. B. 파일 컨벤션 #① page.js: 해당 경로에 보여줄 UI 컴포넌트② route.js: ③ layout.js: 현재 경로 세그먼트와 자식 세그먼트의 레이아웃을 위한 UI 컴포넌트④ loading.js: 로딩 상태를..
1. Vite 작동 방식(개발 환경)A. 스크립트 파일 로드Vite의 React + TypeScript 탬플릿의 `index.html` 파일을 보면 script 태그에 tsx 파일이 그대로 들어가 있는 걸 볼 수 있다. 브라우저는 JavaScript 파일만 읽을 수 있는데 어떻게 문제가 없이 작동할 수 있는 걸까? `npm run dev`로 개발 서버(ex. http://localhost:3000/)를 시작하면 브라우저에서는 해당 URL의 html 파일을 Vite 개발 서버에 요청한다. 브라우저가 다운받은 html 파일은 아래와 같은데 위 템플릿 html에 스크립트가 추가되어 있다. react-refresh는 React 코드에 변경 사..
이 글은 CSS Flex 아이템 크기 결정 알고리즘: 이론 편을 바탕으로 CSS Flex 아이템의 크기가 어떻게 결정되는지 구체적인 사례를 통해 이해해보는 글이다. 1. 고정 크기의 헤더, 푸터와 유동적인 본문위 사진과 같이 헤더와 푸터의 높이는 고정이고, 본문의 크기는 viewport에 따라서 달라지는 레이아웃을 생각해보자. 이 레이아웃은 Flex를 사용하지 않고 CSS `calc()` 함수를 이용해서 만들 수도 있지만 요구사항이 바뀌어 헤더, 푸터의 높이가 달라진다면 각 요소의 높이를 개별적으로 수정해줘야 하는 불편함이 있다. Flex 레이아웃을 사용한다면 헤더, 푸터의 높이가 달라지더라도 본문의 높이는 수정해줄 필요가 없어 편하다. 이 레이아웃에서 CSS 코드는 아래와 같다..container ..
Figma의 코멘트 요소처럼 캔버스 노드 바로 위에 DOM 요소를 렌더링해야 하는 요구사항이 생기다 보니 react-konva-utils의 ``을 이용해 DOM 요소를 렌더링할 수 있도록 했다. 처음에는 간단한 UI 요소에만 ``을 사용했는데 점점 노드 설정 팝업 등 스타일링이 들어간 요소가 필요하게 되어 styled-components를 사용하게 됐는데 그 과정에서 styled-components의 theme을 제대로 가져오지 못하는 문제에 직면하게 됐다. 이 글은 react-konva-utils의 ``와 styled-components를 사용하면서 theme 설정을 제대로 가져오지 못하는 문제를 해결해나가는, 다소 허무한 여정을 정리한 것이다. 1. styled-components의 테마를 사용할..
모던 웹에서 CSS Flex는 많이 사용되고 개념도 그리 어렵지는 않지만 내가 생각한 결과와 실제 브라우저에서 보여지는 레이아웃이 다르다면 당황스러울 수 있다. 플렉스 너비 결정 알고리즘을 이해한다면 플렉스 아이템의 크기가 왜 그렇게 결정되었는지, 왜 내가 생각한 대로 렌더링되지 않았는지 고민하느라 시간을 낭비하지 않을 수 있을 것이다.문제를 간단하게 하기 위해 플렉스 아이템에 특별히 `position`속성을 설정하지 않은 경우, 그리고 플렉스 메인 축(main axis)이 x축 방향일 때만을 고려해보자.(`flex-direction: column`이라면 동일한 내용을 y축에 대해 적용해주면 된다.)Flex Layout Algorithm1. Initial Setup2. Line Length Determi..
JavaScript/React 2025. 6. 13. 09:09
1. 브라우저 이벤트 루프(Event Loop)이벤트 루프가 처리하는 작업은 Task와 Microtask로 나뉘는데 이 Task가 일반적으로 Macrotask라 불리는 작업이다. WHATWG 명세에는 Macrotask라는 용어가 존재하지 않음에 유의하자.Event Loop Processing Model #1. Task Queue에서 작업 `oldestTask`을 하나 꺼낸다.2. `oldestTask`을 Event Loop의 currentlyRunningTask로 설정하고 처리한다. (Microtask는 여기에서 처리되는 task가 아니다!)3. currentlyRunningTask를 `null`로 되돌린다.4. Microtask 체크포인트 실행한다. i. Event Loop의 microta..
JavaScript/React 2025. 5. 17. 16:55
1. Renderer와 Reconciler #처음 React는 오직 DOM을 위해서만 개발되었지만 React Native와 같은 네이티브 플랫폼을 지원하게 되면서 Renderer와 Reconciler라는 개념이 생겨났다. 상태가 업데이트되어 UI가 업데이트되어야 한다고 했을 때, DOM과 Native에서 UI를 변경하는 방법은 다르다. 하지만 UI가 아닌 React 트리 구조가 어떻게 업데이트되어야 하는지는 두 플랫폼에서 동일한데 이것은 Reconciler의 역할이다. 정리하자면 Renderer는 React 컴포넌트 트리를 어떻게 각각의 플랫폼에 맞는 호출로 변환해 처리할 것인지를 결정한다면, Reconciler는 플랫폼에 상관없는 React의 컴포넌트, 상태, 생애주기 메서드 등이 일관되게 동작할 수 ..
기타 2025. 3. 21. 12:51
/app/packages├── /hook├── /type└── /componenttsconfig.base.json이러한 모노레포 구조의 프로젝트(npm workspace + Vite + React + TypeScript)가 있다고 해보자. `packages/*`에 있는 개별 패키지를 `/app`이나 다른 패키지에서 가져다 쓰고 싶은 경우 `package.json`, `vite.config.ts`, `tsconfig.json`은 어떻게 작성해야 할까? 우선 `packages/*`에서 `extends`할 `tsconfig.base.json` 파일은 아래와 같이 설정한다.// tsconfig.base.json{ "compilerOptions": { "baseUrl": ".", "target": "..
JavaScript 2025. 2. 25. 10:33
const obj = { all: ['all'], list: () => [...obj.all, 'list'], detail: (id: string) => [...obj.all, 'detail', id],}이런 JavaScript 객체를 생각해보자. 이 객체의 list 속성의 함수는 내부에서 객체 `obj`를 참조하고 있는데 `obj`가 초기화되지 않은 상태에서 정의되는데 문제가 없을까? 놀랍게도(?) 객체 `obj`가 선언 및 초기화되는 것도, `obj.list()`가 실행되는 과정에서 아무런 에러가 발생하지 않는다. 함수 본문에서 참조하고 있기 때문에 문제가 없는 것 같기도 한데 JavaScript 함수에서 변수가 어떻게 참조되길래 이 코드가 정상적으로 선언되고 실행될까? 1. 실행 컨텍스트..
기타 2025. 1. 11. 19:13
1. 문자열 인코딩의 역사A. ASCII 코드1960년대, 다양한 통신 시스템들이 각각 고유한 문자 인코딩 방식을 사용했기 때문에 서로 다른 통신 시스템 사이에 문자를 교환하는 것이 무척 까다로웠다. 이러한 문제를 해결하고자 통신 시스템에서 사용하는 문자 인코딩 방식을 통일하기 위해 미국 표준 협회(ANSI)는 아스키(ASCII; American Standard Code for Information Interchange)라는 표준 인코딩 방식을 개발하였다. ASCII 코드1. 7비트로 제어문자, 영문자 및 숫자, 일부 특수문자를 표현(총 128개 문자)2. 당시 많은 시스템, 장비들이 7비트를 기본으로 처리해 ASCII 코드에서도 7비트를 사용해 메모리를 절약하고, 1비트는 데이터의 오류를 확인하기 위한..
JavaScript/Next.js 2024. 12. 28. 18:16
1. app 폴더 구조 #A. 기본 폴더 구조Next에서는 /app 폴더 내부에 각각의 경로 세그먼트(route segment)에 해당하는 폴더를 만듦으로써 라우팅이 가능하다. 예를 들어, /app/dashboard/page.js 컴포넌트는 www.mypage.com/dashboard 페이지로 연결된다. 이러한 방식으로 중첩 라우팅이 가능한데, /app/dashboard/setting/page.js 컴포넌트는 www.mypage.com/dashboard/setting 페이지에 해당한다. B. 파일 컨벤션 #① page.js: 해당 경로에 보여줄 UI 컴포넌트② route.js: ③ layout.js: 현재 경로 세그먼트와 자식 세그먼트의 레이아웃을 위한 UI 컴포넌트④ loading.js: 로딩 상태를..
JavaScript/기타 라이브러리 2024. 11. 23. 16:15
1. Vite 작동 방식(개발 환경)A. 스크립트 파일 로드Vite의 React + TypeScript 탬플릿의 `index.html` 파일을 보면 script 태그에 tsx 파일이 그대로 들어가 있는 걸 볼 수 있다. 브라우저는 JavaScript 파일만 읽을 수 있는데 어떻게 문제가 없이 작동할 수 있는 걸까? `npm run dev`로 개발 서버(ex. http://localhost:3000/)를 시작하면 브라우저에서는 해당 URL의 html 파일을 Vite 개발 서버에 요청한다. 브라우저가 다운받은 html 파일은 아래와 같은데 위 템플릿 html에 스크립트가 추가되어 있다. react-refresh는 React 코드에 변경 사..
CSS 2024. 9. 5. 21:52
이 글은 CSS Flex 아이템 크기 결정 알고리즘: 이론 편을 바탕으로 CSS Flex 아이템의 크기가 어떻게 결정되는지 구체적인 사례를 통해 이해해보는 글이다. 1. 고정 크기의 헤더, 푸터와 유동적인 본문위 사진과 같이 헤더와 푸터의 높이는 고정이고, 본문의 크기는 viewport에 따라서 달라지는 레이아웃을 생각해보자. 이 레이아웃은 Flex를 사용하지 않고 CSS `calc()` 함수를 이용해서 만들 수도 있지만 요구사항이 바뀌어 헤더, 푸터의 높이가 달라진다면 각 요소의 높이를 개별적으로 수정해줘야 하는 불편함이 있다. Flex 레이아웃을 사용한다면 헤더, 푸터의 높이가 달라지더라도 본문의 높이는 수정해줄 필요가 없어 편하다. 이 레이아웃에서 CSS 코드는 아래와 같다..container ..
JavaScript/React 2024. 8. 29. 16:48
Figma의 코멘트 요소처럼 캔버스 노드 바로 위에 DOM 요소를 렌더링해야 하는 요구사항이 생기다 보니 react-konva-utils의 ``을 이용해 DOM 요소를 렌더링할 수 있도록 했다. 처음에는 간단한 UI 요소에만 ``을 사용했는데 점점 노드 설정 팝업 등 스타일링이 들어간 요소가 필요하게 되어 styled-components를 사용하게 됐는데 그 과정에서 styled-components의 theme을 제대로 가져오지 못하는 문제에 직면하게 됐다. 이 글은 react-konva-utils의 ``와 styled-components를 사용하면서 theme 설정을 제대로 가져오지 못하는 문제를 해결해나가는, 다소 허무한 여정을 정리한 것이다. 1. styled-components의 테마를 사용할..
CSS 2024. 8. 7. 12:40
모던 웹에서 CSS Flex는 많이 사용되고 개념도 그리 어렵지는 않지만 내가 생각한 결과와 실제 브라우저에서 보여지는 레이아웃이 다르다면 당황스러울 수 있다. 플렉스 너비 결정 알고리즘을 이해한다면 플렉스 아이템의 크기가 왜 그렇게 결정되었는지, 왜 내가 생각한 대로 렌더링되지 않았는지 고민하느라 시간을 낭비하지 않을 수 있을 것이다.문제를 간단하게 하기 위해 플렉스 아이템에 특별히 `position`속성을 설정하지 않은 경우, 그리고 플렉스 메인 축(main axis)이 x축 방향일 때만을 고려해보자.(`flex-direction: column`이라면 동일한 내용을 y축에 대해 적용해주면 된다.)Flex Layout Algorithm1. Initial Setup2. Line Length Determi..