diff --git a/.vitepress/plugins/markdown-picture.ts b/.vitepress/plugins/markdown-picture.ts index c903ceb..7b69e87 100644 --- a/.vitepress/plugins/markdown-picture.ts +++ b/.vitepress/plugins/markdown-picture.ts @@ -52,11 +52,36 @@ function convertImgToPicture( additionalAttrs: string = "", ): string { const safeAlt = alt || ""; - const safeAttrs = additionalAttrs && additionalAttrs.trim() ? " " + additionalAttrs.trim() : ""; + let safeAttrs = additionalAttrs && additionalAttrs.trim() ? " " + additionalAttrs.trim() : ""; + let pictureStyle = ""; + + // width 속성 처리: 퍼센트나 단위가 있는 경우 picture의 스타일로 이동하여 중첩 계산 방지 + const widthMatch = /width=["']([^"']+)["']/i.exec(safeAttrs); + if (widthMatch) { + const widthVal = widthMatch[1]; + if (widthVal.includes("%") || widthVal.includes("px")) { + pictureStyle = `width: ${widthVal}; display: inline-block;`; + // img 태그에서는 원본 width 속성을 제거하고 내부적으로 100%를 가지도록 함 + safeAttrs = safeAttrs.replace(/width=["'][^"']*["']/gi, "").trim(); + + if (safeAttrs.includes("style=\"")) { + safeAttrs = safeAttrs.replace(/style=["']([^"']*)["']/i, (m, s) => { + const baseStyle = s.trim(); + const separator = baseStyle && !baseStyle.endsWith(";") ? ";" : ""; + return `style="${baseStyle}${separator} width: 100%;"`; + }); + } else { + safeAttrs += " style=\"width: 100%;\""; + } + } else { + // 숫자만 있는 경우(HTML5 표준) px 제거 로직 유지 + safeAttrs = safeAttrs.replace(/width="(\d+)(px)?"/gi, "width=\"$1\""); + } + } // 외부 URL이거나 svg, gif는 picture 태그로 변환하지 않음 if (src.startsWith("http") || src.endsWith(".svg") || src.endsWith(".gif")) { - return `${safeAlt}`; + return `${safeAlt}`; } // 이미지 포맷별 경로 생성 @@ -82,13 +107,14 @@ function convertImgToPicture( // 변환된 이미지가 없으면 원본만 사용 if (sources.length === 0) { - return `${safeAlt}`; + return `${safeAlt}`; } // picture 태그 생성 (원본을 최종 fallback으로 사용) - return ` + const pictureAttr = pictureStyle ? ` style="${pictureStyle}"` : ""; + return ` ${sources.join("\n ")} - ${safeAlt} + ${safeAlt} `; } @@ -117,6 +143,7 @@ function processHtmlImages(html: string, markdownPath: string): string { .replace(/src=["'][^"']*["']/gi, "") .replace(/alt=["'][^"']*["']/gi, "") .replace(/loading=["'][^"']*["']/gi, "") // loading은 우리가 추가할 것이므로 제거 + .replace(/\s+/g, " ") // 중복 공백 제거 .trim(); // 속성이 비어있거나 공백만 있으면 빈 문자열로 @@ -142,16 +169,23 @@ export function markdownPicturePlugin(md: MarkdownIt) { md.renderer.rules.image = (tokens, idx, options, env, self) => { const token = tokens[idx]; const srcIndex = token.attrIndex("src"); + const altIndex = token.attrIndex("alt"); if (srcIndex < 0) { return defaultRender(tokens, idx, options, env, self); } const src = token.attrs![srcIndex][1]; - const alt = token.content; + const alt = altIndex >= 0 ? token.attrs![altIndex][1] : token.content || ""; const markdownPath = env.path || ""; - return convertImgToPicture(src, alt, markdownPath); + // src, alt를 제외한 나머지 속성들 추출 (width, height 등) + const additionalAttrs = token.attrs! + .filter(([name]) => name !== "src" && name !== "alt") + .map(([name, value]) => `${name}="${value}"`) + .join(" "); + + return convertImgToPicture(src, alt, markdownPath, additionalAttrs); }; // 2. HTML inline 이미지 () 처리 diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..2788ce1 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,57 @@ +# ToothlessDev Blog + +이 프로젝트는 VitePress를 기반으로 구축된 기술 블로그 및 포트폴리오 사이트입니다. + +## 프로젝트 개요 +- **프레임워크:** [VitePress](https://vitepress.dev/) (Vue 기반 정적 사이트 생성기) +- **주요 기술:** TypeScript, Vue 3, Vanilla CSS +- **콘텐츠 관리:** `contents/` 디렉토리 내의 마크다운 파일 +- **주요 기능:** + - 이미지 자동 최적화 (Sharp 사용) + - KaTeX를 이용한 수식 렌더링 + - Giscus를 이용한 댓글 시스템 + - 포스트 목록 및 사이드바 자동 생성 플러그인 + +## 디렉토리 구조 +- `.vitepress/`: VitePress 설정 및 커스텀 플러그인 (`plugins/`) +- `contents/`: 마크다운 콘텐츠 + - `posts/`: 기술 블로그 포스트 + - `projects/`: 프로젝트 소개 + - `archive/`: 아카이브 페이지 +- `src/`: 테마 커스터마이징을 위한 Vue 컴포넌트 및 유틸리티 +- `scripts/`: 포스트 데이터 생성을 위한 스크립트 +- `data/`: 자동 생성된 포스트 데이터 (`posts.json`) + +## 개발 및 빌드 명령 +- **의존성 설치:** `yarn install` +- **로컬 개발 서버 실행:** `npm run docs:dev` +- **프로젝트 빌드:** `npm run docs:build` +- **빌드 결과물 미리보기:** `npm run docs:preview` +- **포스트 데이터 수동 생성:** `npm run generate-posts` + +## 개발 컨벤션 +### 포스트 작성 (Markdown) +모든 포스트는 `contents/posts/` 하위 디렉토리에 위치해야 하며, 다음의 frontmatter 형식을 반드시 준수해야 합니다: +```yaml +--- +title: "포스트 제목" +description: "포스트 요약 설명" +createdAt: "2024-03-20" +category: "카테고리명" +comment: true # 댓글 활성화 여부 +--- +``` +- `index.md` 파일은 포스트 목록 생성에서 제외됩니다. +- 이미지는 각 포스트 디렉토리 내의 `img/` 폴더에 위치시키는 것을 권장합니다. + +### 스타일링 +- 컴포넌트별로 전용 `.css` 파일을 생성하여 관리합니다 (`src/components/` 참조). +- 전역 스타일은 `.vitepress/theme/style.css`에서 관리합니다. + +### 아키텍처 및 플러그인 +- **플러그인 시스템:** `.vitepress/plugins/`에 위치한 커스텀 Vite 플러그인을 통해 빌드 시 포스트 목록 생성, 이미지 최적화 등을 자동화합니다. +- **데이터 흐름:** 마크다운 파일 수정 -> Vite 플러그인 감지 -> `generate-posts.mjs` 실행 -> `data/posts.json` 업데이트 -> UI 반영 + +## 배포 +- GitHub Actions를 통해 `main` 브랜치 푸시 시 자동 배포됩니다. +- 배포 설정은 `.github/workflows/deploy.yml`에 정의되어 있습니다. diff --git a/contents/posts/Aws/img/lambda-img-optimization/optimize.jpeg b/contents/posts/Aws/lambda-image-optimization/img/optimize.jpeg similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/optimize.jpeg rename to contents/posts/Aws/lambda-image-optimization/img/optimize.jpeg diff --git a/contents/posts/Aws/img/lambda-img-optimization/optimize.jpg b/contents/posts/Aws/lambda-image-optimization/img/optimize.jpg similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/optimize.jpg rename to contents/posts/Aws/lambda-image-optimization/img/optimize.jpg diff --git a/contents/posts/Aws/img/lambda-img-optimization/optimize.webp b/contents/posts/Aws/lambda-image-optimization/img/optimize.webp similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/optimize.webp rename to contents/posts/Aws/lambda-image-optimization/img/optimize.webp diff --git a/contents/posts/Aws/img/lambda-img-optimization/setup-lambda.jpeg b/contents/posts/Aws/lambda-image-optimization/img/setup-lambda.jpeg similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/setup-lambda.jpeg rename to contents/posts/Aws/lambda-image-optimization/img/setup-lambda.jpeg diff --git a/contents/posts/Aws/img/lambda-img-optimization/setup-lambda.png b/contents/posts/Aws/lambda-image-optimization/img/setup-lambda.png similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/setup-lambda.png rename to contents/posts/Aws/lambda-image-optimization/img/setup-lambda.png diff --git a/contents/posts/Aws/img/lambda-img-optimization/setup-lambda.webp b/contents/posts/Aws/lambda-image-optimization/img/setup-lambda.webp similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/setup-lambda.webp rename to contents/posts/Aws/lambda-image-optimization/img/setup-lambda.webp diff --git a/contents/posts/Aws/img/lambda-img-optimization/setup-trigger.jpeg b/contents/posts/Aws/lambda-image-optimization/img/setup-trigger.jpeg similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/setup-trigger.jpeg rename to contents/posts/Aws/lambda-image-optimization/img/setup-trigger.jpeg diff --git a/contents/posts/Aws/img/lambda-img-optimization/setup-trigger.png b/contents/posts/Aws/lambda-image-optimization/img/setup-trigger.png similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/setup-trigger.png rename to contents/posts/Aws/lambda-image-optimization/img/setup-trigger.png diff --git a/contents/posts/Aws/img/lambda-img-optimization/setup-trigger.webp b/contents/posts/Aws/lambda-image-optimization/img/setup-trigger.webp similarity index 100% rename from contents/posts/Aws/img/lambda-img-optimization/setup-trigger.webp rename to contents/posts/Aws/lambda-image-optimization/img/setup-trigger.webp diff --git a/contents/posts/Aws/lambda-image-optimization.md b/contents/posts/Aws/lambda-image-optimization/index.md similarity index 93% rename from contents/posts/Aws/lambda-image-optimization.md rename to contents/posts/Aws/lambda-image-optimization/index.md index 69186b7..1292329 100644 --- a/contents/posts/Aws/lambda-image-optimization.md +++ b/contents/posts/Aws/lambda-image-optimization/index.md @@ -7,7 +7,7 @@ comment: true --- :::info -이 글은 [응~ 이미지 키워봐~ 최적화 하면 그만이야 🤡 (pt1. 이미지 포맷)](../Web/image-format.md) 글의 속편입니다. +이 글은 [응~ 이미지 키워봐~ 최적화 하면 그만이야 🤡 (pt1. 이미지 포맷)](../../Web/image-format/index.md) 글의 속편입니다. 지난 글에서 이미지 포맷 선택이 얼마나 중요한지 살펴봤다면,
이번 글에서는 **AWS Lambda와 S3 이벤트를 활용해 업로드 시점에서 자동으로 이미지 최적화**하는 방법을 다룹니다. ::: @@ -17,7 +17,7 @@ comment: true 디자인학과 졸업전시 웹사이트를 만들면서, 이미지 때문에 꽤나 고생을 했습니다. 학생들이 주는 작품 사진은 대부분 몇 MB가 넘는 고화질의 원본이었고, 저는 그걸 웹에 맞게 리사이즈해서 올려야 했습니다. -![최적화 해야한다.... vs 딸깍!](./img/lambda-img-optimization/optimize.jpg) +![최적화 해야한다.... vs 딸깍!](./img/optimize.jpg) 처음에는 로컬에서 일일이 줄여 업로드했지만, 작품 수가 수십 개, 이미지가 수백 장을 넘어가자 상황은 달라졌습니다. 리사이즈 작업만으로도 반나절이 날아가고, 썸네일·포맷별 파일까지 관리하려니 점점 감당하기 힘들어졌습니다. @@ -50,11 +50,11 @@ AWS Lambda는 서버를 직접 관리하지 않고도 코드를 실행할 수 그 다음, AWS Lambda 콘솔에서 새 Lambda 함수를 생성합니다. -![Lambda 함수 생성](./img/lambda-img-optimization/setup-lambda.png) +![Lambda 함수 생성](./img/setup-lambda.png) 아래쪽에 `구성` > `트리거` > `트리거 추가` 를 클릭해 S3 트리거를 설정합니다. -![S3 Trigger 설정](./img/lambda-img-optimization/setup-trigger.png) +![S3 Trigger 설정](./img/setup-trigger.png) ## Presigned URL 로 이미지 업로드 시점에 Lambda 트리거하기 diff --git a/contents/posts/CS/Algorithm/img/permutation-dfs.gif b/contents/posts/CS/Algorithm/permutation-combination/img/permutation-dfs.gif similarity index 100% rename from contents/posts/CS/Algorithm/img/permutation-dfs.gif rename to contents/posts/CS/Algorithm/permutation-combination/img/permutation-dfs.gif diff --git a/contents/posts/CS/Algorithm/img/permutation-swap.gif b/contents/posts/CS/Algorithm/permutation-combination/img/permutation-swap.gif similarity index 100% rename from contents/posts/CS/Algorithm/img/permutation-swap.gif rename to contents/posts/CS/Algorithm/permutation-combination/img/permutation-swap.gif diff --git a/contents/posts/CS/Algorithm/permutation-combination.md b/contents/posts/CS/Algorithm/permutation-combination/index.md similarity index 100% rename from contents/posts/CS/Algorithm/permutation-combination.md rename to contents/posts/CS/Algorithm/permutation-combination/index.md diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/base-cas.jpeg b/contents/posts/CS/DataStructure/content-addressable-store/img/base-cas.jpeg similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/base-cas.jpeg rename to contents/posts/CS/DataStructure/content-addressable-store/img/base-cas.jpeg diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/base-cas.png b/contents/posts/CS/DataStructure/content-addressable-store/img/base-cas.png similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/base-cas.png rename to contents/posts/CS/DataStructure/content-addressable-store/img/base-cas.png diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/base-cas.webp b/contents/posts/CS/DataStructure/content-addressable-store/img/base-cas.webp similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/base-cas.webp rename to contents/posts/CS/DataStructure/content-addressable-store/img/base-cas.webp diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/chunking-sharding.jpeg b/contents/posts/CS/DataStructure/content-addressable-store/img/chunking-sharding.jpeg similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/chunking-sharding.jpeg rename to contents/posts/CS/DataStructure/content-addressable-store/img/chunking-sharding.jpeg diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/chunking-sharding.png b/contents/posts/CS/DataStructure/content-addressable-store/img/chunking-sharding.png similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/chunking-sharding.png rename to contents/posts/CS/DataStructure/content-addressable-store/img/chunking-sharding.png diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/chunking-sharding.webp b/contents/posts/CS/DataStructure/content-addressable-store/img/chunking-sharding.webp similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/chunking-sharding.webp rename to contents/posts/CS/DataStructure/content-addressable-store/img/chunking-sharding.webp diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hash-tree.jpeg b/contents/posts/CS/DataStructure/content-addressable-store/img/hash-tree.jpeg similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hash-tree.jpeg rename to contents/posts/CS/DataStructure/content-addressable-store/img/hash-tree.jpeg diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hash-tree.png b/contents/posts/CS/DataStructure/content-addressable-store/img/hash-tree.png similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hash-tree.png rename to contents/posts/CS/DataStructure/content-addressable-store/img/hash-tree.png diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hash-tree.webp b/contents/posts/CS/DataStructure/content-addressable-store/img/hash-tree.webp similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hash-tree.webp rename to contents/posts/CS/DataStructure/content-addressable-store/img/hash-tree.webp diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hash.jpeg b/contents/posts/CS/DataStructure/content-addressable-store/img/hash.jpeg similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hash.jpeg rename to contents/posts/CS/DataStructure/content-addressable-store/img/hash.jpeg diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hash.png b/contents/posts/CS/DataStructure/content-addressable-store/img/hash.png similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hash.png rename to contents/posts/CS/DataStructure/content-addressable-store/img/hash.png diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hash.webp b/contents/posts/CS/DataStructure/content-addressable-store/img/hash.webp similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hash.webp rename to contents/posts/CS/DataStructure/content-addressable-store/img/hash.webp diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hashmap-inconsistent.jpeg b/contents/posts/CS/DataStructure/content-addressable-store/img/hashmap-inconsistent.jpeg similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hashmap-inconsistent.jpeg rename to contents/posts/CS/DataStructure/content-addressable-store/img/hashmap-inconsistent.jpeg diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hashmap-inconsistent.png b/contents/posts/CS/DataStructure/content-addressable-store/img/hashmap-inconsistent.png similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hashmap-inconsistent.png rename to contents/posts/CS/DataStructure/content-addressable-store/img/hashmap-inconsistent.png diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/hashmap-inconsistent.webp b/contents/posts/CS/DataStructure/content-addressable-store/img/hashmap-inconsistent.webp similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/hashmap-inconsistent.webp rename to contents/posts/CS/DataStructure/content-addressable-store/img/hashmap-inconsistent.webp diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/metadata-disk.jpeg b/contents/posts/CS/DataStructure/content-addressable-store/img/metadata-disk.jpeg similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/metadata-disk.jpeg rename to contents/posts/CS/DataStructure/content-addressable-store/img/metadata-disk.jpeg diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/metadata-disk.png b/contents/posts/CS/DataStructure/content-addressable-store/img/metadata-disk.png similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/metadata-disk.png rename to contents/posts/CS/DataStructure/content-addressable-store/img/metadata-disk.png diff --git a/contents/posts/CS/DataStructure/img/content-addressable-store/metadata-disk.webp b/contents/posts/CS/DataStructure/content-addressable-store/img/metadata-disk.webp similarity index 100% rename from contents/posts/CS/DataStructure/img/content-addressable-store/metadata-disk.webp rename to contents/posts/CS/DataStructure/content-addressable-store/img/metadata-disk.webp diff --git a/contents/posts/CS/DataStructure/content-addressable-store.md b/contents/posts/CS/DataStructure/content-addressable-store/index.md similarity index 93% rename from contents/posts/CS/DataStructure/content-addressable-store.md rename to contents/posts/CS/DataStructure/content-addressable-store/index.md index 8285943..947ca79 100644 --- a/contents/posts/CS/DataStructure/content-addressable-store.md +++ b/contents/posts/CS/DataStructure/content-addressable-store/index.md @@ -27,7 +27,7 @@ CAS는 간단히 말해서 내용기반 식별입니다
여기서, CAS 가 주는 불변성이 매우 중요합니다
-Content Addressable Store 의 핵심 아이디어 +Content Addressable Store 의 핵심 아이디어
### 1️⃣ 동일내용 = 동일 키 (Deduplication) @@ -61,7 +61,7 @@ const contentAddressableStore = new Map(); ```
-해시맵 구조의 Content Addressable Store +해시맵 구조의 Content Addressable Store
이것만으로도 CAS 의 기본 기능은 구현할 수 있습니다
@@ -85,7 +85,7 @@ const contentAddressableStore = new Map(); 가 있습니다.
-디스크 기반 인덱싱 구조 +디스크 기반 인덱싱 구조
해시맵의 키로 Content 의 해시값을 사용하고,
@@ -117,7 +117,7 @@ ab12cd... -> ab/12cd... Chunking 과 Prefix Sharding 을 함께 사용하면 다음과 같은 구조가 됩니다 -Chunking 과 Sharding +Chunking 과 Sharding ## Hash Tree 를 이용한 내용 무결성 검증 @@ -131,7 +131,7 @@ Content Addressable Store 는 데이터를 `내용 기반 주소` 로 식별하 예를들어 데이터를 저장할때, metadata 는 메모리 (해시 맵) 에 저장됐지만, content 는 디스크 (BlobStorage) 에 저장이 안된 경우가 있을 수 있습니다
-저장 과정의 일관성 문제 +저장 과정의 일관성 문제
이런 경우 CAS 는 `주소 - 내용` 매핑이 깨지게 됩니다.
@@ -177,7 +177,7 @@ TCP 는 Checksum 을 두고 TLS 는 MAC(Message Authentication Code) 을 사용 - 리프 노드는 실제 데이터 블록의 해시값을 저장하고,
- 내부 노드는 자식 노드들의 해시값을 조합하여 해시값을 계산합니다
-![alt text](./img/content-addressable-store/hash-tree.png) +![alt text](./img/hash-tree.png) #### 🤔 Merkle Tree 로 무결성 검증이 어떻게 이루어질까 ? diff --git a/contents/posts/CS/DataStructure/img/idempotency-hash-table/cart-hash-func.jpeg b/contents/posts/CS/DataStructure/idempotency-hash-table/img/cart-hash-func.jpeg similarity index 100% rename from contents/posts/CS/DataStructure/img/idempotency-hash-table/cart-hash-func.jpeg rename to contents/posts/CS/DataStructure/idempotency-hash-table/img/cart-hash-func.jpeg diff --git a/contents/posts/CS/DataStructure/img/idempotency-hash-table/cart-hash-func.png b/contents/posts/CS/DataStructure/idempotency-hash-table/img/cart-hash-func.png similarity index 100% rename from contents/posts/CS/DataStructure/img/idempotency-hash-table/cart-hash-func.png rename to contents/posts/CS/DataStructure/idempotency-hash-table/img/cart-hash-func.png diff --git a/contents/posts/CS/DataStructure/img/idempotency-hash-table/cart-hash-func.webp b/contents/posts/CS/DataStructure/idempotency-hash-table/img/cart-hash-func.webp similarity index 100% rename from contents/posts/CS/DataStructure/img/idempotency-hash-table/cart-hash-func.webp rename to contents/posts/CS/DataStructure/idempotency-hash-table/img/cart-hash-func.webp diff --git a/contents/posts/CS/DataStructure/idempotency-hash-table.md b/contents/posts/CS/DataStructure/idempotency-hash-table/index.md similarity index 99% rename from contents/posts/CS/DataStructure/idempotency-hash-table.md rename to contents/posts/CS/DataStructure/idempotency-hash-table/index.md index 46c8e72..f2bf135 100644 --- a/contents/posts/CS/DataStructure/idempotency-hash-table.md +++ b/contents/posts/CS/DataStructure/idempotency-hash-table/index.md @@ -135,7 +135,7 @@ const cartItem2 = { > 같은 입력 = 샌드위치 id + 옵션 조합
> 같은 결과 = 장바구니 항목의 고유키 -![alt text](./img/idempotency-hash-table/cart-hash-func.png) +![alt text](./img/cart-hash-func.png) ### 1️⃣ 단순 순회하면서 비교하기 diff --git a/contents/posts/Etc/img/2025-toss-interview/gemini.jpeg b/contents/posts/Etc/2025-toss-interview/img/gemini.jpeg similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/gemini.jpeg rename to contents/posts/Etc/2025-toss-interview/img/gemini.jpeg diff --git a/contents/posts/Etc/img/2025-toss-interview/gemini.png b/contents/posts/Etc/2025-toss-interview/img/gemini.png similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/gemini.png rename to contents/posts/Etc/2025-toss-interview/img/gemini.png diff --git a/contents/posts/Etc/img/2025-toss-interview/gemini.webp b/contents/posts/Etc/2025-toss-interview/img/gemini.webp similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/gemini.webp rename to contents/posts/Etc/2025-toss-interview/img/gemini.webp diff --git a/contents/posts/Etc/img/2025-toss-interview/study-1.webp b/contents/posts/Etc/2025-toss-interview/img/study-1.webp similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/study-1.webp rename to contents/posts/Etc/2025-toss-interview/img/study-1.webp diff --git a/contents/posts/Etc/img/2025-toss-interview/study-2.jpeg b/contents/posts/Etc/2025-toss-interview/img/study-2.jpeg similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/study-2.jpeg rename to contents/posts/Etc/2025-toss-interview/img/study-2.jpeg diff --git a/contents/posts/Etc/img/2025-toss-interview/study-2.png b/contents/posts/Etc/2025-toss-interview/img/study-2.png similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/study-2.png rename to contents/posts/Etc/2025-toss-interview/img/study-2.png diff --git a/contents/posts/Etc/img/2025-toss-interview/study-2.webp b/contents/posts/Etc/2025-toss-interview/img/study-2.webp similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/study-2.webp rename to contents/posts/Etc/2025-toss-interview/img/study-2.webp diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-auth.jpeg b/contents/posts/Etc/2025-toss-interview/img/toss-auth.jpeg similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-auth.jpeg rename to contents/posts/Etc/2025-toss-interview/img/toss-auth.jpeg diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-auth.png b/contents/posts/Etc/2025-toss-interview/img/toss-auth.png similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-auth.png rename to contents/posts/Etc/2025-toss-interview/img/toss-auth.png diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-auth.webp b/contents/posts/Etc/2025-toss-interview/img/toss-auth.webp similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-auth.webp rename to contents/posts/Etc/2025-toss-interview/img/toss-auth.webp diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-cta.jpeg b/contents/posts/Etc/2025-toss-interview/img/toss-cta.jpeg similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-cta.jpeg rename to contents/posts/Etc/2025-toss-interview/img/toss-cta.jpeg diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-cta.png b/contents/posts/Etc/2025-toss-interview/img/toss-cta.png similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-cta.png rename to contents/posts/Etc/2025-toss-interview/img/toss-cta.png diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-cta.webp b/contents/posts/Etc/2025-toss-interview/img/toss-cta.webp similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-cta.webp rename to contents/posts/Etc/2025-toss-interview/img/toss-cta.webp diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-failed.jpeg b/contents/posts/Etc/2025-toss-interview/img/toss-failed.jpeg similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-failed.jpeg rename to contents/posts/Etc/2025-toss-interview/img/toss-failed.jpeg diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-failed.png b/contents/posts/Etc/2025-toss-interview/img/toss-failed.png similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-failed.png rename to contents/posts/Etc/2025-toss-interview/img/toss-failed.png diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-failed.webp b/contents/posts/Etc/2025-toss-interview/img/toss-failed.webp similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-failed.webp rename to contents/posts/Etc/2025-toss-interview/img/toss-failed.webp diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-passed.jpeg b/contents/posts/Etc/2025-toss-interview/img/toss-passed.jpeg similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-passed.jpeg rename to contents/posts/Etc/2025-toss-interview/img/toss-passed.jpeg diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-passed.png b/contents/posts/Etc/2025-toss-interview/img/toss-passed.png similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-passed.png rename to contents/posts/Etc/2025-toss-interview/img/toss-passed.png diff --git a/contents/posts/Etc/img/2025-toss-interview/toss-passed.webp b/contents/posts/Etc/2025-toss-interview/img/toss-passed.webp similarity index 100% rename from contents/posts/Etc/img/2025-toss-interview/toss-passed.webp rename to contents/posts/Etc/2025-toss-interview/img/toss-passed.webp diff --git a/contents/posts/Etc/2025-toss-interview.md b/contents/posts/Etc/2025-toss-interview/index.md similarity index 93% rename from contents/posts/Etc/2025-toss-interview.md rename to contents/posts/Etc/2025-toss-interview/index.md index f7965c3..c8c0bf7 100644 --- a/contents/posts/Etc/2025-toss-interview.md +++ b/contents/posts/Etc/2025-toss-interview/index.md @@ -22,7 +22,7 @@ head: 토스뱅크는 단순히 가기 어려운 회사가 아니라, 내가 되고 싶은 개발자의 모습이 담긴 회사였다 -[대학 시절 창업을 도전했다가 실패한 경험](./roomfit-failure.md) 이 있었는데, 그 과정에서 토스 이승건 대표님의 영상을 보고 많은 깨달음을 얻었다 +[대학 시절 창업을 도전했다가 실패한 경험](../roomfit-failure/) 이 있었는데, 그 과정에서 토스 이승건 대표님의 영상을 보고 많은 깨달음을 얻었다 그 과정에서 토스가 추구하는 가치관과 개발 문화가 나와 잘 맞는다는 생각이 들었고, 언젠가 꼭 토스에서 일하고 싶다는 목표를 가지게 되었다
특히 "사용자를 위해 불편을 부수는 집요함" 이라는 철학을 접했고, 내가 생각했던 개발자의 모습과도 일치했다. @@ -32,8 +32,8 @@ head: 토스는 이걸 진짜 현실로 만들어낸 팀이라고 생각했다.
- 토스뱅크가 혁신적으로 인증절차를 바꾼 이야기 - 토스뱅크가 IOS 에서 BottomCTA 버튼이 사라지는 현상을 해결한 이야기 + 토스뱅크가 혁신적으로 인증절차를 바꾼 이야기 + 토스뱅크가 IOS 에서 BottomCTA 버튼이 사라지는 현상을 해결한 이야기
:::details [개발자를 성장시키는 토스의 개발 문화 3가지 | 박서진 토스 Head of Frontend | Square of Toss](https://www.youtube.com/watch?v=RzVABPt9f-g) @@ -79,7 +79,7 @@ UX, 유지보수성, 아키텍쳐 각각에서 개발자경험과 사용자 경 모든 레포에 Gemini Code Assist를 붙여놓은 상태였는데, PR을 제출하고 나니 얘가 갑자기 크리티컬한 문제가 있다고 소리를 지르는것이었다 -![](./img/2025-toss-interview/gemini.png) +![](./img/gemini.png) 하... 떨어졌구나 @@ -90,7 +90,7 @@ UX, 유지보수성, 아키텍쳐 각각에서 개발자경험과 사용자 경 근데 며칠 뒤, 과제합격 메일이 도착했다
현실을 잠깐 의심했다. 진짜?? 아니 이게 진짜라고? -토스뱅크 프론트엔드 과제 합격 메일 +토스뱅크 프론트엔드 과제 합격 메일 진짜 하루종일 이렇게 기쁠 수가 없었다. @@ -101,7 +101,7 @@ UX, 유지보수성, 아키텍쳐 각각에서 개발자경험과 사용자 경 너무가고싶은 마음에 면접보기 전까지 쥐죽은듯이 공부했다.
근 몇달간 가장 집중을 많이하고 공부를 많이 했지 않나.. 싶다 - + ## 😵 대망의 면접날 고해성사를 시작합니다 @@ -288,7 +288,7 @@ UX, 유지보수성, 아키텍쳐 각각에서 개발자경험과 사용자 경 ## 🥲 다음 기회를 기약하며.. -토스뱅크 프론트엔드 면접 불합격 메일 +토스뱅크 프론트엔드 면접 불합격 메일 뭐... 결국은 불합격했다. diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/feedback.jpeg b/contents/posts/Etc/kakao-tech-campus-record/img/feedback.jpeg similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/feedback.jpeg rename to contents/posts/Etc/kakao-tech-campus-record/img/feedback.jpeg diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/feedback.png b/contents/posts/Etc/kakao-tech-campus-record/img/feedback.png similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/feedback.png rename to contents/posts/Etc/kakao-tech-campus-record/img/feedback.png diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/feedback.webp b/contents/posts/Etc/kakao-tech-campus-record/img/feedback.webp similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/feedback.webp rename to contents/posts/Etc/kakao-tech-campus-record/img/feedback.webp diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/ideathon-1.jpeg b/contents/posts/Etc/kakao-tech-campus-record/img/ideathon-1.jpeg similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/ideathon-1.jpeg rename to contents/posts/Etc/kakao-tech-campus-record/img/ideathon-1.jpeg diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/ideathon-1.jpg b/contents/posts/Etc/kakao-tech-campus-record/img/ideathon-1.jpg similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/ideathon-1.jpg rename to contents/posts/Etc/kakao-tech-campus-record/img/ideathon-1.jpg diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/ideathon-1.webp b/contents/posts/Etc/kakao-tech-campus-record/img/ideathon-1.webp similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/ideathon-1.webp rename to contents/posts/Etc/kakao-tech-campus-record/img/ideathon-1.webp diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/ideathon-2.jpeg b/contents/posts/Etc/kakao-tech-campus-record/img/ideathon-2.jpeg similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/ideathon-2.jpeg rename to contents/posts/Etc/kakao-tech-campus-record/img/ideathon-2.jpeg diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/ideathon-2.jpg b/contents/posts/Etc/kakao-tech-campus-record/img/ideathon-2.jpg similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/ideathon-2.jpg rename to contents/posts/Etc/kakao-tech-campus-record/img/ideathon-2.jpg diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/ideathon-2.webp b/contents/posts/Etc/kakao-tech-campus-record/img/ideathon-2.webp similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/ideathon-2.webp rename to contents/posts/Etc/kakao-tech-campus-record/img/ideathon-2.webp diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/lec-1.webp b/contents/posts/Etc/kakao-tech-campus-record/img/lec-1.webp similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/lec-1.webp rename to contents/posts/Etc/kakao-tech-campus-record/img/lec-1.webp diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/lec-2.webp b/contents/posts/Etc/kakao-tech-campus-record/img/lec-2.webp similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/lec-2.webp rename to contents/posts/Etc/kakao-tech-campus-record/img/lec-2.webp diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pass.jpeg b/contents/posts/Etc/kakao-tech-campus-record/img/pass.jpeg similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pass.jpeg rename to contents/posts/Etc/kakao-tech-campus-record/img/pass.jpeg diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pass.png b/contents/posts/Etc/kakao-tech-campus-record/img/pass.png similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pass.png rename to contents/posts/Etc/kakao-tech-campus-record/img/pass.png diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pass.webp b/contents/posts/Etc/kakao-tech-campus-record/img/pass.webp similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pass.webp rename to contents/posts/Etc/kakao-tech-campus-record/img/pass.webp diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pr-1.jpeg b/contents/posts/Etc/kakao-tech-campus-record/img/pr-1.jpeg similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pr-1.jpeg rename to contents/posts/Etc/kakao-tech-campus-record/img/pr-1.jpeg diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pr-1.png b/contents/posts/Etc/kakao-tech-campus-record/img/pr-1.png similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pr-1.png rename to contents/posts/Etc/kakao-tech-campus-record/img/pr-1.png diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pr-1.webp b/contents/posts/Etc/kakao-tech-campus-record/img/pr-1.webp similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pr-1.webp rename to contents/posts/Etc/kakao-tech-campus-record/img/pr-1.webp diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pr-2.jpeg b/contents/posts/Etc/kakao-tech-campus-record/img/pr-2.jpeg similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pr-2.jpeg rename to contents/posts/Etc/kakao-tech-campus-record/img/pr-2.jpeg diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pr-2.png b/contents/posts/Etc/kakao-tech-campus-record/img/pr-2.png similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pr-2.png rename to contents/posts/Etc/kakao-tech-campus-record/img/pr-2.png diff --git a/contents/posts/Etc/img/kakao-tech-campus-record/pr-2.webp b/contents/posts/Etc/kakao-tech-campus-record/img/pr-2.webp similarity index 100% rename from contents/posts/Etc/img/kakao-tech-campus-record/pr-2.webp rename to contents/posts/Etc/kakao-tech-campus-record/img/pr-2.webp diff --git a/contents/posts/Etc/kakao-tech-campus-record.md b/contents/posts/Etc/kakao-tech-campus-record/index.md similarity index 94% rename from contents/posts/Etc/kakao-tech-campus-record.md rename to contents/posts/Etc/kakao-tech-campus-record/index.md index c80051c..528f181 100644 --- a/contents/posts/Etc/kakao-tech-campus-record.md +++ b/contents/posts/Etc/kakao-tech-campus-record/index.md @@ -18,7 +18,7 @@ head: 졸업을 위한 현장실습 대체 학점을 채워야 했고, 마침 카카오 테크캠퍼스가 그걸 채워줄 수 있었고, "어차피 할 거면 카카오 이름 달린 데서 하면 좋지" 정도의 마음가짐이었습니다
- +
부트캠프에 대한 이미지도 솔직히 그렇게 좋진 않았습니다.
@@ -73,8 +73,8 @@ PR 을 올릴 때, 질문을 진짜 많이 적었고, 고민한 흔적 설계 리뷰해주시는 멘토님들이 꽤 고생을 많이 하셨을 것 같습니다 ㅋㅋㅋ
- - + +
:::details 💬 멘토님과 함께한 코드리뷰 PR 모음 @@ -172,7 +172,7 @@ PR 을 올릴 때, 질문을 진짜 많이 적었고, 고민한 흔적 설계 실무에서 `generator` 많이 쓰시나요? 라고 여쭤봤는데 멘토님이 이렇게 답해주셨습니다.
- +
좋은 코드는 단순히 변수명이 깔끔하고, 여러 설계원칙을 잘 지키는 그런 코드가 아니라
@@ -191,8 +191,8 @@ PR 을 올릴 때, 질문을 진짜 많이 적었고, 고민한 흔적 설계 아직 취업은 못했지만, 이런 사소해보이는 습관들이 저를 조금은 더 준비된 상태로 만들어줬다고 생각합니다 ㅎㅎ
- - + +
특히 취업관련 특강, 기술특강, 서류작성 포트폴리오 방향성 등
@@ -208,6 +208,6 @@ PR 을 올릴 때, 질문을 진짜 많이 적었고, 고민한 흔적 설계 쫌 힘들고 아프고 그래야 성장하는 타입인것같습니다.. 약간 ~~마조히스트~~ 기질이 있는것 같기도 하고요
- - + +
diff --git a/contents/posts/Etc/img/overcoming-difficult-times/image.jpeg b/contents/posts/Etc/overcoming-difficult-times/img/image.jpeg similarity index 100% rename from contents/posts/Etc/img/overcoming-difficult-times/image.jpeg rename to contents/posts/Etc/overcoming-difficult-times/img/image.jpeg diff --git a/contents/posts/Etc/img/overcoming-difficult-times/image.png b/contents/posts/Etc/overcoming-difficult-times/img/image.png similarity index 100% rename from contents/posts/Etc/img/overcoming-difficult-times/image.png rename to contents/posts/Etc/overcoming-difficult-times/img/image.png diff --git a/contents/posts/Etc/img/overcoming-difficult-times/image.webp b/contents/posts/Etc/overcoming-difficult-times/img/image.webp similarity index 100% rename from contents/posts/Etc/img/overcoming-difficult-times/image.webp rename to contents/posts/Etc/overcoming-difficult-times/img/image.webp diff --git a/contents/posts/Etc/overcoming-difficult-times.md b/contents/posts/Etc/overcoming-difficult-times/index.md similarity index 98% rename from contents/posts/Etc/overcoming-difficult-times.md rename to contents/posts/Etc/overcoming-difficult-times/index.md index cbb856e..6251ca7 100644 --- a/contents/posts/Etc/overcoming-difficult-times.md +++ b/contents/posts/Etc/overcoming-difficult-times/index.md @@ -62,7 +62,7 @@ head: 힘든것은 사실이지만, 그 이후에 어떤 태도를 선택할지는 결국 각자의 몫이다 -![도망쳐서 도착한 곳에 낙원이란 있을 수 없는 거야](./img/overcoming-difficult-times/image.png) +![도망쳐서 도착한 곳에 낙원이란 있을 수 없는 거야](./img/image.png)
diff --git a/contents/posts/Etc/roomfit-failure.md b/contents/posts/Etc/roomfit-failure/index.md similarity index 100% rename from contents/posts/Etc/roomfit-failure.md rename to contents/posts/Etc/roomfit-failure/index.md diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-1.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-1.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-1.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-1.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-1.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-1.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-1.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-1.png diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-1.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-1.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-1.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-1.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-10.gif b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-10.gif similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-10.gif rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-10.gif diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-11.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-11.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-11.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-11.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-11.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-11.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-11.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-11.png diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-11.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-11.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-11.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-11.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-2.gif b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-2.gif similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-2.gif rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-2.gif diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-3.gif b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-3.gif similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-3.gif rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-3.gif diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-4.gif b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-4.gif similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-4.gif rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-4.gif diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-5.gif b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-5.gif similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-5.gif rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-5.gif diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-6.gif b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-6.gif similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-6.gif rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-6.gif diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-7.gif b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-7.gif similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-7.gif rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-7.gif diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-8.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-8.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-8.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-8.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-8.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-8.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-8.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-8.png diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-8.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-8.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-8.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-8.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-9.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-9.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-9.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-9.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-9.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-9.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-9.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-9.png diff --git a/contents/posts/JavaScript/img/execution-context/js-ec-example-9.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-9.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-ec-example-9.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-ec-example-9.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-0.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-0.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-0.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-0.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-0.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-0.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-0.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-0.png diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-0.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-0.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-0.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-0.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-1.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-1.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-1.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-1.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-1.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-1.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-1.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-1.png diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-1.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-1.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-1.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-1.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-2.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-2.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-2.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-2.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-2.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-2.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-2.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-2.png diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-2.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-2.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-2.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-2.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-3.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-3.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-3.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-3.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-3.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-3.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-3.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-3.png diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-3.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-3.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-3.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-3.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-overview.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-overview.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-overview.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-overview.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-overview.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-overview.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-overview.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-overview.png diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-overview.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-overview.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-overview.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-overview.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-realm.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-realm.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-realm.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-realm.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-realm.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-realm.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-realm.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-realm.png diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-realm.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-realm.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-realm.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-realm.webp diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-summary.jpeg b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-summary.jpeg similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-summary.jpeg rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-summary.jpeg diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-summary.png b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-summary.png similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-summary.png rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-summary.png diff --git a/contents/posts/JavaScript/img/execution-context/js-execution-context-summary.webp b/contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-summary.webp similarity index 100% rename from contents/posts/JavaScript/img/execution-context/js-execution-context-summary.webp rename to contents/posts/JavaScript/js-execution-context-part1/img/js-execution-context-summary.webp diff --git a/contents/posts/JavaScript/js-execution-context-part1.md b/contents/posts/JavaScript/js-execution-context-part1/index.md similarity index 95% rename from contents/posts/JavaScript/js-execution-context-part1.md rename to contents/posts/JavaScript/js-execution-context-part1/index.md index 82bea8c..0e0e551 100644 --- a/contents/posts/JavaScript/js-execution-context-part1.md +++ b/contents/posts/JavaScript/js-execution-context-part1/index.md @@ -12,7 +12,7 @@ comment: true 스코프 (Scope), 클로저 (Closure), this 바인딩까지 모두 실행 컨텍스트와 연관되어 있습니다.
- +
실제 면접에서도 "자바스크립트의 실행 컨텍스트에 대해 설명해보세요"는 단골 질문입니다.
@@ -25,7 +25,7 @@ comment: true ## 🤔 실행 컨텍스트란 무엇인가?
- +
우리가 JavaScript 코드를 작성하고 실행될 때, `import` `export` 를 통해 모듈 코드를 실행할때, 함수 호출을 할 때,
@@ -35,7 +35,7 @@ comment: true ## 🏗️ 실행 컨텍스트의 구성 요소
- +
실행 컨텍스트는 크게 다음과 같은 요소로 구성되어 있습니다. @@ -56,7 +56,7 @@ Realm 은 JavaScript 코드가 실행되는 독립된 (Isolated) 환경을 의 Realm 은 다음과 같은 요소로 구성되어 있습니다.
- +
#### 1.1. Intrinsics (내장객체) @@ -101,7 +101,7 @@ Environment Record 는 **식별자 바인딩**을 저장하는 객체입니다. 또한, 공통적으로 **상위 Environment Record 에 대한 참조를 저장**하는 `[[Outer Env Reference]]` 슬롯을 가집니다.
- +
`Environment Record` 는 식별자를 어떻게 선언하느냐에 따라 `Lexical Environment` 와 `Variable Environment` 로 나뉩니다.
@@ -121,7 +121,7 @@ Variable Environment 는
### ⭐️ 실행컨텍스트의 구성요소 정리
- +
정리하자면, 실행컨텍스트는 diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.jpeg new file mode 100644 index 0000000..59eb9fc Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.png new file mode 100644 index 0000000..94c8495 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.webp new file mode 100644 index 0000000..561e5c1 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-1.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-10.gif b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-10.gif new file mode 100644 index 0000000..ba772e1 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-10.gif differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.jpeg new file mode 100644 index 0000000..fa4dc14 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.png new file mode 100644 index 0000000..5bbc7c1 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.webp new file mode 100644 index 0000000..6b6ae6e Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-11.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-2.gif b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-2.gif new file mode 100644 index 0000000..9b48f6a Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-2.gif differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-3.gif b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-3.gif new file mode 100644 index 0000000..c18294d Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-3.gif differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-4.gif b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-4.gif new file mode 100644 index 0000000..3bbf97d Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-4.gif differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-5.gif b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-5.gif new file mode 100644 index 0000000..6f8687e Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-5.gif differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-6.gif b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-6.gif new file mode 100644 index 0000000..53903be Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-6.gif differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-7.gif b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-7.gif new file mode 100644 index 0000000..70ba515 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-7.gif differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.jpeg new file mode 100644 index 0000000..812fc30 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.png new file mode 100644 index 0000000..0b734e6 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.webp new file mode 100644 index 0000000..b9ca020 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-8.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.jpeg new file mode 100644 index 0000000..28ea709 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.png new file mode 100644 index 0000000..e8deb85 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.webp new file mode 100644 index 0000000..3d65127 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-ec-example-9.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.jpeg new file mode 100644 index 0000000..131a415 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.png new file mode 100644 index 0000000..15caa5e Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.webp new file mode 100644 index 0000000..e10410e Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-0.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.jpeg new file mode 100644 index 0000000..3adc613 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.png new file mode 100644 index 0000000..4da2cdd Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.webp new file mode 100644 index 0000000..221c44e Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-1.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.jpeg new file mode 100644 index 0000000..e2aac70 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.png new file mode 100644 index 0000000..fee5484 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.webp new file mode 100644 index 0000000..0e3ac81 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-2.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.jpeg new file mode 100644 index 0000000..1ac8edd Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.png new file mode 100644 index 0000000..12552da Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.webp new file mode 100644 index 0000000..f15c4c7 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-3.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.jpeg new file mode 100644 index 0000000..ae8aa24 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.png new file mode 100644 index 0000000..fb319e6 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.webp new file mode 100644 index 0000000..d496317 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-overview.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.jpeg new file mode 100644 index 0000000..1d37059 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.png new file mode 100644 index 0000000..8bb47d2 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.webp new file mode 100644 index 0000000..7912d81 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-realm.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.jpeg b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.jpeg new file mode 100644 index 0000000..62d71b4 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.jpeg differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.png b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.png new file mode 100644 index 0000000..3c4799b Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.png differ diff --git a/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.webp b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.webp new file mode 100644 index 0000000..5028ee5 Binary files /dev/null and b/contents/posts/JavaScript/js-execution-context-part2/img/js-execution-context-summary.webp differ diff --git a/contents/posts/JavaScript/js-execution-context-part2.md b/contents/posts/JavaScript/js-execution-context-part2/index.md similarity index 92% rename from contents/posts/JavaScript/js-execution-context-part2.md rename to contents/posts/JavaScript/js-execution-context-part2/index.md index 51968ee..49d5e7b 100644 --- a/contents/posts/JavaScript/js-execution-context-part2.md +++ b/contents/posts/JavaScript/js-execution-context-part2/index.md @@ -8,12 +8,12 @@ comment: true ## 🤔 Recap -이전 글에서는 [JavaScript 실행 컨텍스트의 개념과 구성요소, Creation Phase와 Execution Phase](./js-execution-context-part1.md)에 대해 알아보았습니다.
+이전 글에서는 [JavaScript 실행 컨텍스트의 개념과 구성요소, Creation Phase와 Execution Phase](../js-execution-context-part1/)에 대해 알아보았습니다.
다시 한번 정리하자면,
- +
실행 컨텍스트는 @@ -67,7 +67,7 @@ console.log(sayHello()); // "안녕하세요! 대건 김" ### 1. Script Loaded
- +
가장 먼저 스크립트가 로드되면, **Realm** 이 생성됩니다.
@@ -85,7 +85,7 @@ console.log(sayHello()); // "안녕하세요! 대건 김" Realm 이 생성되면, **Global Execution Context** 가 생성(Creation Phase)됩니다.
- +
Global Execution Context 의 `Lexical Environment` 는 Realm 의 `Global Environment Record` 의 `[[Declarative Record]]` 슬롯을 참조합니다.
@@ -98,7 +98,7 @@ Global Execution Context 의 `Lexical Environment` 는 Realm 의 `Global Environ Creation Phase 에서는 식별자들을 스캔하여 메모리 공간을 예약합니다.
- +
> 1. `message` : `var` 키워드로 선언되었으므로, `Variable Environment Record` 에 등록되고 `undefined` 로 초기화됩니다.
@@ -111,14 +111,14 @@ Creation Phase 에서는 식별자들을 스캔하여 메모리 공간을 예약 ### 3. Global Execution Context - Execution Phase
- +
Creation Phase 가 끝나면, 실제 코드가 실행되는 **Execution Phase** 가 실행됩니다
생성된 Global Execution Context 는 콜스택에 쌓이고, 실행됩니다.
- +
> 1. `message` : "안녕하세요! " 문자열이 Heap 영역에 생성되고, `message` 변수는 해당 값을 가리킵니다.
@@ -136,7 +136,7 @@ Function Execution Context 또한 Creation Phase 와 Execution Phase 를 거칩 ### 4. greet Function Execution Context - Creation Phase
- +
`greet` 함수가 호출되기위해 **greet Function Execution Context** 의 Creation Phase 가 시작됩니다.
@@ -151,7 +151,7 @@ Function Execution Context 또한 Creation Phase 와 Execution Phase 를 거칩 `greet` 함수의 Execution Context Creation Phase 가 끝났으므로, 콜스택에 쌓이고, Execution Phase 가 시작됩니다.
- +
> 1. `person` : `new Person(firstName, lastName)` 를 통해 `Person` 클래스의 인스턴스가 생성되고, `person` 변수는 해당 인스턴스를 가리킵니다.
@@ -163,7 +163,7 @@ Function Execution Context 또한 Creation Phase 와 Execution Phase 를 거칩 ### 6. Global Execution Context - Execution Phase (계속)
- +
`greet` 함수의 Execution Phase 가 끝나고, `sayHello` 변수에 `createGreetingMessage` 함수 객체가 바인딩됩니다.
@@ -172,7 +172,7 @@ Function Execution Context 또한 Creation Phase 와 Execution Phase 를 거칩 ### 7. createGreetingMessage Function Execution Context - Creation Phase
- +
`createGreetingMessage` 함수가 호출되기위해 **createGreetingMessage Function Execution Context** 의 Creation Phase 가 시작됩니다.
@@ -185,7 +185,7 @@ Function Execution Context 또한 Creation Phase 와 Execution Phase 를 거칩 `createGreetingMessage` 함수의 Execution Context Creation Phase 가 끝났으므로, 콜스택에 쌓이고, Execution Phase 가 시작됩니다.
- +
> 1. `baseGreetMessage` : (‼️ 4-3 에서 생성된 Closure 를 통해) `greet` 함수의 `Lexical Environment` 에 접근하여, `baseGreetMessage` 는 "안녕하세요! " 가 됩니다
@@ -197,7 +197,7 @@ Function Execution Context 또한 Creation Phase 와 Execution Phase 를 거칩 ### 9. Global Execution Context - Execution Phase (계속)
- +
> 1. `console` : `console` 식별자를 찾기위해 Global Execution Context 의 `Lexical Environment` 를 참조하고, 이는 Global Object 를 참조합니다.
diff --git a/contents/posts/JavaScript/img/js-immutability/primitive.jpeg b/contents/posts/JavaScript/js-immutability/img/primitive.jpeg similarity index 100% rename from contents/posts/JavaScript/img/js-immutability/primitive.jpeg rename to contents/posts/JavaScript/js-immutability/img/primitive.jpeg diff --git a/contents/posts/JavaScript/img/js-immutability/primitive.png b/contents/posts/JavaScript/js-immutability/img/primitive.png similarity index 100% rename from contents/posts/JavaScript/img/js-immutability/primitive.png rename to contents/posts/JavaScript/js-immutability/img/primitive.png diff --git a/contents/posts/JavaScript/img/js-immutability/primitive.webp b/contents/posts/JavaScript/js-immutability/img/primitive.webp similarity index 100% rename from contents/posts/JavaScript/img/js-immutability/primitive.webp rename to contents/posts/JavaScript/js-immutability/img/primitive.webp diff --git a/contents/posts/JavaScript/img/js-immutability/reference.jpeg b/contents/posts/JavaScript/js-immutability/img/reference.jpeg similarity index 100% rename from contents/posts/JavaScript/img/js-immutability/reference.jpeg rename to contents/posts/JavaScript/js-immutability/img/reference.jpeg diff --git a/contents/posts/JavaScript/img/js-immutability/reference.png b/contents/posts/JavaScript/js-immutability/img/reference.png similarity index 100% rename from contents/posts/JavaScript/img/js-immutability/reference.png rename to contents/posts/JavaScript/js-immutability/img/reference.png diff --git a/contents/posts/JavaScript/img/js-immutability/reference.webp b/contents/posts/JavaScript/js-immutability/img/reference.webp similarity index 100% rename from contents/posts/JavaScript/img/js-immutability/reference.webp rename to contents/posts/JavaScript/js-immutability/img/reference.webp diff --git a/contents/posts/JavaScript/js-immutability.md b/contents/posts/JavaScript/js-immutability/index.md similarity index 98% rename from contents/posts/JavaScript/js-immutability.md rename to contents/posts/JavaScript/js-immutability/index.md index 582e0fe..a9d24e8 100644 --- a/contents/posts/JavaScript/js-immutability.md +++ b/contents/posts/JavaScript/js-immutability/index.md @@ -54,7 +54,7 @@ num = 20; // ✅ 새로운 숫자 재할당 console.log(num); // 20 ``` -![alt text](./img/js-immutability/primitive.png) +![alt text](./img/primitive.png) ```ts let str = "hello"; @@ -80,7 +80,7 @@ obj.a = 10; // ✅ 내부 프로퍼티 변경 console.log(obj); // { a: 10, b: 2 } ``` -![alt text](./img/js-immutability/reference.png) +![alt text](./img/reference.png) ```ts const user = { name: "Alice", age: 25 }; diff --git a/contents/posts/JavaScript/img/js-object-1.jpeg b/contents/posts/JavaScript/js-object-comparison/img/js-object-1.jpeg similarity index 100% rename from contents/posts/JavaScript/img/js-object-1.jpeg rename to contents/posts/JavaScript/js-object-comparison/img/js-object-1.jpeg diff --git a/contents/posts/JavaScript/img/js-object-1.png b/contents/posts/JavaScript/js-object-comparison/img/js-object-1.png similarity index 100% rename from contents/posts/JavaScript/img/js-object-1.png rename to contents/posts/JavaScript/js-object-comparison/img/js-object-1.png diff --git a/contents/posts/JavaScript/img/js-object-1.webp b/contents/posts/JavaScript/js-object-comparison/img/js-object-1.webp similarity index 100% rename from contents/posts/JavaScript/img/js-object-1.webp rename to contents/posts/JavaScript/js-object-comparison/img/js-object-1.webp diff --git a/contents/posts/JavaScript/js-object-comparison.md b/contents/posts/JavaScript/js-object-comparison/index.md similarity index 100% rename from contents/posts/JavaScript/js-object-comparison.md rename to contents/posts/JavaScript/js-object-comparison/index.md diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/chatgpt-event-stream.jpeg b/contents/posts/JavaScript/server-sent-event-generator/img/chatgpt-event-stream.jpeg similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/chatgpt-event-stream.jpeg rename to contents/posts/JavaScript/server-sent-event-generator/img/chatgpt-event-stream.jpeg diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/chatgpt-event-stream.png b/contents/posts/JavaScript/server-sent-event-generator/img/chatgpt-event-stream.png similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/chatgpt-event-stream.png rename to contents/posts/JavaScript/server-sent-event-generator/img/chatgpt-event-stream.png diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/chatgpt-event-stream.webp b/contents/posts/JavaScript/server-sent-event-generator/img/chatgpt-event-stream.webp similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/chatgpt-event-stream.webp rename to contents/posts/JavaScript/server-sent-event-generator/img/chatgpt-event-stream.webp diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/chatgpt.jpeg b/contents/posts/JavaScript/server-sent-event-generator/img/chatgpt.jpeg similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/chatgpt.jpeg rename to contents/posts/JavaScript/server-sent-event-generator/img/chatgpt.jpeg diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/chatgpt.png b/contents/posts/JavaScript/server-sent-event-generator/img/chatgpt.png similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/chatgpt.png rename to contents/posts/JavaScript/server-sent-event-generator/img/chatgpt.png diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/chatgpt.webp b/contents/posts/JavaScript/server-sent-event-generator/img/chatgpt.webp similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/chatgpt.webp rename to contents/posts/JavaScript/server-sent-event-generator/img/chatgpt.webp diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/sse.jpeg b/contents/posts/JavaScript/server-sent-event-generator/img/sse.jpeg similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/sse.jpeg rename to contents/posts/JavaScript/server-sent-event-generator/img/sse.jpeg diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/sse.png b/contents/posts/JavaScript/server-sent-event-generator/img/sse.png similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/sse.png rename to contents/posts/JavaScript/server-sent-event-generator/img/sse.png diff --git a/contents/posts/JavaScript/img/server-sent-event-generator/sse.webp b/contents/posts/JavaScript/server-sent-event-generator/img/sse.webp similarity index 100% rename from contents/posts/JavaScript/img/server-sent-event-generator/sse.webp rename to contents/posts/JavaScript/server-sent-event-generator/img/sse.webp diff --git a/contents/posts/JavaScript/server-sent-event-generator.md b/contents/posts/JavaScript/server-sent-event-generator/index.md similarity index 98% rename from contents/posts/JavaScript/server-sent-event-generator.md rename to contents/posts/JavaScript/server-sent-event-generator/index.md index 879a00f..0003487 100644 --- a/contents/posts/JavaScript/server-sent-event-generator.md +++ b/contents/posts/JavaScript/server-sent-event-generator/index.md @@ -13,8 +13,8 @@ head: GPT, Gemini, Claude 등 다양한 LLM 모델들이 등장하면서, 이 모델들과 상호작용하는 방법도 다양해지고 있습니다. 특히, 서버에서 클라이언트로 실시간으로 데이터를 푸시하는 `Server Sent Events (SSE)` 는 LLM 의 스트리밍 응답을 처리하는데 유용한 기술입니다.
- - + +
그렇다면 먼저 `Server Sent Events` 는 뭔지 알아보겠습니다 @@ -24,7 +24,7 @@ GPT, Gemini, Claude 등 다양한 LLM 모델들이 등장하면서, 이 모델 > Server Sent Events(SSE) 는 서버가 클라이언트(브라우저)에 단방향으로 지속적으로 데이터를 push 할 수 있게 해주는 기술
- +
SSE 는 HTTP 프로토콜을 기반으로 하고, 클라이언트가 서버에 연결을 열면 서버는 이벤트 스트림을 통해 데이터를 지속적으로 전송할 수 있습니다. 클라이언트는 `EventSource` API 나 `fetch` API 를 사용하여 SSE 스트림에 연결할 수 있습니다. diff --git a/contents/posts/JavaScript/img/v8-pointer-compression-1.jpeg b/contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-1.jpeg similarity index 100% rename from contents/posts/JavaScript/img/v8-pointer-compression-1.jpeg rename to contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-1.jpeg diff --git a/contents/posts/JavaScript/img/v8-pointer-compression-1.png b/contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-1.png similarity index 100% rename from contents/posts/JavaScript/img/v8-pointer-compression-1.png rename to contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-1.png diff --git a/contents/posts/JavaScript/img/v8-pointer-compression-1.webp b/contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-1.webp similarity index 100% rename from contents/posts/JavaScript/img/v8-pointer-compression-1.webp rename to contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-1.webp diff --git a/contents/posts/JavaScript/img/v8-pointer-compression-2.jpeg b/contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-2.jpeg similarity index 100% rename from contents/posts/JavaScript/img/v8-pointer-compression-2.jpeg rename to contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-2.jpeg diff --git a/contents/posts/JavaScript/img/v8-pointer-compression-2.png b/contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-2.png similarity index 100% rename from contents/posts/JavaScript/img/v8-pointer-compression-2.png rename to contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-2.png diff --git a/contents/posts/JavaScript/img/v8-pointer-compression-2.webp b/contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-2.webp similarity index 100% rename from contents/posts/JavaScript/img/v8-pointer-compression-2.webp rename to contents/posts/JavaScript/v8-how-the-value-stored/img/v8-pointer-compression-2.webp diff --git a/contents/posts/JavaScript/v8-how-the-value-stored.md b/contents/posts/JavaScript/v8-how-the-value-stored/index.md similarity index 100% rename from contents/posts/JavaScript/v8-how-the-value-stored.md rename to contents/posts/JavaScript/v8-how-the-value-stored/index.md diff --git a/contents/posts/Next/img/next-rendering-patterns/image-1.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-1.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-1.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-1.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-1.png b/contents/posts/Next/next-rendering-patterns/img/image-1.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-1.png rename to contents/posts/Next/next-rendering-patterns/img/image-1.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-1.webp b/contents/posts/Next/next-rendering-patterns/img/image-1.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-1.webp rename to contents/posts/Next/next-rendering-patterns/img/image-1.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-10.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-10.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-10.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-10.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-10.png b/contents/posts/Next/next-rendering-patterns/img/image-10.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-10.png rename to contents/posts/Next/next-rendering-patterns/img/image-10.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-10.webp b/contents/posts/Next/next-rendering-patterns/img/image-10.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-10.webp rename to contents/posts/Next/next-rendering-patterns/img/image-10.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-11.gif b/contents/posts/Next/next-rendering-patterns/img/image-11.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-11.gif rename to contents/posts/Next/next-rendering-patterns/img/image-11.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-12.gif b/contents/posts/Next/next-rendering-patterns/img/image-12.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-12.gif rename to contents/posts/Next/next-rendering-patterns/img/image-12.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-13.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-13.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-13.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-13.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-13.png b/contents/posts/Next/next-rendering-patterns/img/image-13.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-13.png rename to contents/posts/Next/next-rendering-patterns/img/image-13.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-13.webp b/contents/posts/Next/next-rendering-patterns/img/image-13.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-13.webp rename to contents/posts/Next/next-rendering-patterns/img/image-13.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-14.gif b/contents/posts/Next/next-rendering-patterns/img/image-14.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-14.gif rename to contents/posts/Next/next-rendering-patterns/img/image-14.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-15.gif b/contents/posts/Next/next-rendering-patterns/img/image-15.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-15.gif rename to contents/posts/Next/next-rendering-patterns/img/image-15.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-16.gif b/contents/posts/Next/next-rendering-patterns/img/image-16.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-16.gif rename to contents/posts/Next/next-rendering-patterns/img/image-16.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-17.gif b/contents/posts/Next/next-rendering-patterns/img/image-17.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-17.gif rename to contents/posts/Next/next-rendering-patterns/img/image-17.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-18.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-18.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-18.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-18.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-18.png b/contents/posts/Next/next-rendering-patterns/img/image-18.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-18.png rename to contents/posts/Next/next-rendering-patterns/img/image-18.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-18.webp b/contents/posts/Next/next-rendering-patterns/img/image-18.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-18.webp rename to contents/posts/Next/next-rendering-patterns/img/image-18.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-19.gif b/contents/posts/Next/next-rendering-patterns/img/image-19.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-19.gif rename to contents/posts/Next/next-rendering-patterns/img/image-19.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-2.gif b/contents/posts/Next/next-rendering-patterns/img/image-2.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-2.gif rename to contents/posts/Next/next-rendering-patterns/img/image-2.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-20.gif b/contents/posts/Next/next-rendering-patterns/img/image-20.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-20.gif rename to contents/posts/Next/next-rendering-patterns/img/image-20.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-21.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-21.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-21.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-21.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-21.png b/contents/posts/Next/next-rendering-patterns/img/image-21.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-21.png rename to contents/posts/Next/next-rendering-patterns/img/image-21.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-21.webp b/contents/posts/Next/next-rendering-patterns/img/image-21.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-21.webp rename to contents/posts/Next/next-rendering-patterns/img/image-21.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-22.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-22.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-22.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-22.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-22.png b/contents/posts/Next/next-rendering-patterns/img/image-22.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-22.png rename to contents/posts/Next/next-rendering-patterns/img/image-22.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-22.webp b/contents/posts/Next/next-rendering-patterns/img/image-22.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-22.webp rename to contents/posts/Next/next-rendering-patterns/img/image-22.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-3.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-3.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-3.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-3.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-3.png b/contents/posts/Next/next-rendering-patterns/img/image-3.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-3.png rename to contents/posts/Next/next-rendering-patterns/img/image-3.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-3.webp b/contents/posts/Next/next-rendering-patterns/img/image-3.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-3.webp rename to contents/posts/Next/next-rendering-patterns/img/image-3.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-4.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-4.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-4.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-4.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-4.png b/contents/posts/Next/next-rendering-patterns/img/image-4.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-4.png rename to contents/posts/Next/next-rendering-patterns/img/image-4.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-4.webp b/contents/posts/Next/next-rendering-patterns/img/image-4.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-4.webp rename to contents/posts/Next/next-rendering-patterns/img/image-4.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-5.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-5.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-5.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-5.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-5.png b/contents/posts/Next/next-rendering-patterns/img/image-5.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-5.png rename to contents/posts/Next/next-rendering-patterns/img/image-5.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-5.webp b/contents/posts/Next/next-rendering-patterns/img/image-5.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-5.webp rename to contents/posts/Next/next-rendering-patterns/img/image-5.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-6.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-6.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-6.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-6.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-6.png b/contents/posts/Next/next-rendering-patterns/img/image-6.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-6.png rename to contents/posts/Next/next-rendering-patterns/img/image-6.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-6.webp b/contents/posts/Next/next-rendering-patterns/img/image-6.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-6.webp rename to contents/posts/Next/next-rendering-patterns/img/image-6.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-7.gif b/contents/posts/Next/next-rendering-patterns/img/image-7.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-7.gif rename to contents/posts/Next/next-rendering-patterns/img/image-7.gif diff --git a/contents/posts/Next/img/next-rendering-patterns/image-8.jpeg b/contents/posts/Next/next-rendering-patterns/img/image-8.jpeg similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-8.jpeg rename to contents/posts/Next/next-rendering-patterns/img/image-8.jpeg diff --git a/contents/posts/Next/img/next-rendering-patterns/image-8.png b/contents/posts/Next/next-rendering-patterns/img/image-8.png similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-8.png rename to contents/posts/Next/next-rendering-patterns/img/image-8.png diff --git a/contents/posts/Next/img/next-rendering-patterns/image-8.webp b/contents/posts/Next/next-rendering-patterns/img/image-8.webp similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-8.webp rename to contents/posts/Next/next-rendering-patterns/img/image-8.webp diff --git a/contents/posts/Next/img/next-rendering-patterns/image-9.gif b/contents/posts/Next/next-rendering-patterns/img/image-9.gif similarity index 100% rename from contents/posts/Next/img/next-rendering-patterns/image-9.gif rename to contents/posts/Next/next-rendering-patterns/img/image-9.gif diff --git a/contents/posts/Next/next-rendering-patterns.md b/contents/posts/Next/next-rendering-patterns/index.md similarity index 90% rename from contents/posts/Next/next-rendering-patterns.md rename to contents/posts/Next/next-rendering-patterns/index.md index 9fa9e6a..2d222e6 100644 --- a/contents/posts/Next/next-rendering-patterns.md +++ b/contents/posts/Next/next-rendering-patterns/index.md @@ -10,7 +10,7 @@ comment: true ## ✍️ NextJS 란 ? -![](./img/next-rendering-patterns/image-1.png) +![](./img/image-1.png) NextJS 는 무엇일까요? NextJS 공식 웹사이트에 들어가면 @@ -31,7 +31,7 @@ NextJS 는 리액트 기반의 웹 프레임워크이기 때문에 다음과 같 그렇다면 NextJS 의 렌더링 패턴을 자세히 알아보기에 앞서, 렌더링(Rendering) 이 무엇인지 알아보겠습니다 -![](./img/next-rendering-patterns/image-2.gif) +![](./img/image-2.gif) 우리가 브라우저에서 유튜브에 접속하는 상황을 가정해보도록 하겠습니다 @@ -47,7 +47,7 @@ WAS (Web Application Server) 가 데이터베이스와 정보를 주고받으며 ### Construction 단계 -![](./img/next-rendering-patterns/image-3.png) +![](./img/image-3.png) 먼저 브라우저는 @@ -62,7 +62,7 @@ WAS (Web Application Server) 가 데이터베이스와 정보를 주고받으며 ### Operation 단계 -![](./img/next-rendering-patterns/image-4.png) +![](./img/image-4.png) 다음으로 Render Tree 의 노드를 표시할 위치를 결정하는 Layout 단계와, Render Tree 를 순회하며 Node 를 그리는 Paint 단계를 거쳐, @@ -76,9 +76,9 @@ z-index 가 낮은 요소부터 차례로 레이어를 구성하는 composition 본격적으로 렌더링 패턴들에 대해 알아보기에 앞서서, 구글에서 제안하는 웹 페이지들의 사용자 경험을 평가하는 지표인 Core Web Vitals 에 대해 잠깐 알아보겠습니다 -![](./img/next-rendering-patterns/image-5.png) +![](./img/image-5.png)
-![](./img/next-rendering-patterns/image-6.png) +![](./img/image-6.png) ## ✍️ Rendering Patterns @@ -90,12 +90,12 @@ z-index 가 낮은 요소부터 차례로 레이어를 구성하는 composition 초기에 웹은 정적인 컨텐츠를 보여주는것에 그쳤습니다. -![](./img/next-rendering-patterns/image-7.gif) +![](./img/image-7.gif) 클라이언트가 특정 페이지에 접속하면, 정적인 HTML, CSS, JS 를 제공합니다. AWS S3 버킷과 같은 저장소에 올리거나, NginX 등을 사용해 정적인 페이지는 서빙됩니다 -![](./img/next-rendering-patterns/image-8.png) +![](./img/image-8.png) Static Site 를 Core Web Vitals 관점에서 보면, @@ -106,7 +106,7 @@ Static Site 를 Core Web Vitals 관점에서 보면, ### Server Side Rendering (SSR) -![](./img/next-rendering-patterns/image-9.gif) +![](./img/image-9.gif) 다음으로는 서버사이드 렌더링입니다. @@ -115,7 +115,7 @@ Static Site 를 Core Web Vitals 관점에서 보면, 요청에 따라 서버에서 데이터를 삽입한 완성된 HTML 을 클라이언트에게 제공합니다. JSP, TimeLeaf, HandleBars 등과 같은 템플릿 엔진을 사용해 구현할 수 있습니다. -![](./img/next-rendering-patterns/image-10.png) +![](./img/image-10.png) Static Site 와 동일하게 TTI 와 FCP 가 동일하다는 점과 SEO 에 좋다는 장점이 있습니다. @@ -129,8 +129,8 @@ AJAX 라는 기술이 나오게 되면서 새로고침 없이 동적으로 데 이에 따라 React, Angular, Vue 와 같은 라이브러리가 발전하여 앱과같은 부드러운 화면 전환이 가능해졌습니다 -![](./img/next-rendering-patterns/image-11.gif) -![](./img/next-rendering-patterns/image-12.gif) +![](./img/image-11.gif) +![](./img/image-12.gif) 페이지를 요청하면, HTML 과 CSS 를 받고, 빌드된 JS 번들 파일을 응답으로 받습니다 @@ -138,7 +138,7 @@ AJAX 라는 기술이 나오게 되면서 새로고침 없이 동적으로 데 이후, 클라이언트 측에서 JS (React) 를 사용해 DOM 요소를 삽입하고 조작하며 렌더링을 진행하고, AJAX 요청을보내서 서버로부터 동적인 데이터를 받아옵니다 -![](./img/next-rendering-patterns/image-13.png) +![](./img/image-13.png) 앱처럼 부드러운 전환과 상호작용으로 UX 에 좋지만, 검색엔진 크롤링 봇이 텅 빈 HTML 을 크롤링하기 때문에 검색엔진 최적화 SEO 에 좋지 못합니다 @@ -151,7 +151,7 @@ FCP 와 TTI 의 차이가 크기 때문에, 사용자가 페이지가 로드되 먼저 SSR with Hydration 입니다. -![](./img/next-rendering-patterns/image-14.gif) +![](./img/image-14.gif) 이름에서 알 수 있듯이, 앞서 봤던 SSR 과 유사하게 동작합니다 @@ -160,7 +160,7 @@ API 요청을 보내 데이터를 삽입 후, 완성된 HTML 을 응답으로 여기까지는 SSR 과 동일합니다 -![](./img/next-rendering-patterns/image-15.gif) +![](./img/image-15.gif) 이후, 추가적으로 React 코드가 클라이언트로 함께 전송되어 `Hydration` 이 진행됩니다 @@ -175,14 +175,14 @@ SSR with Hydration 과 유사하나, 요청마다 서버에서 렌더링을 진행하는 것이 아닌, 빌드시간에 변하지 않는 부분은 HTML 로 생성해두고 -![](./img/next-rendering-patterns/image-16.gif) +![](./img/image-16.gif) 이후, React 코드가 연결되는 Hydration 이 진행되고, API 요청은 AJAX 를 통해 진행됩니다 -![](./img/next-rendering-patterns/image-17.gif) +![](./img/image-17.gif) -![](./img/next-rendering-patterns/image-18.png) +![](./img/image-18.png) 두 렌더링 패턴 모두 검색엔진 최적화에 좋지만, TTFB 가 느리다는 단점이 있습니다 @@ -193,23 +193,23 @@ TTFB 가 느리다는 단점이 있습니다 SSR with Hydration 과 SSG with Hydration 을 합친 렌더링 패턴이라고 볼 수 있습니다 -![](./img/next-rendering-patterns/image-19.gif) +![](./img/image-19.gif) 빌드타임에 리액트를 사용해 사전렌더링된 HTML 을 캐싱하고 (SSG with Hydration 과 유사) 응답으로 제공합니다 -![](./img/next-rendering-patterns/image-20.gif) +![](./img/image-20.gif) 이후, 요청이 발생하고 캐시가 유효하지 않을때 (만료 되었을때, revalidate 시간 지정) 서버에서 개별 페이지를 재생성하여 캐싱합니다 -![](./img/next-rendering-patterns/image-21.png) +![](./img/image-21.png) 캐싱된 페이지에 대해서는 TTFB 가 빠르다는 장점이 있지만, 데이터가 자주 바뀌는 사이트에서는 적합하지 않습니다. ## ✍️ 마치며 -![alt text](./img/next-rendering-patterns/image-22.png) +![alt text](./img/image-22.png) 그래서 좋은 렌더링 패턴은 뭐고, 뭘 써야한다 라고 묻는다면, 딱히 정해진 좋은 패턴은 없습니다. diff --git a/contents/posts/ProblemSolving/img/baekjoon-tip-for-nodejs/image.jpeg b/contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/img/image.jpeg similarity index 100% rename from contents/posts/ProblemSolving/img/baekjoon-tip-for-nodejs/image.jpeg rename to contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/img/image.jpeg diff --git a/contents/posts/ProblemSolving/img/baekjoon-tip-for-nodejs/image.png b/contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/img/image.png similarity index 100% rename from contents/posts/ProblemSolving/img/baekjoon-tip-for-nodejs/image.png rename to contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/img/image.png diff --git a/contents/posts/ProblemSolving/img/baekjoon-tip-for-nodejs/image.webp b/contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/img/image.webp similarity index 100% rename from contents/posts/ProblemSolving/img/baekjoon-tip-for-nodejs/image.webp rename to contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/img/image.webp diff --git a/contents/posts/ProblemSolving/baekjoon-tip-for-nodejs.md b/contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/index.md similarity index 99% rename from contents/posts/ProblemSolving/baekjoon-tip-for-nodejs.md rename to contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/index.md index eb3e52c..9cccb6e 100644 --- a/contents/posts/ProblemSolving/baekjoon-tip-for-nodejs.md +++ b/contents/posts/ProblemSolving/baekjoon-tip-for-nodejs/index.md @@ -33,7 +33,7 @@ let input = fs [Competitive Programming Helper](https://marketplace.visualstudio.com/items?itemName=DivyanshuAgrawal.competitive-programming-helper) Extension 을 사용하면 따로 `process.platform` 을 확인하지 않고도 여러 테스트케이스에 대해 출력값을 쉽게 확인할 수 있습니다. -![alt text](./img/baekjoon-tip-for-nodejs/image.png) +![alt text](./img/image.png) ::: diff --git a/contents/posts/React/img/build-react-1/dumb.jpeg b/contents/posts/React/build-react-1/img/dumb.jpeg similarity index 100% rename from contents/posts/React/img/build-react-1/dumb.jpeg rename to contents/posts/React/build-react-1/img/dumb.jpeg diff --git a/contents/posts/React/img/build-react-1/dumb.png b/contents/posts/React/build-react-1/img/dumb.png similarity index 100% rename from contents/posts/React/img/build-react-1/dumb.png rename to contents/posts/React/build-react-1/img/dumb.png diff --git a/contents/posts/React/img/build-react-1/dumb.webp b/contents/posts/React/build-react-1/img/dumb.webp similarity index 100% rename from contents/posts/React/img/build-react-1/dumb.webp rename to contents/posts/React/build-react-1/img/dumb.webp diff --git a/contents/posts/React/build-react-1.md b/contents/posts/React/build-react-1/index.md similarity index 98% rename from contents/posts/React/build-react-1.md rename to contents/posts/React/build-react-1/index.md index 17fef5e..adaf010 100644 --- a/contents/posts/React/build-react-1.md +++ b/contents/posts/React/build-react-1/index.md @@ -39,7 +39,7 @@ HTML 처럼 보이지만 실제로는 JavaScript 를 확장한 문법입니다. 그래서 브라우저는 JSX 를 이해하지 못해요 ㅠㅠ
-dumb +dumb
### 🚀 JSX 는 어떻게 동작하는데 ? diff --git a/contents/posts/React/constellation-impl/img/coordinate.jpeg b/contents/posts/React/constellation-impl/img/coordinate.jpeg new file mode 100644 index 0000000..f341ff9 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/coordinate.jpeg differ diff --git a/contents/posts/React/constellation-impl/img/coordinate.png b/contents/posts/React/constellation-impl/img/coordinate.png new file mode 100644 index 0000000..2aaa2d5 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/coordinate.png differ diff --git a/contents/posts/React/constellation-impl/img/coordinate.webp b/contents/posts/React/constellation-impl/img/coordinate.webp new file mode 100644 index 0000000..2195605 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/coordinate.webp differ diff --git a/contents/posts/React/constellation-impl/img/design-after.jpeg b/contents/posts/React/constellation-impl/img/design-after.jpeg new file mode 100644 index 0000000..ec683c2 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/design-after.jpeg differ diff --git a/contents/posts/React/constellation-impl/img/design-after.png b/contents/posts/React/constellation-impl/img/design-after.png new file mode 100644 index 0000000..cd75c08 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/design-after.png differ diff --git a/contents/posts/React/constellation-impl/img/design-after.webp b/contents/posts/React/constellation-impl/img/design-after.webp new file mode 100644 index 0000000..82ae193 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/design-after.webp differ diff --git a/contents/posts/React/constellation-impl/img/design-before.jpeg b/contents/posts/React/constellation-impl/img/design-before.jpeg new file mode 100644 index 0000000..15bbc32 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/design-before.jpeg differ diff --git a/contents/posts/React/constellation-impl/img/design-before.png b/contents/posts/React/constellation-impl/img/design-before.png new file mode 100644 index 0000000..40e9950 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/design-before.png differ diff --git a/contents/posts/React/constellation-impl/img/design-before.webp b/contents/posts/React/constellation-impl/img/design-before.webp new file mode 100644 index 0000000..478da78 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/design-before.webp differ diff --git a/contents/posts/React/constellation-impl/img/devtools.gif b/contents/posts/React/constellation-impl/img/devtools.gif new file mode 100644 index 0000000..7ad17fb Binary files /dev/null and b/contents/posts/React/constellation-impl/img/devtools.gif differ diff --git a/contents/posts/React/constellation-impl/img/image-1.jpeg b/contents/posts/React/constellation-impl/img/image-1.jpeg new file mode 100644 index 0000000..7280aed Binary files /dev/null and b/contents/posts/React/constellation-impl/img/image-1.jpeg differ diff --git a/contents/posts/React/constellation-impl/img/image-1.png b/contents/posts/React/constellation-impl/img/image-1.png new file mode 100644 index 0000000..d81b850 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/image-1.png differ diff --git a/contents/posts/React/constellation-impl/img/image-1.webp b/contents/posts/React/constellation-impl/img/image-1.webp new file mode 100644 index 0000000..473a0c5 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/image-1.webp differ diff --git a/contents/posts/React/constellation-impl/img/image.jpeg b/contents/posts/React/constellation-impl/img/image.jpeg new file mode 100644 index 0000000..9dad4fb Binary files /dev/null and b/contents/posts/React/constellation-impl/img/image.jpeg differ diff --git a/contents/posts/React/constellation-impl/img/image.png b/contents/posts/React/constellation-impl/img/image.png new file mode 100644 index 0000000..bc52481 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/image.png differ diff --git a/contents/posts/React/constellation-impl/img/image.webp b/contents/posts/React/constellation-impl/img/image.webp new file mode 100644 index 0000000..302446b Binary files /dev/null and b/contents/posts/React/constellation-impl/img/image.webp differ diff --git a/contents/posts/React/constellation-impl/img/layer-perspective.jpeg b/contents/posts/React/constellation-impl/img/layer-perspective.jpeg new file mode 100644 index 0000000..b4678ab Binary files /dev/null and b/contents/posts/React/constellation-impl/img/layer-perspective.jpeg differ diff --git a/contents/posts/React/constellation-impl/img/layer-perspective.png b/contents/posts/React/constellation-impl/img/layer-perspective.png new file mode 100644 index 0000000..1760038 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/layer-perspective.png differ diff --git a/contents/posts/React/constellation-impl/img/layer-perspective.webp b/contents/posts/React/constellation-impl/img/layer-perspective.webp new file mode 100644 index 0000000..4fc9791 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/layer-perspective.webp differ diff --git a/contents/posts/React/constellation-impl/img/math.jpeg b/contents/posts/React/constellation-impl/img/math.jpeg new file mode 100644 index 0000000..44be5b7 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/math.jpeg differ diff --git a/contents/posts/React/constellation-impl/img/math.png b/contents/posts/React/constellation-impl/img/math.png new file mode 100644 index 0000000..b267122 Binary files /dev/null and b/contents/posts/React/constellation-impl/img/math.png differ diff --git a/contents/posts/React/constellation-impl/img/math.webp b/contents/posts/React/constellation-impl/img/math.webp new file mode 100644 index 0000000..cdbf94a Binary files /dev/null and b/contents/posts/React/constellation-impl/img/math.webp differ diff --git a/contents/posts/React/constellation-impl/index.md b/contents/posts/React/constellation-impl/index.md new file mode 100644 index 0000000..9ede517 --- /dev/null +++ b/contents/posts/React/constellation-impl/index.md @@ -0,0 +1,218 @@ +--- +title: "정적 좌표 지옥에서 탈출한 동적 별자리 노드 시스템 구축기" +createdAt: "2026-03-02" +category: React +description: '누비랩 냠냠플러스 "오늘찰칵" 서비스의 별자리 맵 시스템을 하드코딩된 좌표 대신 기하학 알고리즘과 Render Props 패턴으로 해결하며 유지보수성과 확장성을 확보한 경험을 공유합니다.' +comment: true +head: + - - meta + - name: keywords + content: "React, Renderer Props, 삼각함수, 별자리 지도" +--- + +최근 인턴으로 재직중인 누비랩의 냠냠플러스 `오늘찰칵` 서비스 고도화 작업을 하면서, 단순 갤러리 형태의 화면을 조금 더 재미있고 감정적으로 연결되는 경험으로 바꾸는 작업을 맡게 되었습니다. + +기존 POC는 "사진을 나열해서 보여주는 화면"에 가까웠습니다. 기능은 있었지만, 아이의 기록을 탐험하듯 따라가게 만드는 몰입감이나, 부모 입장에서 하나씩 발견하는 재미는 부족했습니다. + +
+ 기존 POC UI + 개선된 UI +
+ +그래서 도입된 컨셉이 바로 **별자리 지도 UI**이었습니다. + +문제는 여기서부터였습니다. 겉으로 보기엔 별처럼 점이 이어진 예쁜 경로지만, 실제 구현 단계에 들어가면 이건 단순한 데코레이션이 아니라 다음 조건을 모두 만족해야 하는 시스템이었습니다. + +> - 별자리 노드 개수가 바뀌어도 대응 가능해야 함 +> - 경로 모양이 바뀌어도 유지보수가 가능해야 함 +> - 모바일 WebView에서도 버벅이지 않아야 함 +> - 디자인 QA에서 미세 조정을 요청해도 빠르게 반영 가능해야 함 + +처음엔 그냥 하드코딩으로 정적인 좌표를 박아 넣으면 되는 문제처럼 보였지만, 추후 확장성을 고려했을때는 해당 방법이 적절하지 않다고 생각했습니다. + +이번 글에서는 그 과정에서 왜 단순 하드코딩을 버리고, **삼각함수 기반의 좌표 계산 + Render Props 패턴**으로 문제를 풀었는지 정리해보겠습니다. + +## 예쁜 시안, 끔찍한 유지보수 + +디자인 시안을 기준으로 보면 별자리 노드는 세로 방향으로 길게 이어지고, 중간중간 좌우로 꺾이며, 특정 간격마다 큰 마커(별)가 들어가고 그 외에는 작은 점선처럼 이어지는 구조였습니다. + +
+ +
+ +이걸 가장 단순히 구현하는 첫 번째 접근방법은 해당 경로가 포함된 이미지를 배경으로 깔고, 상호작용이 필요한 각 별의 x, y 좌표를 추출하여 하드코딩하는 방식입니다. + +```tsx +const nodes = [ + { x: -102, y: 0 }, + { x: -102, y: 20 }, + { x: -102, y: 40 }, + { x: -86, y: 60 }, + ... +]; + + + {nodes.map((node, index) => ( + + ))} + +``` + +가장 단순한 구현방법이지만, 다음과 같은 문제점들이 예상되었습니다 + +### 1️⃣ 노드 개수나 경로가 바뀌는 순간, 전체 좌표를 다시 설정해야한다 + +오늘은 20개 노드지만 기록이 추가되며 추후 40개가 될 수 있고, 경로의 각도나 밀도를 바꿔야 할 수도 있습니다.
+하드코딩 방식은 일부만 수정해도 전체 균형이 깨질 수 있고, 하나하나의 좌표를 찾아서 수정하는 것은 비효율적입니다.
+Figma MCP 를 사용하더라도 여전히 안맞는 픽셀이 있는경우 하나하나 검토하는건 개발자의 몫이었습니다 + +### 2️⃣ 디자인 QA 대응의 비효율성 + +"여기 조금만 더 오른쪽으로", "이 구간은 간격이 너무 촘촘함"과 같은 픽셀 단위의 요청이 들어올 때마다 수동으로 좌표를 찾고 수정하는 과정은 비효율적입니다. + +### 3️⃣ SVG Path의 실용성 한계 + +SVG Path는 곡선 표현력은 좋지만, 모바일 WebView 환경에서 경로가 길고 노드가 많아질 경우 래스터화 비용과 렌더링 안정성 측면에서 부담이 될 가능성이 있었습니다.
+무엇보다 특정 노드를 개별 UI 컴포넌트로 제어하기에는 유연성이 떨어졌습니다. + +## 선택지 검토 + +구현 방향은 크게 세 가지로 압축되었습니다. + +| 구분 | 장점 | 단점 | +| :----------------------------- | :----------------------------------- | :----------------------------------------- | +| **A. 수동 하드코딩** | 시안과 100% 동일하게 구현 가능 | 유지보수 비용 급증, QA 대응 취약 | +| **B. SVG Path 기반** | 정교한 곡선 표현 | WebView 성능 우려
개별 노드 제어 어려움 | +| **C. 삼각함수 기반 좌표 계산** | 파라미터 기반 자동 생성, 운영 최적화 | 초기 로직 설계 필요 | + +최종적으로 디자인 100% 복제보다 운영 가능한 시스템이 더 중요하다고 판단하여 C안을 선택했습니다. + +## 좌표를 저장하지 말고, 규칙으로 만들자 + +> "노드 하나하나의 좌표를 직접 갖고 있지 말고, 시작점 + 간격 + 각도 + 방향 패턴만으로 좌표를 생성하자." + +
+ +
+ +이 구조가 되면 경로는 더 이상 픽셀 덩어리가 아니라, **파라미터 기반 생성 결과물**이 됩니다. + +- `nodeGap`: 노드 사이의 거리 (빗변) +- `angle`: 경로가 꺾이는 기준 각도 +- `offsetArray`: 좌/우/직진 여부를 결정하는 패턴 배열 +- `offsetStartX`: 시작점 가로 위치 + +## 구현 1: 삼각함수로 노드 간 수평/수직 이동 거리 계산 + +
+ +
+ +처음에는 단순히 세로 간격을 고정하고 가로 이동량만 계산했으나, 대각선 경로에서도 일정한 시각적 밀도를 유지하기 위해 **빗변(`nodeGap`)을 기준**으로 잡았습니다. + +내려갈 때 좌우로 얼마나 이동할지(`dx`)와 아래로 얼마나 내려갈지(`dy`)를 각도와 빗변 기반으로 계산했습니다. + +```ts +const deg = angle * (Math.PI / 180); +const dx = nodeGap * Math.cos(deg); +const dy = nodeGap * Math.sin(deg); +``` + +이렇게 구한 `dx`, `dy`를 패턴 배열에 적용하여 각 노드의 위치를 자동 생성하도록 했습니다. + +```ts +export function createStarNodes({ + totalNodes, + nodeGap, + angle, + offsetArray, + offsetStartX, +}: CreatStarNodesArgs) { + const nodes = new Array(); + const deg = angle * (Math.PI / 180); + const dx = nodeGap * Math.cos(deg); + const dy = nodeGap * Math.sin(deg); + + let x = offsetStartX; + let y = 0; + + for (let n = 0; n < totalNodes; n++) { + nodes.push({ x, y }); + + const dir = offsetArray[n % offsetArray.length]; + + if (dir === 0) { + // 직진할 때는 nodeGap만큼 수직으로만 이동 + y += nodeGap; + } else { + // 꺾일 때는 계산된 dx, dy만큼 이동 + x += dir * dx; + y += dy; + } + } + + return nodes; +} +``` + +`offsetArray`의 값이 `0`이면 직진, `1`이면 우측, `-1`이면 좌측으로 흐름을 정의하되, 꺾이는 구간에서도 노드 사이의 거리(`nodeGap`)가 일정하게 유지되도록 설계했습니다. + +## 구현 2: Render Props로 "좌표 생성"과 "UI"를 분리 + +좌표 로직과 UI를 섞지 않기 위해 `StarMapLayer`는 좌표 계산과 배치만 책임지고, 각 노드에 무엇을 낼지는 외부에서 주입받는 **Render Props** 패턴을 적용했습니다. + +```tsx +// 0 : 직진, 1 : 우측, -1 : 좌측 +const offsetArray = [ + Array(9).fill(0), + Array(12).fill(1), + Array(27).fill(0), + Array(10).fill(-1), + Array(9).fill(0), + Array(8).fill(1), + Array(11).fill(0), + Array(12).fill(-1), +].flat(); + + { + // 5번째 노드만 별자리 마커로 표시 + if (index % 5 === 0) return ; + return ; + }} +/>; +``` + +덕분에 특정 인덱스만 잠금 상태로 표시하거나, 보상 강조 UI를 입히는 등의 확장이 자유로워졌습니다. + +## 구현 3: 픽셀 맞추기 지옥에서 벗어나기 위한 "개발자 도구" + +수학적으로 위치를 계산하게 만들었지만, 여전히 고민은 남았습니다.
+`angle`, `gap`, `offsetArray` 같은 값들을 바꿀 때마다 코드를 수정하고 HMR을 기다리며 픽셀을 맞추는 건 여전히 비효율적이었습니다 + +> "그냥 화면에서 직접 슬라이더로 조절하면서 최적의 값을 찾고, 그 코드만 복사해서 붙여넣으면 안 될까?" + +이런 고민 끝에 별자리 에디터(StarMap DevTools)를 추가했습니다.
+슬라이더를 통해 실시간으로 경로를 비틀어보며 최적의 디자인을 찾고, `코드 복사하기` 버튼으로 즉시 현재 설정값을 복사할 수 있는 도구입니다. + +
+ +
+ +이 개발자 도구 덕분에 며칠이 걸릴 수도 있었던 디자인 미세 조정 작업을 단 몇분만에 끝낼 수 있었습니다. + +## 느낀 점 + +### 이거 좌표 하나하나를 나보고 찍으라고? + +처음 시안을 받았을 때 가장 먼저 든 생각은 '노드 좌표를 언제 다 따고 있지?'였습니다. 하지만 단순히 귀찮음의 문제가 아니었습니다.
운영 환경에서 노드가 추가되거나 경로를 살짝만 비틀어달라는 요청이 오면, 그때마다 피그마에서 좌표를 다시 추출하고 코드를 수정하는 '노가다'가 반복될 게 뻔햇기 때문입니다.
+ +### 디자인 재현도와 제어 가능성의 균형 + +개발자로서 시안을 100% 똑같이 재현하고 싶은 욕심은 늘 있습니다. 하지만 실제 서비스 관점에서는 경로를 수식으로 완벽하게 그리는 것보다, **개발자가 숫자로 제어할 수 있고 운영팀의 요구에 즉각 대응할 수 있는 구조**를 만드는 게 훨씬 가치 있다는 걸 배웠습니다.
+`angle`, `gap` 같은 변수 몇 개로 전체 흐름을 바꿀 수 있게 되었습니다 diff --git a/contents/posts/React/img/context-provider-hell/prop-drilling.jpeg b/contents/posts/React/context-provider-hell/img/prop-drilling.jpeg similarity index 100% rename from contents/posts/React/img/context-provider-hell/prop-drilling.jpeg rename to contents/posts/React/context-provider-hell/img/prop-drilling.jpeg diff --git a/contents/posts/React/img/context-provider-hell/prop-drilling.png b/contents/posts/React/context-provider-hell/img/prop-drilling.png similarity index 100% rename from contents/posts/React/img/context-provider-hell/prop-drilling.png rename to contents/posts/React/context-provider-hell/img/prop-drilling.png diff --git a/contents/posts/React/img/context-provider-hell/prop-drilling.webp b/contents/posts/React/context-provider-hell/img/prop-drilling.webp similarity index 100% rename from contents/posts/React/img/context-provider-hell/prop-drilling.webp rename to contents/posts/React/context-provider-hell/img/prop-drilling.webp diff --git a/contents/posts/React/context-provider-hell.md b/contents/posts/React/context-provider-hell/index.md similarity index 97% rename from contents/posts/React/context-provider-hell.md rename to contents/posts/React/context-provider-hell/index.md index bf572e9..086fa54 100644 --- a/contents/posts/React/context-provider-hell.md +++ b/contents/posts/React/context-provider-hell/index.md @@ -6,7 +6,7 @@ description: React Context API를 사용할 때 발생할 수 있는 'Context Pr comment: true --- -![Prop Drilling](./img/context-provider-hell/prop-drilling.png) +![Prop Drilling](./img/prop-drilling.png) React 를 사용하다 보면 전역적인 상태나 설정을 공유하기 위해 자연스럽게 Context를 사용하게 됩니다. 테마, 인증정보, 폼 상태 ... 처음엔 편합니다. `` 로 감싸주면, 어디서든 데이터를 쉽게 꺼내쓸 수 있으니까요. diff --git a/contents/posts/React/img/create-entity-adapter/global-state.jpeg b/contents/posts/React/create-entity-adapter/img/global-state.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/global-state.jpeg rename to contents/posts/React/create-entity-adapter/img/global-state.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/global-state.png b/contents/posts/React/create-entity-adapter/img/global-state.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/global-state.png rename to contents/posts/React/create-entity-adapter/img/global-state.png diff --git a/contents/posts/React/img/create-entity-adapter/global-state.webp b/contents/posts/React/create-entity-adapter/img/global-state.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/global-state.webp rename to contents/posts/React/create-entity-adapter/img/global-state.webp diff --git a/contents/posts/React/img/create-entity-adapter/image-1.jpeg b/contents/posts/React/create-entity-adapter/img/image-1.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-1.jpeg rename to contents/posts/React/create-entity-adapter/img/image-1.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/image-1.png b/contents/posts/React/create-entity-adapter/img/image-1.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-1.png rename to contents/posts/React/create-entity-adapter/img/image-1.png diff --git a/contents/posts/React/img/create-entity-adapter/image-1.webp b/contents/posts/React/create-entity-adapter/img/image-1.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-1.webp rename to contents/posts/React/create-entity-adapter/img/image-1.webp diff --git a/contents/posts/React/img/create-entity-adapter/image-2.jpeg b/contents/posts/React/create-entity-adapter/img/image-2.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-2.jpeg rename to contents/posts/React/create-entity-adapter/img/image-2.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/image-2.png b/contents/posts/React/create-entity-adapter/img/image-2.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-2.png rename to contents/posts/React/create-entity-adapter/img/image-2.png diff --git a/contents/posts/React/img/create-entity-adapter/image-2.webp b/contents/posts/React/create-entity-adapter/img/image-2.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-2.webp rename to contents/posts/React/create-entity-adapter/img/image-2.webp diff --git a/contents/posts/React/img/create-entity-adapter/image-3.jpeg b/contents/posts/React/create-entity-adapter/img/image-3.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-3.jpeg rename to contents/posts/React/create-entity-adapter/img/image-3.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/image-3.png b/contents/posts/React/create-entity-adapter/img/image-3.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-3.png rename to contents/posts/React/create-entity-adapter/img/image-3.png diff --git a/contents/posts/React/img/create-entity-adapter/image-3.webp b/contents/posts/React/create-entity-adapter/img/image-3.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-3.webp rename to contents/posts/React/create-entity-adapter/img/image-3.webp diff --git a/contents/posts/React/img/create-entity-adapter/image-4.jpeg b/contents/posts/React/create-entity-adapter/img/image-4.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-4.jpeg rename to contents/posts/React/create-entity-adapter/img/image-4.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/image-4.png b/contents/posts/React/create-entity-adapter/img/image-4.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-4.png rename to contents/posts/React/create-entity-adapter/img/image-4.png diff --git a/contents/posts/React/img/create-entity-adapter/image-4.webp b/contents/posts/React/create-entity-adapter/img/image-4.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-4.webp rename to contents/posts/React/create-entity-adapter/img/image-4.webp diff --git a/contents/posts/React/img/create-entity-adapter/image-5.jpeg b/contents/posts/React/create-entity-adapter/img/image-5.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-5.jpeg rename to contents/posts/React/create-entity-adapter/img/image-5.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/image-5.png b/contents/posts/React/create-entity-adapter/img/image-5.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-5.png rename to contents/posts/React/create-entity-adapter/img/image-5.png diff --git a/contents/posts/React/img/create-entity-adapter/image-5.webp b/contents/posts/React/create-entity-adapter/img/image-5.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-5.webp rename to contents/posts/React/create-entity-adapter/img/image-5.webp diff --git a/contents/posts/React/img/create-entity-adapter/image-6.jpeg b/contents/posts/React/create-entity-adapter/img/image-6.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-6.jpeg rename to contents/posts/React/create-entity-adapter/img/image-6.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/image-6.png b/contents/posts/React/create-entity-adapter/img/image-6.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-6.png rename to contents/posts/React/create-entity-adapter/img/image-6.png diff --git a/contents/posts/React/img/create-entity-adapter/image-6.webp b/contents/posts/React/create-entity-adapter/img/image-6.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image-6.webp rename to contents/posts/React/create-entity-adapter/img/image-6.webp diff --git a/contents/posts/React/img/create-entity-adapter/image.jpeg b/contents/posts/React/create-entity-adapter/img/image.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image.jpeg rename to contents/posts/React/create-entity-adapter/img/image.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/image.png b/contents/posts/React/create-entity-adapter/img/image.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image.png rename to contents/posts/React/create-entity-adapter/img/image.png diff --git a/contents/posts/React/img/create-entity-adapter/image.webp b/contents/posts/React/create-entity-adapter/img/image.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/image.webp rename to contents/posts/React/create-entity-adapter/img/image.webp diff --git a/contents/posts/React/img/create-entity-adapter/nested.jpeg b/contents/posts/React/create-entity-adapter/img/nested.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/nested.jpeg rename to contents/posts/React/create-entity-adapter/img/nested.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/nested.png b/contents/posts/React/create-entity-adapter/img/nested.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/nested.png rename to contents/posts/React/create-entity-adapter/img/nested.png diff --git a/contents/posts/React/img/create-entity-adapter/nested.webp b/contents/posts/React/create-entity-adapter/img/nested.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/nested.webp rename to contents/posts/React/create-entity-adapter/img/nested.webp diff --git a/contents/posts/React/img/create-entity-adapter/spotify-global-state.jpeg b/contents/posts/React/create-entity-adapter/img/spotify-global-state.jpeg similarity index 100% rename from contents/posts/React/img/create-entity-adapter/spotify-global-state.jpeg rename to contents/posts/React/create-entity-adapter/img/spotify-global-state.jpeg diff --git a/contents/posts/React/img/create-entity-adapter/spotify-global-state.png b/contents/posts/React/create-entity-adapter/img/spotify-global-state.png similarity index 100% rename from contents/posts/React/img/create-entity-adapter/spotify-global-state.png rename to contents/posts/React/create-entity-adapter/img/spotify-global-state.png diff --git a/contents/posts/React/img/create-entity-adapter/spotify-global-state.webp b/contents/posts/React/create-entity-adapter/img/spotify-global-state.webp similarity index 100% rename from contents/posts/React/img/create-entity-adapter/spotify-global-state.webp rename to contents/posts/React/create-entity-adapter/img/spotify-global-state.webp diff --git a/contents/posts/React/create-entity-adapter.md b/contents/posts/React/create-entity-adapter/index.md similarity index 96% rename from contents/posts/React/create-entity-adapter.md rename to contents/posts/React/create-entity-adapter/index.md index 0c617b6..41e4b2b 100644 --- a/contents/posts/React/create-entity-adapter.md +++ b/contents/posts/React/create-entity-adapter/index.md @@ -16,7 +16,7 @@ head: 혹시 여러분은 어떤 상태를 전역상태로 관리하고 있나요 ? -![전역 상태의 종류](./img/create-entity-adapter/global-state.png) +![전역 상태의 종류](./img/global-state.png) 사용자의 인증정보, 테마 설정, 전역적으로 관리되는 모달이나 토스트, 그리고 서버에서 받아온 데이터들까지 다양한 상태들이 전역상태로 관리될 수 있습니다. @@ -28,7 +28,7 @@ head: Spotify 앱을 예시로 생각해봅시다 -![Spotify 앱 예시](./img/create-entity-adapter/spotify-global-state.png) +![Spotify 앱 예시](./img/spotify-global-state.png) 좌측에는 재생목록이 있고, 가운데는 재생목록에 속한 노래들이 목록 형태로 주어져 있습니다.
하단에는 현재 재생중인 노래의 정보가 표시되고 있네요. @@ -63,7 +63,7 @@ interface Playlist { ## 🫨 Nested 한 전역상태의 문제점 -![alt text](./img/create-entity-adapter/nested.png) +![alt text](./img/nested.png) 이러한 구조에서 발생하는 문제는 어떤 것들이 있을까요?
처음 봤을때는 별 문제가 없어 보일수도 있습니다. 저도 그랬구요.. @@ -75,11 +75,11 @@ interface Playlist { > id 가 1인 노래가 싫어졌어요 ㅠㅠ
> 모든 플레이리스트에서 id 가 1인 노래의 liked 속성을 false 로 토글해주세요! -![alt text](./img/create-entity-adapter/image.png) +![alt text](./img/image.png) 먼저 모든 플레이리스트를 순회합니다 ($$O(n)$$) -![alt text](./img/create-entity-adapter/image-1.png) +![alt text](./img/image-1.png) 이후, 각 플레이리스트의 `tracks` 배열을 순회하며 ($$O(m)$$)
id 가 1인 노래를 찾으면 liked 속성을 토글합니다 @@ -90,7 +90,7 @@ id 가 1인 노래를 찾으면 liked 속성을 토글합니다 또는 구현을 했는데 `어느 한군데의 플레이리스트에서 id 가 1인 노래의 liked 속성이 토글되지 않았다면?`
디버깅하기가 너무 힘들어집니다. -![alt text](./img/create-entity-adapter/image-2.png) +![alt text](./img/image-2.png) 그리고 두 플레이리스트를 각각 구독하고있는 컴포넌트 `` 과 `` 이 있다고 가정해봅시다. @@ -101,7 +101,7 @@ id 가 1인 노래를 찾으면 liked 속성을 토글합니다 이처럼 Nested 한 전역상태는 다음과 같은 문제점이 있습니다. -![alt text](./img/create-entity-adapter/image-3.png) +![alt text](./img/image-3.png) > 1. 동일한 데이터가 중복되어 흩어져 있다 (일관성 깨짐) > 2. 변경 범위가 너무 크다 (불필요한 재렌더링) @@ -112,7 +112,7 @@ id 가 1인 노래를 찾으면 liked 속성을 토글합니다 ## 🧐 어떻게 중복된 상태를 제거할 수 있을까 ? -![alt text](./img/create-entity-adapter/image-4.png) +![alt text](./img/image-4.png) 데이터베이스에서는 중복된 데이터를 제거하기 위해 `정규화(Normalization)` 라는 개념을 사용합니다.
그 중, 제1정규형 (1NF) 는 `최소한의 테이블은 관계이며, 중복되는 항목이 없어야한다` 는 원칙을 가지고 있습니다. @@ -127,7 +127,7 @@ id 가 1인 노래를 찾으면 liked 속성을 토글합니다 ## 🤩 Spotify 전역상태 다시 설계하기 -![alt text](./img/create-entity-adapter/image-5.png) +![alt text](./img/image-5.png) 오른쪽 그림과 같이 기존에 중첩되어 있던 `tracks` 배열을 분리해서 각각의 id 로 접근할 수 있는 유사배열객체 형태로 바꿀 수 있습니다. @@ -331,7 +331,7 @@ export const selectPlaylistWithTracks = (playlistId: PlaylistId) => { ## 🏁 정리하자면 -![alt text](./img/create-entity-adapter/image-6.png) +![alt text](./img/image-6.png) 1. React App 이 커질수록 전역상태는 단순한 UI 상태 저장소가 아니라 관계가 연결된 도메인 데이터를 다루게 된다. 2. Nested 구조는 중복, 비일관성, 과한 리렌더링이 발생하고, 이를 정규화를 통해 해결할 수 있다 diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-1.gif b/contents/posts/React/inf-scroll/img/inf-scroll-1.gif similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-1.gif rename to contents/posts/React/inf-scroll/img/inf-scroll-1.gif diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-10.gif b/contents/posts/React/inf-scroll/img/inf-scroll-10.gif similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-10.gif rename to contents/posts/React/inf-scroll/img/inf-scroll-10.gif diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-11.gif b/contents/posts/React/inf-scroll/img/inf-scroll-11.gif similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-11.gif rename to contents/posts/React/inf-scroll/img/inf-scroll-11.gif diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-12.gif b/contents/posts/React/inf-scroll/img/inf-scroll-12.gif similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-12.gif rename to contents/posts/React/inf-scroll/img/inf-scroll-12.gif diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-13.gif b/contents/posts/React/inf-scroll/img/inf-scroll-13.gif similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-13.gif rename to contents/posts/React/inf-scroll/img/inf-scroll-13.gif diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-14.gif b/contents/posts/React/inf-scroll/img/inf-scroll-14.gif similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-14.gif rename to contents/posts/React/inf-scroll/img/inf-scroll-14.gif diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-2.jpeg b/contents/posts/React/inf-scroll/img/inf-scroll-2.jpeg similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-2.jpeg rename to contents/posts/React/inf-scroll/img/inf-scroll-2.jpeg diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-2.png b/contents/posts/React/inf-scroll/img/inf-scroll-2.png similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-2.png rename to contents/posts/React/inf-scroll/img/inf-scroll-2.png diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-2.webp b/contents/posts/React/inf-scroll/img/inf-scroll-2.webp similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-2.webp rename to contents/posts/React/inf-scroll/img/inf-scroll-2.webp diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-3.jpeg b/contents/posts/React/inf-scroll/img/inf-scroll-3.jpeg similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-3.jpeg rename to contents/posts/React/inf-scroll/img/inf-scroll-3.jpeg diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-3.png b/contents/posts/React/inf-scroll/img/inf-scroll-3.png similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-3.png rename to contents/posts/React/inf-scroll/img/inf-scroll-3.png diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-3.webp b/contents/posts/React/inf-scroll/img/inf-scroll-3.webp similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-3.webp rename to contents/posts/React/inf-scroll/img/inf-scroll-3.webp diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-4.jpeg b/contents/posts/React/inf-scroll/img/inf-scroll-4.jpeg similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-4.jpeg rename to contents/posts/React/inf-scroll/img/inf-scroll-4.jpeg diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-4.png b/contents/posts/React/inf-scroll/img/inf-scroll-4.png similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-4.png rename to contents/posts/React/inf-scroll/img/inf-scroll-4.png diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-4.webp b/contents/posts/React/inf-scroll/img/inf-scroll-4.webp similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-4.webp rename to contents/posts/React/inf-scroll/img/inf-scroll-4.webp diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-5.gif b/contents/posts/React/inf-scroll/img/inf-scroll-5.gif similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-5.gif rename to contents/posts/React/inf-scroll/img/inf-scroll-5.gif diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-6.jpeg b/contents/posts/React/inf-scroll/img/inf-scroll-6.jpeg similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-6.jpeg rename to contents/posts/React/inf-scroll/img/inf-scroll-6.jpeg diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-6.png b/contents/posts/React/inf-scroll/img/inf-scroll-6.png similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-6.png rename to contents/posts/React/inf-scroll/img/inf-scroll-6.png diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-6.webp b/contents/posts/React/inf-scroll/img/inf-scroll-6.webp similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-6.webp rename to contents/posts/React/inf-scroll/img/inf-scroll-6.webp diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-7.jpeg b/contents/posts/React/inf-scroll/img/inf-scroll-7.jpeg similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-7.jpeg rename to contents/posts/React/inf-scroll/img/inf-scroll-7.jpeg diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-7.png b/contents/posts/React/inf-scroll/img/inf-scroll-7.png similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-7.png rename to contents/posts/React/inf-scroll/img/inf-scroll-7.png diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-7.webp b/contents/posts/React/inf-scroll/img/inf-scroll-7.webp similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-7.webp rename to contents/posts/React/inf-scroll/img/inf-scroll-7.webp diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-8.gif b/contents/posts/React/inf-scroll/img/inf-scroll-8.gif similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-8.gif rename to contents/posts/React/inf-scroll/img/inf-scroll-8.gif diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-8.jpeg b/contents/posts/React/inf-scroll/img/inf-scroll-8.jpeg similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-8.jpeg rename to contents/posts/React/inf-scroll/img/inf-scroll-8.jpeg diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-8.png b/contents/posts/React/inf-scroll/img/inf-scroll-8.png similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-8.png rename to contents/posts/React/inf-scroll/img/inf-scroll-8.png diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-8.webp b/contents/posts/React/inf-scroll/img/inf-scroll-8.webp similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-8.webp rename to contents/posts/React/inf-scroll/img/inf-scroll-8.webp diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-9.jpeg b/contents/posts/React/inf-scroll/img/inf-scroll-9.jpeg similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-9.jpeg rename to contents/posts/React/inf-scroll/img/inf-scroll-9.jpeg diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-9.png b/contents/posts/React/inf-scroll/img/inf-scroll-9.png similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-9.png rename to contents/posts/React/inf-scroll/img/inf-scroll-9.png diff --git a/contents/posts/React/img/inf-scroll/inf-scroll-9.webp b/contents/posts/React/inf-scroll/img/inf-scroll-9.webp similarity index 100% rename from contents/posts/React/img/inf-scroll/inf-scroll-9.webp rename to contents/posts/React/inf-scroll/img/inf-scroll-9.webp diff --git a/contents/posts/React/inf-scroll.md b/contents/posts/React/inf-scroll/index.md similarity index 91% rename from contents/posts/React/inf-scroll.md rename to contents/posts/React/inf-scroll/index.md index 234fbe7..621d659 100644 --- a/contents/posts/React/inf-scroll.md +++ b/contents/posts/React/inf-scroll/index.md @@ -6,7 +6,7 @@ description: React와 Intersection Observer API를 활용해 성능 최적화된 comment: true --- -![alt text](./img/inf-scroll/inf-scroll-1.gif) +![alt text](./img/inf-scroll-1.gif) 현대의 모바일 웹이나 앱에서 흔이 볼 수 있는 기능 중 하나가 바로 '무한 스크롤' 입니다. 하지만, 무한 스크롤을 이해하기 위해선 먼저 '페이지네이션'을 알아볼 필요가 있습니다. @@ -14,7 +14,7 @@ comment: true ## 📖 Pagination 페이지네이션이란? -![](./img/inf-scroll/inf-scroll-2.png) +![](./img/inf-scroll-2.png) 페이지네이션이란? 많은 데이터를 부분적으로 나눠서 불러오는 기술을 말합니다. @@ -42,18 +42,18 @@ comment: true 오프셋 기반 페이지네이션은 페이지를 기준으로 데이터를 잘라서 요청하는 페이지네이션 입니다. -![](./img/inf-scroll/inf-scroll-3.png) +![](./img/inf-scroll-3.png) 주로, 페이지 버튼이 있는 UI 에서 사용되며, API 호출시, 원하는 데이터 개수와, 몇 번째 페이지를 가져올지 명시합니다. -![](./img/inf-scroll/inf-scroll-4.png) +![](./img/inf-scroll-4.png) 오프셋 기반의 페이지네이션은 커서 기반 페이지네이션보다 비교적 구현이 간단하다는 장점이 있지만,
페이지네이션 도중, 데이터가 추가/삭제 될 경우, 데이터가 누락/중복 될 수 있다는 단점이 있습니다. ### ✏️ Offset Based Pagination 오프셋 기반 페이지네이션의 동작 -![](./img/inf-scroll/inf-scroll-5.gif) +![](./img/inf-scroll-5.gif) 10개의 데이터를 4개씩 나눠 오프셋 기반의 페이지네이션으로 가져오는 상황을 가정해 보겠습니다. @@ -64,20 +64,20 @@ comment: true ### ✏️ Cursor Based Pagination 커서 기반 페이지네이션 -![](./img/inf-scroll/inf-scroll-6.png) +![](./img/inf-scroll-6.png) 커서 기반의 페이지네이션은 가장 최근에 가져온 데이터를 기준으로, 다음 데이터를 불러옵니다. 주로, 무한 스크롤과 같은 UI 에서 사용되며, API 호출시, 마지막 데이터의 기준값, 원하는 데이터 개수를 명시합니다. -![](./img/inf-scroll/inf-scroll-7.png) +![](./img/inf-scroll-7.png) 커서 기반 페이지네이션은 최근 요청된 데이터를 기준으로 쿼리가 작성되기 때문에, 누락되거나 중복될 확률이 적다는 장점이 있지만,
페이지네이션 구현이 비교적 복잡할 수 있다는 단점이 있습니다 ### ✏️ Offset Based Pagination 오프셋 기반 페이지네이션의 동작 -![](./img/inf-scroll/inf-scroll-8.gif) +![](./img/inf-scroll-8.gif) 이전과 동일한 10개의 데이터를 페이징하는 상황에서,
응답에 들어있는 커서를 다음 요청의 query 로 전송하면, 서버에서는 해당 커서 이후의 데이터를 응답으로 보내줍니다. @@ -86,7 +86,7 @@ comment: true ### ✏️ 정리 -![](./img/inf-scroll/inf-scroll-8.png) +![](./img/inf-scroll-8.png) ## 📖 Infinite Scroll 무한 스크롤 @@ -94,7 +94,7 @@ comment: true 무한 스크롤을 구현하기 위한 요구사항을 정리하면 다음과 같습니다. -![](./img/inf-scroll/inf-scroll-9.png) +![](./img/inf-scroll-9.png) 다음 페이지에 대한 데이터는 이전 응답에서의 커서를 요청 쿼리 파라미터에 넣으면 되고,
우리는 사용자가 페이지 하단에 도달했을때를 감지할 수 있어야 합니다. @@ -103,7 +103,7 @@ comment: true ScrollEventListener 를 사용하면, 사용자가 얼만큼 스크롤을 내렸는지 확인 할 수 있습니다. -![](./img/inf-scroll/inf-scroll-10.gif) +![](./img/inf-scroll-10.gif) 브라우저에서는 스크롤이 가능한 컨테이너에 대해 `scrollTop` , `clientHeight` , `scrollHeight` 프로퍼티를 제공합니다. @@ -112,7 +112,7 @@ ScrollEventListener 를 사용하면, 사용자가 얼만큼 스크롤을 내렸 ### ✏️ Scroll Event 의 단점 -![](./img/inf-scroll/inf-scroll-11.gif) +![](./img/inf-scroll-11.gif) 하지만, 스크롤 이벤트 핸들러를 사용하면,
스크롤이 발생 할 때 마다 콜백함수가 Task Queue 에 등록되게 됩니다. @@ -122,14 +122,14 @@ JS 는 싱글 스레드로 동작하기 때문에, 스크롤 이벤트와 같은 이는 네트워크 요청이나 다른 UI 업데이트가 늦어지거나 멈추는 현상이 발생 할 수 있습니다. -![](./img/inf-scroll/inf-scroll-12.gif) +![](./img/inf-scroll-12.gif) ### ✏️ Intersection Observer 다행이도 DOM API 에서는 Element 의 가시성을 판단해주는
IntersectionObserver API 를 제공합니다 -![](./img/inf-scroll/inf-scroll-13.gif) +![](./img/inf-scroll-13.gif) 우리는 단순히 intersectionObserver 인스턴스를 생성하고,
감시할 요소를 intersectionObserver.observe(target) 으로 관찰할 수 있습니다. @@ -139,7 +139,7 @@ IntersectionObserver API 를 제공합니다 ### ✏️ Intersection Observer 로 무한 스크롤 구현하기 -![](./img/inf-scroll/inf-scroll-14.gif) +![](./img/inf-scroll-14.gif) > 1. 먼저 감시할 요소, 스크롤 컨테이너 요소, Intersection Observer 의 인스턴스를 저장할 ref 를 선언합니다
> 2. 이후, observerOptions 와 observerCallback 을 설정해 주고,
diff --git a/contents/posts/React/img/kareer-fit-1/after.gif b/contents/posts/React/kareer-fit-1/img/after.gif similarity index 100% rename from contents/posts/React/img/kareer-fit-1/after.gif rename to contents/posts/React/kareer-fit-1/img/after.gif diff --git a/contents/posts/React/img/kareer-fit-1/before.gif b/contents/posts/React/kareer-fit-1/img/before.gif similarity index 100% rename from contents/posts/React/img/kareer-fit-1/before.gif rename to contents/posts/React/kareer-fit-1/img/before.gif diff --git a/contents/posts/React/img/kareer-fit-1/event-bus-architecture.webp b/contents/posts/React/kareer-fit-1/img/event-bus-architecture.webp similarity index 100% rename from contents/posts/React/img/kareer-fit-1/event-bus-architecture.webp rename to contents/posts/React/kareer-fit-1/img/event-bus-architecture.webp diff --git a/contents/posts/React/img/kareer-fit-1/image-1.jpeg b/contents/posts/React/kareer-fit-1/img/image-1.jpeg similarity index 100% rename from contents/posts/React/img/kareer-fit-1/image-1.jpeg rename to contents/posts/React/kareer-fit-1/img/image-1.jpeg diff --git a/contents/posts/React/img/kareer-fit-1/image-1.png b/contents/posts/React/kareer-fit-1/img/image-1.png similarity index 100% rename from contents/posts/React/img/kareer-fit-1/image-1.png rename to contents/posts/React/kareer-fit-1/img/image-1.png diff --git a/contents/posts/React/img/kareer-fit-1/image-1.webp b/contents/posts/React/kareer-fit-1/img/image-1.webp similarity index 100% rename from contents/posts/React/img/kareer-fit-1/image-1.webp rename to contents/posts/React/kareer-fit-1/img/image-1.webp diff --git a/contents/posts/React/img/kareer-fit-1/image.jpeg b/contents/posts/React/kareer-fit-1/img/image.jpeg similarity index 100% rename from contents/posts/React/img/kareer-fit-1/image.jpeg rename to contents/posts/React/kareer-fit-1/img/image.jpeg diff --git a/contents/posts/React/img/kareer-fit-1/image.png b/contents/posts/React/kareer-fit-1/img/image.png similarity index 100% rename from contents/posts/React/img/kareer-fit-1/image.png rename to contents/posts/React/kareer-fit-1/img/image.png diff --git a/contents/posts/React/img/kareer-fit-1/image.webp b/contents/posts/React/kareer-fit-1/img/image.webp similarity index 100% rename from contents/posts/React/img/kareer-fit-1/image.webp rename to contents/posts/React/kareer-fit-1/img/image.webp diff --git a/contents/posts/React/img/kareer-fit-1/select-state-machine.webp b/contents/posts/React/kareer-fit-1/img/select-state-machine.webp similarity index 100% rename from contents/posts/React/img/kareer-fit-1/select-state-machine.webp rename to contents/posts/React/kareer-fit-1/img/select-state-machine.webp diff --git a/contents/posts/React/kareer-fit-1.md b/contents/posts/React/kareer-fit-1/index.md similarity index 96% rename from contents/posts/React/kareer-fit-1.md rename to contents/posts/React/kareer-fit-1/index.md index 5875d66..0957ade 100644 --- a/contents/posts/React/kareer-fit-1.md +++ b/contents/posts/React/kareer-fit-1/index.md @@ -19,11 +19,11 @@ React 개발자라면 재렌더링을 위해 `useState`를 사용해 상태를 U 최근 PDF 문서 위에 사용자가 드래그로 영역을 선택해 피드백을 남기는 기능을 개발하게 되었다. 당연하게도 `useState` 로 드래그 영역의 좌표를 관리했다. 잘 동작했지만, 결과는 처참했다.
-![니 코드 성능 너무 구려서 컴퓨터 뻗어버림 ㅋㅋ](./img/kareer-fit-1/image.png) +![니 코드 성능 너무 구려서 컴퓨터 뻗어버림 ㅋㅋ](./img/image.png) 마우스를 조금만 빠르게 움직여도 이벤트가 씹히는 현상이 발생했다. `onMouseMove` 이벤트가 발생할 때마다 `setState`가 호출되면서 초당 수십 번의 리렌더링이 일어났기 때문이다. ([PR - Feature#31](https://github.com/kakao-tech-campus-3rd-step3/Team7_FE/pull/38)) -![변경 전](./img/kareer-fit-1/before.gif) +![변경 전](./img/before.gif) 이처럼 간단해 보이는 기능에서, 어떻게 성능과 멋찐 아키텍쳐를 모두 잡을 수 있을까? @@ -39,7 +39,7 @@ React 개발자라면 재렌더링을 위해 `useState`를 사용해 상태를 U `useRef`는 컴포넌트가 리렌더링 되더라도 값이 유지되며, 값이 변경되어도 리렌더링을 발생시키지 않는다.
따라서 드래그 중인 좌표를 `useRef`로 관리하면 불필요한 리렌더링을 피할 수 있다. -![변경 후](./img/kareer-fit-1/after.gif) +![변경 후](./img/after.gif) 또, `useRef`를 사용해 DOM 엘리먼트를 직접 참조하고 `style` 속성을 직접 변경했다.
리렌더링은 0회. 성능 문제는 해결되었따! @@ -62,7 +62,7 @@ React 개발자라면 재렌더링을 위해 `useState`를 사용해 상태를 U > Publish-Subscribe 모델의 한 형태로, 시스템의 각 부분을 독립적인 모듈로 만들어 결합도를 낮추는데 도움을 준다.
- 이게뭐고.. + 이게뭐고..
쉽게 말해! 인스타 팔로우 라고 생각하면된다!
@@ -163,11 +163,11 @@ const eventBus = new EventBus() 또, 각각의 플러그인은 독립적으로 개발 및 테스트할 수 있어 유지보수도 용이하다. -![클래스 다이어그램](./img/kareer-fit-1/event-bus-architecture.webp) +![클래스 다이어그램](./img/event-bus-architecture.webp) SelectionEventController는 단순히 `attach` 로 부터 받은 `eventBus` 를 통해 이벤트를 구독하고, 상태머신을 이용해 고수준 이벤트로 변환해 발행하는 역할만 한다. -![SelectionEventController 상태 머신](./img/kareer-fit-1/select-state-machine.webp) +![SelectionEventController 상태 머신](./img/select-state-machine.webp) ```ts export type SelectionState = "idle" | "dragging"; diff --git a/contents/posts/React/react-aop-hoc.md b/contents/posts/React/react-aop-hoc/index.md similarity index 100% rename from contents/posts/React/react-aop-hoc.md rename to contents/posts/React/react-aop-hoc/index.md diff --git a/contents/posts/React/react-create-portal-modal.md b/contents/posts/React/react-create-portal-modal/index.md similarity index 100% rename from contents/posts/React/react-create-portal-modal.md rename to contents/posts/React/react-create-portal-modal/index.md diff --git a/contents/posts/React/img/react-toastify/toastify-1.jpeg b/contents/posts/React/react-toastify/img/toastify-1.jpeg similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-1.jpeg rename to contents/posts/React/react-toastify/img/toastify-1.jpeg diff --git a/contents/posts/React/img/react-toastify/toastify-1.png b/contents/posts/React/react-toastify/img/toastify-1.png similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-1.png rename to contents/posts/React/react-toastify/img/toastify-1.png diff --git a/contents/posts/React/img/react-toastify/toastify-1.webp b/contents/posts/React/react-toastify/img/toastify-1.webp similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-1.webp rename to contents/posts/React/react-toastify/img/toastify-1.webp diff --git a/contents/posts/React/img/react-toastify/toastify-2.jpeg b/contents/posts/React/react-toastify/img/toastify-2.jpeg similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-2.jpeg rename to contents/posts/React/react-toastify/img/toastify-2.jpeg diff --git a/contents/posts/React/img/react-toastify/toastify-2.png b/contents/posts/React/react-toastify/img/toastify-2.png similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-2.png rename to contents/posts/React/react-toastify/img/toastify-2.png diff --git a/contents/posts/React/img/react-toastify/toastify-2.webp b/contents/posts/React/react-toastify/img/toastify-2.webp similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-2.webp rename to contents/posts/React/react-toastify/img/toastify-2.webp diff --git a/contents/posts/React/img/react-toastify/toastify-3.jpeg b/contents/posts/React/react-toastify/img/toastify-3.jpeg similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-3.jpeg rename to contents/posts/React/react-toastify/img/toastify-3.jpeg diff --git a/contents/posts/React/img/react-toastify/toastify-3.png b/contents/posts/React/react-toastify/img/toastify-3.png similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-3.png rename to contents/posts/React/react-toastify/img/toastify-3.png diff --git a/contents/posts/React/img/react-toastify/toastify-3.webp b/contents/posts/React/react-toastify/img/toastify-3.webp similarity index 100% rename from contents/posts/React/img/react-toastify/toastify-3.webp rename to contents/posts/React/react-toastify/img/toastify-3.webp diff --git a/contents/posts/React/react-toastify.md b/contents/posts/React/react-toastify/index.md similarity index 98% rename from contents/posts/React/react-toastify.md rename to contents/posts/React/react-toastify/index.md index d404098..eeca0cf 100644 --- a/contents/posts/React/react-toastify.md +++ b/contents/posts/React/react-toastify/index.md @@ -51,7 +51,7 @@ setTimeout(() => toast("잠깐 후에 다시 알려줌!"), 5000); `react-toastify` 는 아래와 같은 흐름으로 동작합니다
-![alt text](./img/react-toastify/toastify-1.png) +![alt text](./img/toastify-1.png) 옆에 `react-toastify` 코드를 함께 보고 흐름을따라가면 이해하기가 쉽습니다! (https://github.com/fkhadra/react-toastify) @@ -59,7 +59,7 @@ setTimeout(() => toast("잠깐 후에 다시 알려줌!"), 5000); ### 1. `` 의 마운트 및 subscribe -![alt text](./img/react-toastify/toastify-2.png) +![alt text](./img/toastify-2.png) `react-toastify` 를 사용하기 위해서는 가장 먼저 `` 를 리액트 앱에 마운트 해야 합니다. @@ -206,7 +206,7 @@ React 18 의 Concurrent Rendering 과 함께 도입한 [`useSyncExternalStore`]( 이제 `toast()` 함수가 호출되는 순간의 흐름을 보면, -![alt text](./img/react-toastify/toastify-3.png) +![alt text](./img/toastify-3.png) `toast()` 함수는 내부적으로 `dispatchToast()` 를 호출하고, diff --git a/contents/posts/React/img/react-transition-group/design-exhibition-site.jpeg b/contents/posts/React/react-transition-group/img/design-exhibition-site.jpeg similarity index 100% rename from contents/posts/React/img/react-transition-group/design-exhibition-site.jpeg rename to contents/posts/React/react-transition-group/img/design-exhibition-site.jpeg diff --git a/contents/posts/React/img/react-transition-group/design-exhibition-site.png b/contents/posts/React/react-transition-group/img/design-exhibition-site.png similarity index 100% rename from contents/posts/React/img/react-transition-group/design-exhibition-site.png rename to contents/posts/React/react-transition-group/img/design-exhibition-site.png diff --git a/contents/posts/React/img/react-transition-group/design-exhibition-site.webp b/contents/posts/React/react-transition-group/img/design-exhibition-site.webp similarity index 100% rename from contents/posts/React/img/react-transition-group/design-exhibition-site.webp rename to contents/posts/React/react-transition-group/img/design-exhibition-site.webp diff --git a/contents/posts/React/img/react-transition-group/problem-1.jpeg b/contents/posts/React/react-transition-group/img/problem-1.jpeg similarity index 100% rename from contents/posts/React/img/react-transition-group/problem-1.jpeg rename to contents/posts/React/react-transition-group/img/problem-1.jpeg diff --git a/contents/posts/React/img/react-transition-group/problem-1.png b/contents/posts/React/react-transition-group/img/problem-1.png similarity index 100% rename from contents/posts/React/img/react-transition-group/problem-1.png rename to contents/posts/React/react-transition-group/img/problem-1.png diff --git a/contents/posts/React/img/react-transition-group/problem-1.webp b/contents/posts/React/react-transition-group/img/problem-1.webp similarity index 100% rename from contents/posts/React/img/react-transition-group/problem-1.webp rename to contents/posts/React/react-transition-group/img/problem-1.webp diff --git a/contents/posts/React/img/react-transition-group/problem-2.jpeg b/contents/posts/React/react-transition-group/img/problem-2.jpeg similarity index 100% rename from contents/posts/React/img/react-transition-group/problem-2.jpeg rename to contents/posts/React/react-transition-group/img/problem-2.jpeg diff --git a/contents/posts/React/img/react-transition-group/problem-2.png b/contents/posts/React/react-transition-group/img/problem-2.png similarity index 100% rename from contents/posts/React/img/react-transition-group/problem-2.png rename to contents/posts/React/react-transition-group/img/problem-2.png diff --git a/contents/posts/React/img/react-transition-group/problem-2.webp b/contents/posts/React/react-transition-group/img/problem-2.webp similarity index 100% rename from contents/posts/React/img/react-transition-group/problem-2.webp rename to contents/posts/React/react-transition-group/img/problem-2.webp diff --git a/contents/posts/React/img/react-transition-group/transition.webp b/contents/posts/React/react-transition-group/img/transition.webp similarity index 100% rename from contents/posts/React/img/react-transition-group/transition.webp rename to contents/posts/React/react-transition-group/img/transition.webp diff --git a/contents/posts/React/react-transition-group.md b/contents/posts/React/react-transition-group/index.md similarity index 96% rename from contents/posts/React/react-transition-group.md rename to contents/posts/React/react-transition-group/index.md index 5fdc5f9..4c86351 100644 --- a/contents/posts/React/react-transition-group.md +++ b/contents/posts/React/react-transition-group/index.md @@ -12,7 +12,7 @@ head: 디자인학과 졸업전시 웹사이트를 만들면서, 전체 페이지에 수평 아코디언 전환 애니메이션이 필요했습니다. -디자인학과 졸업전시 웹사이트 +디자인학과 졸업전시 웹사이트 처음 접근은 단순히 다른 아코디언 애니메이션처럼 단순하게 접근했습니다.
모든 페이지 컴포넌트를 한 번에 전부 마운트해두고, 각 섹션의 `max-width` 만 조절하면서 열리고 닫히는 애니메이션을 구현했습니다. @@ -22,8 +22,8 @@ head: 그런데 웬걸.. Lighthouse에서 DOM 요소가 3,495개라는 경고가 뜨고, TBT(Total Blocking Time)도 높고 메모리 사용량도 계속 늘어나는 현상이 발생하는게 아니겠습니까?
- 문제 상황 1 - 문제 상황 2 + 문제 상황 1 + 문제 상황 2
무엇보다 `안 보이는 페이지도 계속 DOM 요소로써 남아있다`는 점이 문제였습니다.
@@ -95,7 +95,7 @@ head: ~~사실 프론트같은거 좋아하는 이유도 이렇게 시각적으로 뭔가 정리하는게 이해가 쉽고 재밌어서 그렇습니다 ㅎㅎ~~ -Transition 상태 전이 다이어그램 +Transition 상태 전이 다이어그램 :::details 🙋‍♂️ 상태 전이 다이어그램에서 `[]` 는 뭔가요? - Guard `[]` 표시는 가드(Guard) 조건을 의미합니다.
diff --git a/contents/posts/React/img/redux-flux-architecture/flux.jpeg b/contents/posts/React/redux-flux-architecture/img/flux.jpeg similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/flux.jpeg rename to contents/posts/React/redux-flux-architecture/img/flux.jpeg diff --git a/contents/posts/React/img/redux-flux-architecture/flux.png b/contents/posts/React/redux-flux-architecture/img/flux.png similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/flux.png rename to contents/posts/React/redux-flux-architecture/img/flux.png diff --git a/contents/posts/React/img/redux-flux-architecture/flux.webp b/contents/posts/React/redux-flux-architecture/img/flux.webp similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/flux.webp rename to contents/posts/React/redux-flux-architecture/img/flux.webp diff --git a/contents/posts/React/img/redux-flux-architecture/mvc-limit.jpeg b/contents/posts/React/redux-flux-architecture/img/mvc-limit.jpeg similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/mvc-limit.jpeg rename to contents/posts/React/redux-flux-architecture/img/mvc-limit.jpeg diff --git a/contents/posts/React/img/redux-flux-architecture/mvc-limit.png b/contents/posts/React/redux-flux-architecture/img/mvc-limit.png similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/mvc-limit.png rename to contents/posts/React/redux-flux-architecture/img/mvc-limit.png diff --git a/contents/posts/React/img/redux-flux-architecture/mvc-limit.webp b/contents/posts/React/redux-flux-architecture/img/mvc-limit.webp similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/mvc-limit.webp rename to contents/posts/React/redux-flux-architecture/img/mvc-limit.webp diff --git a/contents/posts/React/img/redux-flux-architecture/mvc.jpeg b/contents/posts/React/redux-flux-architecture/img/mvc.jpeg similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/mvc.jpeg rename to contents/posts/React/redux-flux-architecture/img/mvc.jpeg diff --git a/contents/posts/React/img/redux-flux-architecture/mvc.png b/contents/posts/React/redux-flux-architecture/img/mvc.png similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/mvc.png rename to contents/posts/React/redux-flux-architecture/img/mvc.png diff --git a/contents/posts/React/img/redux-flux-architecture/mvc.webp b/contents/posts/React/redux-flux-architecture/img/mvc.webp similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/mvc.webp rename to contents/posts/React/redux-flux-architecture/img/mvc.webp diff --git a/contents/posts/React/img/redux-flux-architecture/prop-drilling.jpeg b/contents/posts/React/redux-flux-architecture/img/prop-drilling.jpeg similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/prop-drilling.jpeg rename to contents/posts/React/redux-flux-architecture/img/prop-drilling.jpeg diff --git a/contents/posts/React/img/redux-flux-architecture/prop-drilling.png b/contents/posts/React/redux-flux-architecture/img/prop-drilling.png similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/prop-drilling.png rename to contents/posts/React/redux-flux-architecture/img/prop-drilling.png diff --git a/contents/posts/React/img/redux-flux-architecture/prop-drilling.webp b/contents/posts/React/redux-flux-architecture/img/prop-drilling.webp similarity index 100% rename from contents/posts/React/img/redux-flux-architecture/prop-drilling.webp rename to contents/posts/React/redux-flux-architecture/img/prop-drilling.webp diff --git a/contents/posts/React/redux-flux-architecture.md b/contents/posts/React/redux-flux-architecture/index.md similarity index 98% rename from contents/posts/React/redux-flux-architecture.md rename to contents/posts/React/redux-flux-architecture/index.md index ecb4368..f365cec 100644 --- a/contents/posts/React/redux-flux-architecture.md +++ b/contents/posts/React/redux-flux-architecture/index.md @@ -29,7 +29,7 @@ PHP 기반의 웹 프레임워크는 기본적으로 MVC (Model - View - Control > `뷰 (View)` : 사용자에게 보이는 인터페이스로, HTML, CSS 이나 템플릿엔진을 활용해 화면을 구성합니다.
> `컨트롤러 (Controller)` : Model 과 View 사이의 상호작용을 관리합니다. 사용자의 요청 / 입력을 받아 Model 을 업데이트하고, 그에 따른 View 를 갱신하는 작업을 합니다. -![](./img/redux-flux-architecture/mvc.png) +![](./img/mvc.png) 하지만, 애플리케이션의 규모가 커지면서, MVC 구조는 점점 더 복잡해져 갔습니다. @@ -47,7 +47,7 @@ PHP 기반의 웹 프레임워크는 기본적으로 MVC (Model - View - Control 라는 단점으로 다가왔습니다. -![](./img/redux-flux-architecture/mvc-limit.png) +![](./img/mvc-limit.png) ### ✍️ MVVM 아키텍쳐과 Component 패턴 @@ -69,7 +69,7 @@ PHP 기반의 웹 프레임워크는 기본적으로 MVC (Model - View - Control 하지만, Container-Presenter 패턴을 이용해 만들었을때, 컴포넌트 구조가 복잡해짐에 따라, 하위 컴포넌트에 값을 전달하기 위해, `Props Drilling Problem` 이 발생하게 됩니다. -![](./img/redux-flux-architecture/prop-drilling.png) +![](./img/prop-drilling.png) ### ✍️ Flux 아키텍쳐 @@ -77,7 +77,7 @@ Container-Presenter 패턴에서 발생한 Prop Drilling 을 통해 데이터를 그래서 단방향 데이터 흐름을 활용한 리액트용 애플리케이션 아키텍쳐인 Flux 아키텍쳐가 탄생했습니다. -![](./img/redux-flux-architecture/flux.png) +![](./img/flux.png) 데이터를 변화시키려는 동작(Action) 이 발생하면 Dispatcher 는 Action 을 받아 Redux 에 Action 이 발생했음을 알리고, @@ -134,7 +134,7 @@ Redux 는 다음과 같은 요소로 구성되어 있습니다. Redux 의 구성요소와 함께 Flux 아키텍쳐가 어떻게 적용되어 Redux 의 상태가 변화하고, View 에 반영되는지 이전에 봤던 그림과 함께 알아보겠습니다. -![](./img/redux-flux-architecture/flux.png) +![](./img/flux.png) 실제 Counter 예제를 통해 Redux의 데이터 흐름이 어떻게 동작하는지 단계별로 살펴보겠습니다. diff --git a/contents/posts/React/redux-normalizing-state-shape.md b/contents/posts/React/redux-normalizing-state-shape/index.md similarity index 100% rename from contents/posts/React/redux-normalizing-state-shape.md rename to contents/posts/React/redux-normalizing-state-shape/index.md diff --git a/contents/posts/React/redux-vs-context.md b/contents/posts/React/redux-vs-context/index.md similarity index 100% rename from contents/posts/React/redux-vs-context.md rename to contents/posts/React/redux-vs-context/index.md diff --git a/contents/posts/React/solid-render-props.md b/contents/posts/React/solid-render-props/index.md similarity index 100% rename from contents/posts/React/solid-render-props.md rename to contents/posts/React/solid-render-props/index.md diff --git a/contents/posts/React/img/storybook-mcp/1.jpeg b/contents/posts/React/storybook-mcp/img/1.jpeg similarity index 100% rename from contents/posts/React/img/storybook-mcp/1.jpeg rename to contents/posts/React/storybook-mcp/img/1.jpeg diff --git a/contents/posts/React/img/storybook-mcp/1.png b/contents/posts/React/storybook-mcp/img/1.png similarity index 100% rename from contents/posts/React/img/storybook-mcp/1.png rename to contents/posts/React/storybook-mcp/img/1.png diff --git a/contents/posts/React/img/storybook-mcp/1.webp b/contents/posts/React/storybook-mcp/img/1.webp similarity index 100% rename from contents/posts/React/img/storybook-mcp/1.webp rename to contents/posts/React/storybook-mcp/img/1.webp diff --git a/contents/posts/React/img/storybook-mcp/2.jpeg b/contents/posts/React/storybook-mcp/img/2.jpeg similarity index 100% rename from contents/posts/React/img/storybook-mcp/2.jpeg rename to contents/posts/React/storybook-mcp/img/2.jpeg diff --git a/contents/posts/React/img/storybook-mcp/2.png b/contents/posts/React/storybook-mcp/img/2.png similarity index 100% rename from contents/posts/React/img/storybook-mcp/2.png rename to contents/posts/React/storybook-mcp/img/2.png diff --git a/contents/posts/React/img/storybook-mcp/2.webp b/contents/posts/React/storybook-mcp/img/2.webp similarity index 100% rename from contents/posts/React/img/storybook-mcp/2.webp rename to contents/posts/React/storybook-mcp/img/2.webp diff --git a/contents/posts/React/img/storybook-mcp/tools.jpeg b/contents/posts/React/storybook-mcp/img/tools.jpeg similarity index 100% rename from contents/posts/React/img/storybook-mcp/tools.jpeg rename to contents/posts/React/storybook-mcp/img/tools.jpeg diff --git a/contents/posts/React/img/storybook-mcp/tools.png b/contents/posts/React/storybook-mcp/img/tools.png similarity index 100% rename from contents/posts/React/img/storybook-mcp/tools.png rename to contents/posts/React/storybook-mcp/img/tools.png diff --git a/contents/posts/React/img/storybook-mcp/tools.webp b/contents/posts/React/storybook-mcp/img/tools.webp similarity index 100% rename from contents/posts/React/img/storybook-mcp/tools.webp rename to contents/posts/React/storybook-mcp/img/tools.webp diff --git a/contents/posts/React/storybook-mcp.md b/contents/posts/React/storybook-mcp/index.md similarity index 97% rename from contents/posts/React/storybook-mcp.md rename to contents/posts/React/storybook-mcp/index.md index 8996dc5..0b746cd 100644 --- a/contents/posts/React/storybook-mcp.md +++ b/contents/posts/React/storybook-mcp/index.md @@ -49,7 +49,7 @@ Storybook MCP를 활성화하면, AI 코딩 도구는 Storybook을 문서 사이 현재 2026년 2월을 기준으로 Storybook MCP 가 제공하는 주요 도구는 다음과 같습니다. -![](./img/storybook-mcp/tools.png) +![](./img/tools.png) ## 1. 전체 컴포넌트 / 문서 목록 조회 (`list-all-documentation`) @@ -184,8 +184,8 @@ Storybook을 실행하면 `http://localhost:6006/mcp` 로 MCP 서버가 자동 또는 Antigravity UI 에서 MCP Servers 설정으로 들어가서 `mcp_config.json` 을 찾을수도 있습니다
- - + +
### Claude Code diff --git a/contents/posts/React/use-imperative-handle.md b/contents/posts/React/use-imperative-handle/index.md similarity index 100% rename from contents/posts/React/use-imperative-handle.md rename to contents/posts/React/use-imperative-handle/index.md diff --git a/contents/posts/React/img/what-is-isomorphic/warn.jpeg b/contents/posts/React/what-is-isomorphic/img/warn.jpeg similarity index 100% rename from contents/posts/React/img/what-is-isomorphic/warn.jpeg rename to contents/posts/React/what-is-isomorphic/img/warn.jpeg diff --git a/contents/posts/React/img/what-is-isomorphic/warn.png b/contents/posts/React/what-is-isomorphic/img/warn.png similarity index 100% rename from contents/posts/React/img/what-is-isomorphic/warn.png rename to contents/posts/React/what-is-isomorphic/img/warn.png diff --git a/contents/posts/React/img/what-is-isomorphic/warn.webp b/contents/posts/React/what-is-isomorphic/img/warn.webp similarity index 100% rename from contents/posts/React/img/what-is-isomorphic/warn.webp rename to contents/posts/React/what-is-isomorphic/img/warn.webp diff --git a/contents/posts/React/what-is-isomorphic.md b/contents/posts/React/what-is-isomorphic/index.md similarity index 99% rename from contents/posts/React/what-is-isomorphic.md rename to contents/posts/React/what-is-isomorphic/index.md index f39f76a..fba220d 100644 --- a/contents/posts/React/what-is-isomorphic.md +++ b/contents/posts/React/what-is-isomorphic/index.md @@ -141,7 +141,7 @@ export const useIsomorphicEffect = typeof window !== "undefined" ? useLayoutEffe 그래서 "페인트 전에 동기 실행, DOM 조작" 이라는 전제 자체가 성립 안 됨으로, 실행할 타이밍이 없고 다음과 같은 경고가 발생합니다.
- +
> Warning: useLayoutEffect does nothing on the server, because its effect runs after the DOM is updated...
diff --git a/contents/posts/TypeScript/chain-of-responsibility.md b/contents/posts/TypeScript/chain-of-responsibility/index.md similarity index 100% rename from contents/posts/TypeScript/chain-of-responsibility.md rename to contents/posts/TypeScript/chain-of-responsibility/index.md diff --git a/contents/posts/Web/img/authentication-authorization/csrf-defend.png b/contents/posts/Web/authentication-authorization/img/csrf-defend.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/csrf-defend.png rename to contents/posts/Web/authentication-authorization/img/csrf-defend.png diff --git a/contents/posts/Web/img/authentication-authorization/csrf.png b/contents/posts/Web/authentication-authorization/img/csrf.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/csrf.png rename to contents/posts/Web/authentication-authorization/img/csrf.png diff --git a/contents/posts/Web/img/authentication-authorization/jwt-1.png b/contents/posts/Web/authentication-authorization/img/jwt-1.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/jwt-1.png rename to contents/posts/Web/authentication-authorization/img/jwt-1.png diff --git a/contents/posts/Web/img/authentication-authorization/jwt-2.png b/contents/posts/Web/authentication-authorization/img/jwt-2.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/jwt-2.png rename to contents/posts/Web/authentication-authorization/img/jwt-2.png diff --git a/contents/posts/Web/img/authentication-authorization/jwt-access-refresh.png b/contents/posts/Web/authentication-authorization/img/jwt-access-refresh.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/jwt-access-refresh.png rename to contents/posts/Web/authentication-authorization/img/jwt-access-refresh.png diff --git a/contents/posts/Web/img/authentication-authorization/jwt.png b/contents/posts/Web/authentication-authorization/img/jwt.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/jwt.png rename to contents/posts/Web/authentication-authorization/img/jwt.png diff --git a/contents/posts/Web/img/authentication-authorization/session-1.png b/contents/posts/Web/authentication-authorization/img/session-1.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/session-1.png rename to contents/posts/Web/authentication-authorization/img/session-1.png diff --git a/contents/posts/Web/img/authentication-authorization/session-2.png b/contents/posts/Web/authentication-authorization/img/session-2.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/session-2.png rename to contents/posts/Web/authentication-authorization/img/session-2.png diff --git a/contents/posts/Web/img/authentication-authorization/session-3.png b/contents/posts/Web/authentication-authorization/img/session-3.png similarity index 100% rename from contents/posts/Web/img/authentication-authorization/session-3.png rename to contents/posts/Web/authentication-authorization/img/session-3.png diff --git a/contents/posts/Web/authentication-authorization.md b/contents/posts/Web/authentication-authorization/index.md similarity index 94% rename from contents/posts/Web/authentication-authorization.md rename to contents/posts/Web/authentication-authorization/index.md index b5afa3c..88d5186 100644 --- a/contents/posts/Web/authentication-authorization.md +++ b/contents/posts/Web/authentication-authorization/index.md @@ -46,7 +46,7 @@ Session 은 서버에서 생성되며, 보통 클라이언트에 Cookie 를 통 ## Session 방식의 인증인가 -![로그인(인증)](./img/authentication-authorization/session-1.png) +![로그인(인증)](./img/session-1.png) > 사용자가 로그인 (인증) 을 요청하면... > (1) Client 가 ID , PW 를 이용해 로그인 요청을 보냅니다 @@ -54,7 +54,7 @@ Session 은 서버에서 생성되며, 보통 클라이언트에 Cookie 를 통 > (3) 올바른 사용자가 인증을 요청한 경우, Session 을 생성해 저장합니다 > (4) 마지막으로 서버는 Cookie 에 SessionID 를 담아 클라이언트에 전달합니다 (HTTP Only Cookie) -![인증된 사용자 요청](./img/authentication-authorization/session-2.png) +![인증된 사용자 요청](./img/session-2.png) > 이후 인증이 필요한 API 를 요청하면... > (1) 해당요청에는 자동으로 Cookie 가 함께 서버로 전송됍니다 @@ -63,7 +63,7 @@ Session 은 서버에서 생성되며, 보통 클라이언트에 Cookie 를 통 > (4) 인증이 필요한 API 에 필요한 데이터를 가져와 > (5) 응답을 클라이언트에 전송합니다 -![로그아웃](./img/authentication-authorization/session-3.png) +![로그아웃](./img/session-3.png) > 사용자가 로그아웃을 요청하면... > (1) 로그아웃 엔드포인트로 API 요청을 날립니다. 이때 쿠키에 세션정보가 함께 전송됩니다. @@ -92,7 +92,7 @@ Session 은 서버에서 생성되며, 보통 클라이언트에 Cookie 를 통 JWT 는 JSON 객체를 사용해 정보를 안전하게 전달하기 위한 개방형 표준 (RFC 7519) 입니다.
JWT 는 주로 인증과 정보 교환에 사용됩니다. -![JWT 구조](./img/authentication-authorization/jwt.png) +![JWT 구조](./img/jwt.png) JWT 는 Header, Payload, Signature 세 부분으로 구성됍니다. @@ -109,7 +109,7 @@ JWT 는 Header, Payload, Signature 세 부분으로 구성됍니다. ## JWT 방식의 인증인가 -![로그인(인증)](./img/authentication-authorization/jwt-1.png) +![로그인(인증)](./img/jwt-1.png) > 사용자가 로그인 (인증) 을 요청하면... > (1) Client 가 ID , PW 를 이용해 로그인 요청을 보냅니다 @@ -118,7 +118,7 @@ JWT 는 Header, Payload, Signature 세 부분으로 구성됍니다. > (4) 마지막으로 서버는 JWT 토큰을 응답으로 전송하고 > (5) 클라이언트는 LocalStorage, SessionStorage, ReduxPersist 등 클라이언트측 Storage 에 저장합니다 -![인증된 사용자 요청](./img/authentication-authorization/jwt-2.png) +![인증된 사용자 요청](./img/jwt-2.png) > 이후 인증이 필요한 API 를 요청하면... > (1) 클라이언트에서 요청시, HTTP Header 의 Authorization 필드에 JWT 토큰을 삽입해 요청합니다. @@ -143,7 +143,7 @@ Access Token, Refresh Token 을 이용하여 인증 인가를 구현합니다. 두 토큰 모두 JWT 기반의 토큰이지만, Refresh Token 은 Access Token 을 재발급 받는 용도로 사용합니다.
자주 사용되는 Access Token 은 유효기간을 짧게 하여 Token 이 탈취돼도 탈취자가 오래 사용하지 못하도록 방지할 수 있습니다. -![Access, Refresh Token](./img/authentication-authorization/jwt-access-refresh.png) +![Access, Refresh Token](./img/jwt-access-refresh.png) # CSRF (Cross-Site Request Forgery) @@ -160,7 +160,7 @@ CSRF 공격이 진행되려면 다음 두 조건을 만족해야 합니다. 이해를 돕기위해 사용자가 A 에게 송금하는 상황을 가정해보겠습니다. -![CSRF 공격](./img/authentication-authorization/csrf.png) +![CSRF 공격](./img/csrf.png) 사용자는 로그인 되어있는 상태이기 때문에, Session ID, Token 을 탈취해 조작된 요청을 보낼 수 있습니다. @@ -171,7 +171,7 @@ CSRF 공격이 진행되려면 다음 두 조건을 만족해야 합니다. Referer 검증은 Request 를 보내는 Referer 가 일치하는지 검사하는 방법입니다.
Referer 헤더는 HTTP 요청의 일부로 전송되는 헤더로, 요청을 보내는 웹 페이지의 출처를 가지고 있습니다. -![Referer 검증](./img/authentication-authorization/csrf-defend.png) +![Referer 검증](./img/csrf-defend.png) Referer 헤더를 분석하여, 요청이 어디서 왔는지 확인하고, 다른 도메인에서의 요청을 제한하거나 보안을 강화할 수 있습니다. diff --git a/contents/posts/Web/img/browser-rendering-in-depth/chrome-browser-rendering.svg b/contents/posts/Web/browser-rendering-in-depth/img/chrome-browser-rendering.svg similarity index 100% rename from contents/posts/Web/img/browser-rendering-in-depth/chrome-browser-rendering.svg rename to contents/posts/Web/browser-rendering-in-depth/img/chrome-browser-rendering.svg diff --git a/contents/posts/Web/browser-rendering-in-depth.md b/contents/posts/Web/browser-rendering-in-depth/index.md similarity index 96% rename from contents/posts/Web/browser-rendering-in-depth.md rename to contents/posts/Web/browser-rendering-in-depth/index.md index 2d8be3f..7412bf4 100644 --- a/contents/posts/Web/browser-rendering-in-depth.md +++ b/contents/posts/Web/browser-rendering-in-depth/index.md @@ -12,7 +12,7 @@ head: ## 🎨 그림으로 한눈에 보는 브라우저 렌더링과정 - + ## ✍️ 참고자료 diff --git a/contents/posts/Web/css-cascade-algorithm.md b/contents/posts/Web/css-cascade-algorithm/index.md similarity index 100% rename from contents/posts/Web/css-cascade-algorithm.md rename to contents/posts/Web/css-cascade-algorithm/index.md diff --git a/contents/posts/Web/img/image-format/image-1.jpeg b/contents/posts/Web/image-format/img/image-1.jpeg similarity index 100% rename from contents/posts/Web/img/image-format/image-1.jpeg rename to contents/posts/Web/image-format/img/image-1.jpeg diff --git a/contents/posts/Web/img/image-format/image-1.png b/contents/posts/Web/image-format/img/image-1.png similarity index 100% rename from contents/posts/Web/img/image-format/image-1.png rename to contents/posts/Web/image-format/img/image-1.png diff --git a/contents/posts/Web/img/image-format/image-1.webp b/contents/posts/Web/image-format/img/image-1.webp similarity index 100% rename from contents/posts/Web/img/image-format/image-1.webp rename to contents/posts/Web/image-format/img/image-1.webp diff --git a/contents/posts/Web/img/image-format/image-2.jpeg b/contents/posts/Web/image-format/img/image-2.jpeg similarity index 100% rename from contents/posts/Web/img/image-format/image-2.jpeg rename to contents/posts/Web/image-format/img/image-2.jpeg diff --git a/contents/posts/Web/img/image-format/image-2.png b/contents/posts/Web/image-format/img/image-2.png similarity index 100% rename from contents/posts/Web/img/image-format/image-2.png rename to contents/posts/Web/image-format/img/image-2.png diff --git a/contents/posts/Web/img/image-format/image-2.webp b/contents/posts/Web/image-format/img/image-2.webp similarity index 100% rename from contents/posts/Web/img/image-format/image-2.webp rename to contents/posts/Web/image-format/img/image-2.webp diff --git a/contents/posts/Web/img/image-format/image-3.jpeg b/contents/posts/Web/image-format/img/image-3.jpeg similarity index 100% rename from contents/posts/Web/img/image-format/image-3.jpeg rename to contents/posts/Web/image-format/img/image-3.jpeg diff --git a/contents/posts/Web/img/image-format/image-3.png b/contents/posts/Web/image-format/img/image-3.png similarity index 100% rename from contents/posts/Web/img/image-format/image-3.png rename to contents/posts/Web/image-format/img/image-3.png diff --git a/contents/posts/Web/img/image-format/image-3.webp b/contents/posts/Web/image-format/img/image-3.webp similarity index 100% rename from contents/posts/Web/img/image-format/image-3.webp rename to contents/posts/Web/image-format/img/image-3.webp diff --git a/contents/posts/Web/img/image-format/image-4.gif b/contents/posts/Web/image-format/img/image-4.gif similarity index 100% rename from contents/posts/Web/img/image-format/image-4.gif rename to contents/posts/Web/image-format/img/image-4.gif diff --git a/contents/posts/Web/img/image-format/image-5.jpeg b/contents/posts/Web/image-format/img/image-5.jpeg similarity index 100% rename from contents/posts/Web/img/image-format/image-5.jpeg rename to contents/posts/Web/image-format/img/image-5.jpeg diff --git a/contents/posts/Web/img/image-format/image-5.png b/contents/posts/Web/image-format/img/image-5.png similarity index 100% rename from contents/posts/Web/img/image-format/image-5.png rename to contents/posts/Web/image-format/img/image-5.png diff --git a/contents/posts/Web/img/image-format/image-5.webp b/contents/posts/Web/image-format/img/image-5.webp similarity index 100% rename from contents/posts/Web/img/image-format/image-5.webp rename to contents/posts/Web/image-format/img/image-5.webp diff --git a/contents/posts/Web/img/image-format/image-6.jpeg b/contents/posts/Web/image-format/img/image-6.jpeg similarity index 100% rename from contents/posts/Web/img/image-format/image-6.jpeg rename to contents/posts/Web/image-format/img/image-6.jpeg diff --git a/contents/posts/Web/img/image-format/image-6.png b/contents/posts/Web/image-format/img/image-6.png similarity index 100% rename from contents/posts/Web/img/image-format/image-6.png rename to contents/posts/Web/image-format/img/image-6.png diff --git a/contents/posts/Web/img/image-format/image-6.webp b/contents/posts/Web/image-format/img/image-6.webp similarity index 100% rename from contents/posts/Web/img/image-format/image-6.webp rename to contents/posts/Web/image-format/img/image-6.webp diff --git a/contents/posts/Web/img/image-format/image-7.jpeg b/contents/posts/Web/image-format/img/image-7.jpeg similarity index 100% rename from contents/posts/Web/img/image-format/image-7.jpeg rename to contents/posts/Web/image-format/img/image-7.jpeg diff --git a/contents/posts/Web/img/image-format/image-7.png b/contents/posts/Web/image-format/img/image-7.png similarity index 100% rename from contents/posts/Web/img/image-format/image-7.png rename to contents/posts/Web/image-format/img/image-7.png diff --git a/contents/posts/Web/img/image-format/image-7.webp b/contents/posts/Web/image-format/img/image-7.webp similarity index 100% rename from contents/posts/Web/img/image-format/image-7.webp rename to contents/posts/Web/image-format/img/image-7.webp diff --git a/contents/posts/Web/image-format.md b/contents/posts/Web/image-format/index.md similarity index 96% rename from contents/posts/Web/image-format.md rename to contents/posts/Web/image-format/index.md index 056464e..25e5db5 100644 --- a/contents/posts/Web/image-format.md +++ b/contents/posts/Web/image-format/index.md @@ -18,7 +18,7 @@ comment: true 그리고 그 결과는?
- +
웬 삐에로가 나타나서 **_"응~ 이미지 그딴식으로 처리해봐~ 브라우저 뻗으면 그만이야"_** 라고 말하는게 아니겠습니까? @@ -34,7 +34,7 @@ comment: true
- https://almanac.httparchive.org/en/2022/page-weight + https://almanac.httparchive.org/en/2022/page-weight
출처 : https://almanac.httparchive.org/en/2022/page-weight
@@ -45,7 +45,7 @@ comment: true 저는 졸업전시 웹사이트에서 이걸 무시했다가 모바일 크롬이 뻗어버리는 참사를 겪었습니다
- +
이미지 포맷 하나만 잘 골라도, 로딩속도, UX 심지어 Core Web Vitals 점수까지 확 달라집니다 @@ -65,7 +65,7 @@ JPEG는 웹에서 수십년간 사골처럼 우려먹은 이미지 포맷입니
- https://web.dev/learn/images/jpeg?hl=ko + https://web.dev/learn/images/jpeg?hl=ko
출처 : https://web.dev/learn/images/jpeg?hl=ko
@@ -106,10 +106,10 @@ Progressive JPEG 는 이미지를 여러 번의 Scan (Pass) 를 통해 점진적 #### (1) AWS Lambda (Node.js) + Sharp 로 이미지 업로드 시점에 변환하기 -![alt text](./img/image-format/image-5.png) +![alt text](./img/image-5.png) AWS Lambda 에서 S3 트리거 이벤트를 사용하면 이미지 업로드 시점에 자동으로 Progressive JPEG 로 변환할 수 있습니다 -([관련 글 : AWS Lambda & S3 트리거로 이미지 최적화 자동화하기](../Aws/lambda-image-optimization.md)) +([관련 글 : AWS Lambda & S3 트리거로 이미지 최적화 자동화하기](../../Aws/lambda-image-optimization/index.md))
@@ -221,7 +221,7 @@ JPEG 대비 50% 이상, WebP 대비 20~30% 더 작은 파일 크기로 압축할 특히 Internet Explorer (IE) 는 AVIF/WebP 를 전혀 지원하지 않기 때문에, AVIF/WebP 만 사용하는 것은 위험할 수 있습니다 -![뭐? 어떤 브라우저 하나를 조심하라고? - 네, IE 는 위험합니다](./img/image-format/image-7.png) +![뭐? 어떤 브라우저 하나를 조심하라고? - 네, IE 는 위험합니다](./img/image-7.png) 그래서, AVIF/WebP 를 사용하되, 브라우저가 WebP 를 지원하지 않는 경우에는 JPEG 나 PNG 같은 대체 포맷을 제공하는 것이 좋습니다 @@ -303,7 +303,7 @@ export const Picture = ({ srcAvif, srcWebp, srcFallback, alt, ...imgProps }: Pic > "가능하면 단일 포맷에 올인하지 말고, 사용자 환경에 맞는 최적의 조합을 제공하자!" 입니다. -[다음 편에서는 실제 React 환경에서 이미지 지연로딩과 같은 최적화 기법을 적용하는 방법에 대해 알아보겠습니다](./image-optimization.md) +[다음 편에서는 실제 React 환경에서 이미지 지연로딩과 같은 최적화 기법을 적용하는 방법에 대해 알아보겠습니다](../image-optimization/index.md) ## 참고 자료 diff --git a/contents/posts/Web/image-optimization.md b/contents/posts/Web/image-optimization/index.md similarity index 100% rename from contents/posts/Web/image-optimization.md rename to contents/posts/Web/image-optimization/index.md diff --git a/contents/posts/Web/network-rest-api.md b/contents/posts/Web/network-rest-api/index.md similarity index 100% rename from contents/posts/Web/network-rest-api.md rename to contents/posts/Web/network-rest-api/index.md diff --git a/contents/posts/Web/img/trolley-dilemma-compatibility/trolley.jpeg b/contents/posts/Web/trolley-dilemma-compatibility/img/trolley.jpeg similarity index 100% rename from contents/posts/Web/img/trolley-dilemma-compatibility/trolley.jpeg rename to contents/posts/Web/trolley-dilemma-compatibility/img/trolley.jpeg diff --git a/contents/posts/Web/img/trolley-dilemma-compatibility/trolley.jpg b/contents/posts/Web/trolley-dilemma-compatibility/img/trolley.jpg similarity index 100% rename from contents/posts/Web/img/trolley-dilemma-compatibility/trolley.jpg rename to contents/posts/Web/trolley-dilemma-compatibility/img/trolley.jpg diff --git a/contents/posts/Web/img/trolley-dilemma-compatibility/trolley.webp b/contents/posts/Web/trolley-dilemma-compatibility/img/trolley.webp similarity index 100% rename from contents/posts/Web/img/trolley-dilemma-compatibility/trolley.webp rename to contents/posts/Web/trolley-dilemma-compatibility/img/trolley.webp diff --git a/contents/posts/Web/trolley-dilemma-compatibility.md b/contents/posts/Web/trolley-dilemma-compatibility/index.md similarity index 97% rename from contents/posts/Web/trolley-dilemma-compatibility.md rename to contents/posts/Web/trolley-dilemma-compatibility/index.md index 48280a9..8bde7fc 100644 --- a/contents/posts/Web/trolley-dilemma-compatibility.md +++ b/contents/posts/Web/trolley-dilemma-compatibility/index.md @@ -18,7 +18,7 @@ comment: true 웹 개발도 마찬가지 -![트롤리 딜레마와 웹 호환성](./img/trolley-dilemma-compatibility/trolley.jpg) +![트롤리 딜레마와 웹 호환성](./img/trolley.jpg) [Can I Use](https://caniuse.com/) 같은 사이트를 보면 대부분 브라우저는 최신 기능을 지원하지만, 소수의 **IE나 Safari 구버전**은 지원하지 않는 경우가 많음 diff --git a/data/posts.json b/data/posts.json index 5b807d0..04f5029 100644 --- a/data/posts.json +++ b/data/posts.json @@ -1,4 +1,13 @@ [ + { + "url": "/posts/React/constellation-impl", + "frontmatter": { + "title": "정적 좌표 지옥에서 탈출한 동적 별자리 노드 시스템 구축기", + "createdAt": "2026-03-02", + "category": "React", + "description": "누비랩 냠냠플러스 \"오늘찰칵\" 서비스의 별자리 맵 시스템을 하드코딩된 좌표 대신 기하학 알고리즘과 Render Props 패턴으로 해결하며 유지보수성과 확장성을 확보한 경험을 공유합니다." + } + }, { "url": "/posts/React/storybook-mcp", "frontmatter": { @@ -35,15 +44,6 @@ "description": "재귀함수를 활용하여 순열(Permutation) 을 구현하는 방법에 대해 알아봅니다. SWAP 기반 방식과 DFS 기반 방식을 비교해봅니다." } }, - { - "url": "/posts/CS/DataStructure/js-heap", - "frontmatter": { - "title": "JavaScript 로 구현하는 Heap 자료구조", - "createdAt": "2025-12-22T00:00:00.000Z", - "category": "CS", - "description": "Heap(힙) 자료구조는 우선순위 큐를 구현하는 데 자주 사용됩니다. 이 글에서는 JavaScript로 최소 힙(Min-Heap)과 최대 힙(Max-Heap)을 구현하는 방법을 단계별로 설명합니다." - } - }, { "url": "/posts/Etc/overcoming-difficult-times", "frontmatter": { @@ -80,15 +80,6 @@ "description": "Server Sent Events (SSE) 를 외부에서도 순차적으로 어떻게 다룰수 있을까? 종합설계프로젝트를 진행하면서 LLM으로부터 스트리밍 응답을 깔끔하게 처리하기 위해 Generator 를 활용한 방법을 공유합니다." } }, - { - "url": "/posts/Web/browser-coordinate", - "frontmatter": { - "title": "브라우저의 좌표계는 어떻게 계산될까 ? (feat. DOMMatrix, 변환 행렬)", - "createdAt": "2025-11-22T00:00:00.000Z", - "category": "Web", - "description": "브라우저에서 좌표계가 어떻게 계산되는지, DOMMatrix와 변환 행렬을 중심으로 설명합니다. translate, rotate, scale 에 따라 Viewport, Local 좌표계가 어떻게 계산되는지 알아봅니다." - } - }, { "url": "/posts/Etc/kakao-tech-campus-record", "frontmatter": { @@ -107,15 +98,6 @@ "description": "이 글은 Mark Erikson의 \"Why React Context is Not a 'State Management' Tool (and Why It Doesn't Replace Redux)\" 을 기반으로 번역 및 보완한 글입니다. 저작권은 원문 저자에게 있습니다. 다소 의역이 포함되어 있을 수 있습니다." } }, - { - "url": "/posts/React/redux-create-entity-adapter", - "frontmatter": { - "title": "[ReduxToolkit 공식문서 번역] createEntityAdapter", - "createdAt": "2025-11-12T00:00:00.000Z", - "category": "React", - "description": "Redux Toolkit의 createEntityAdapter는 전역 상태 관리를 위한 효율적인 방법을 제공합니다. 이 포스트에서는 createEntityAdapter의 개념과 사용법, 그리고 이를 활용한 전역 상태 관리 방법에 대해 알아봅니다." - } - }, { "url": "/posts/React/solid-render-props", "frontmatter": { @@ -152,15 +134,6 @@ "description": "오픈소스를 보다보면 Isomorphic 이라는 단어를 마주치게 됩니다. Isomorphic 이란 무엇인지, 그리고 어떨때 사용하는 네이밍인지에 대해 알아봅니다. 또 리액트에서 자주 사용되는 useIsomorphicEffect 훅도 함께 살펴봅니다." } }, - { - "url": "/posts/Web/critical-rendering-path", - "frontmatter": { - "title": "Web Vitals 과 브라우저의 렌더링 파이프라인 Deep Dive", - "createdAt": "2025-10-28T00:00:00.000Z", - "category": "Web", - "description": "웹 브라우저가 HTML, CSS, JS 파일을 어떻게 처리하여 화면에 렌더링하는지, 그리고 Web Vitals가 무엇인지에 대해 설명합니다. 추가적으로 이미지, 폰트, HTTP 요청은 언제 발생하며 이에 따라 Web Vitals 지표가 어떻게 변화하는지 알아봅니다" - } - }, { "url": "/posts/CS/DataStructure/idempotency-hash-table", "frontmatter": { @@ -179,15 +152,6 @@ "description": "불변성(Immutability) 는 개발 공부를 하다 보면 정말 자주 듣는 단어다. 값을 바꾸지 않는다는 말은 이해되지만, 자바스크립트에서 그게 어떻게 동작하는지, 그리고 왜 React 에서는 꼭 지켜야 하는지 알아보자." } }, - { - "url": "/posts/Web/indexed-db", - "frontmatter": { - "title": "IndexedDB 를 TypeOrm 처럼 사용하기", - "createdAt": "2025-10-07T00:00:00.000Z", - "category": "Web", - "description": "IndexedDB 는 브라우저 내장 데이터베이스로, 대용량 데이터를 클라이언트에 저장할 수 있습니다. 이 글에서는 TypeOrm 스타일의 추상화를 통해 IndexedDB 를 더 쉽게 사용하는 방법을 소개합니다." - } - }, { "url": "/posts/React/build-react-1", "frontmatter": { diff --git a/package.json b/package.json index 5720863..ee85d9e 100644 --- a/package.json +++ b/package.json @@ -18,5 +18,6 @@ "@giscus/vue": "^3.1.1", "katex": "^0.16.25", "markdown-it-katex": "^2.0.3" - } + }, + "version": "0.0.0" } diff --git a/scripts/generate-posts.mjs b/scripts/generate-posts.mjs index 01b33ea..23d3d46 100644 --- a/scripts/generate-posts.mjs +++ b/scripts/generate-posts.mjs @@ -60,15 +60,25 @@ function createPostObject(frontmatter, filePath, urlPrefix) { * @returns {Promise} - 포스트 객체 또는 null */ async function processMarkdownFile(filePath, fileName, urlPrefix) { - // index.md 파일은 제외 - if (fileName === "index.md") return null; - const frontmatter = await readMarkdownFile(filePath); if (!frontmatter || !isValidPostData(frontmatter)) { return null; } - return createPostObject(frontmatter, filePath, urlPrefix); + // 파일명이 index.md인 경우 상위 디렉토리 이름을 URL로 사용 + const url = fileName === "index.md" + ? urlPrefix + : `${urlPrefix}/${basename(filePath, extname(filePath))}`; + + return { + url, + frontmatter: { + title: frontmatter.title, + createdAt: frontmatter.createdAt, + category: frontmatter.category, + description: frontmatter.description, + }, + }; } /** diff --git a/scripts/re-migrate.mjs b/scripts/re-migrate.mjs new file mode 100644 index 0000000..2c226f8 --- /dev/null +++ b/scripts/re-migrate.mjs @@ -0,0 +1,86 @@ +import fs from 'fs'; +import path from 'path'; + +const postsRoot = path.join(process.cwd(), 'contents/posts'); + +async function migrateAll() { + const categories = fs.readdirSync(postsRoot, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory()) + .map(dirent => dirent.name); + + for (const category of categories) { + const categoryPath = path.join(postsRoot, category); + + // 1. 카테고리 루트에 있는 마크다운 파일 이동 (아직 이동 안 된 것들) + const files = fs.readdirSync(categoryPath, { withFileTypes: true }); + for (const file of files) { + if (file.isFile() && file.name.endsWith('.md') && file.name !== 'index.md') { + const postName = path.basename(file.name, '.md'); + const postDirPath = path.join(categoryPath, postName); + if (!fs.existsSync(postDirPath)) fs.mkdirSync(postDirPath); + fs.renameSync(path.join(categoryPath, file.name), path.join(postDirPath, 'index.md')); + } + } + + // 2. 포스트별 이미지 이동 및 경로 수정 + const postDirs = fs.readdirSync(categoryPath, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory() && dirent.name !== 'img') + .map(dirent => dirent.name); + + for (const postDir of postDirs) { + const postDirPath = path.join(categoryPath, postDir); + const indexPath = path.join(postDirPath, 'index.md'); + if (!fs.existsSync(indexPath)) continue; + + let content = fs.readFileSync(indexPath, 'utf-8'); + + // ![...](./img/some-folder/...) 형태 찾기 + const imgPattern = /!\[.*?\]\(\.\/img\/(.*?)\/.*?\)/g; + const matches = [...content.matchAll(imgPattern)]; + + if (matches.length > 0) { + const imgFolderName = matches[0][1]; + const oldImgDirPath = path.join(categoryPath, 'img', imgFolderName); + const newImgDirPath = path.join(postDirPath, 'img'); + + console.log(`Processing: ${category}/${postDir} (img folder: ${imgFolderName})`); + + if (fs.existsSync(oldImgDirPath)) { + if (!fs.existsSync(newImgDirPath)) fs.mkdirSync(newImgDirPath); + const images = fs.readdirSync(oldImgDirPath); + for (const img of images) { + fs.renameSync(path.join(oldImgDirPath, img), path.join(newImgDirPath, img)); + } + try { fs.rmdirSync(oldImgDirPath); } catch (e) {} + } + + // 경로 수정: ./img/folder/ -> ./img/ + const replacePattern = new RegExp(`\./img/${imgFolderName}/`, 'g'); + content = content.replace(replacePattern, './img/'); + fs.writeFileSync(indexPath, content, 'utf-8'); + } else { + // 이미 ./img/로 되어 있는 경우 (이미 이미지가 옮겨졌을 수도 있음) + const newImgDirPath = path.join(postDirPath, 'img'); + // 만약 포스트 폴더 바로 밑에 img가 없는데, 카테고리 밑 img 폴더 이름이 포스트 이름과 같다면? + const guessedOldImgDir = path.join(categoryPath, 'img', postDir); + if (fs.existsSync(guessedOldImgDir) && !fs.existsSync(newImgDirPath)) { + console.log(`Guessing img folder for ${postDir}: ${postDir}`); + fs.mkdirSync(newImgDirPath); + const images = fs.readdirSync(guessedOldImgDir); + for (const img of images) { + fs.renameSync(path.join(guessedOldImgDir, img), path.join(newImgDirPath, img)); + } + try { fs.rmdirSync(guessedOldImgDir); } catch (e) {} + } + } + } + + // 3. 남은 img 폴더 정리 (비어 있는 경우만) + const catImgDir = path.join(categoryPath, 'img'); + if (fs.existsSync(catImgDir) && fs.readdirSync(catImgDir).length === 0) { + fs.rmdirSync(catImgDir); + } + } +} + +migrateAll().catch(console.error);