Curt Poem

프론트 엔드 공부와 지식 나눔을 위한 블로그

개발 67

워커를 더 효율적으로 사용하는 워커풀(Worker Pool) 개발기

이미지 처리 작업은 생각보다 리소스를 많이 소모합니다. 특히 사용자가 가지고 있는 고해상도 이미지를 썸네일로 변환하는 과정에서는, 성능뿐만 아니라 메모리 관리까지도 신경 써야 했습니다. 이러한 문제를 해결하기 위해 웹 워커(Web Worker)를 활용한 워커풀(Worker Pool) 클래스를 직접 설계하게 되었는데요, 이 글에서는 그 과정을 정리해보았습니다.워커를 사용하자이미지를 썸네일 크기로 전환하는 것은 아주 빠른 작업이긴 하지만 많은 이미지를 처리한다면 사용자와의 상호작용이 생각보다 오랜 시간 차단될 수 있습니다. 그래서 이미지 처리를 메인쓰레드에서 하는 대신 워커에 작업을 맡겨 메인 쓰레드의 부담을 줄이고 사용자의 상호작용을 차단하지 않게 만들 수 있습니다. 그래서 당연히 Web Worker를 사..

개발/JavaScript 2025.04.13

로그 출력을 깨끗하게 만드는 방법과 대화형 CLI 만들기

같은 줄에 로그 출력 갱신하기터미널에서 npm 패키지를 설치할 때 진행률(%)이 같은 줄에서 갱신되는 것을 본 적이 있을 것입니다. 이러한 방식은 진행률 표시, 로딩 상태 출력 등 실시간 정보를 효율적으로 전달하는 데 유용합니다.하지만 자바스크립트의 console 함수들은 기본적으로 줄바꿈이 포함되어 있으며 이전 줄을 갱신하는 방법도 없습니다. 과연 어떤 방식으로 이런 출력을 구현한 것일까요? Node.js에서는 console.log 대신 process.stdout.write()를 사용하여 같은 줄에 출력을 덮어쓸 수 있습니다. 이를 위해 캐리지 리턴 문자(\r)를 활용하여 커서를 줄의 시작으로 이동한 후 새로운 내용을 출력하면 됩니다.예제 코드const total = 100;let count = 0;c..

개발/기타 2025.03.30

자바스크립트와 멀티 쓰레드 3 - 다른 형태의 워커(사실 의미가 적은 글)

자 지금까지 다양한 종류의 워커를 알아보았습니다. 사실 Shared Worker와 Service Worker는 단순 추가적인 쓰레드를 활용한다기 보다는 특별한 종류의 작업을 처리하는 것에 더 가까운 것같습니다. 제목인 자바스크립트와 "멀티 쓰레드"와는 조금 맞지 않은 부분이 있습니다.(제목을 자바스크립트와 워커들 같은 식으로 지었어야했나봅니다.) 하지만 오늘 다룰 워커는 멀티 쓰레드라는 제목과 가까운 워커입니다. 바로 Dedicated Worker인데요. 한국말로 번역해 보자면 전용 워커 정도가 될 것입니다. Dedicated는 "헌식적인"이라는 뜻도 있지만 "특정한 목적을 위한"이라는 뜻도 있습니다. 그리고 Dedicated Worker는 이 뜻에 훨씬 잘 들어 맞죠. 그리고 별 다른 언급없이 워커를 ..

개발/JavaScript 2025.02.23

자바스크립트와 멀티 쓰레드 3 - Service Worker로 백그라운드에서 네트워크다루기

웹 애플리케이션에서 중요하게 여겨지는 점 중 하나는 네트워크 최적화입니다. 네트워크와 관련해서 다양한 요청을 캐싱하고, 캐싱한 데이터를 적절한 타이밍에 업데이트하고, 인터넷 연결이 불안정한 상황에서도 최소한의 확실한 동작을 보장하는 것이 중요한 문제입니다. AXIOS, Tanstack Query 등 네트워크와 관련한 다양한 라이브러리가 인기있는 이유이기도 합니다. 이번에는 백그라운드에서 네트워크 요청을 다루며, 다양하게 활용할 수 있는 Service Worekr에 대해 다루어보겠습니다. Service WorekrServie Workeer는 다른 Worker들과 마찬가지로 메인 쓰레드가 아닌 별도의 쓰레드에서 관리되는 Worker입니다. 특히, 네트워크 요청 가로채기(intercept), 요청 캐싱 등을 ..

개발/JavaScript 2025.02.08

자바스크립트와 멀티 쓰레드 2 - Shared Worker로 여러 탭과 창의 데이터를 공유하기(+추상화하여 메모리 관리하기)

Shared Worker와 Service Worker는 이전 글에서 언급하였듯이 데이터 공유와 비동기 작업을 효율적으로 처리하기 위해 제공되는 Web Worker의 확장된 인터페이스입니다. 두 Worker모두 메인 쓰레드와 분리되어 독립된 스레드에서 실행되며, 성능 최적화를 통한 사용자의 경험 향상을 위해 사용할 수 있습니다.Shared WorkerShared Worker는 동일한 출처(origin)에서 실행되는 여러 브라우저 탭, iframe, 또는 웹 애플리케이션 간에 공유될 수 있는 Worker입니다. 만약 브라우저의 서로 다른 탭(tab)이더라도 같은 출처를 가진다면 모두가 동일한 Worker에 접근 가능합니다. 그래서 만약 여러 개의 탭이나 윈도우 창이 켜져있더라도 모두 같은 데이터를 공유받거나..

개발/JavaScript 2025.01.28

자바스크립트와 멀티 쓰레드 1 - 자바스크립트가 싱글 쓰레드라고 불리는 이유와 Worker로 여러 개의 쓰레드 사용하기

자바스크립트는 싱글 쓰레드 언어로 널리 알려져 있습니다. 하지만 브라우저의 Web Worker, 노드의 Worker Thread를 활용하면 멀티 쓰레드 환경을 구현할 수 있습니다. 자바스크립트로 멀티 쓰레드 환경을 구현하는 방법을 알아보기 전에 멀티 쓰레드 환경을 구현할 수 있음에도 싱글 쓰레드 언어라고 소개하는 지 짚어보고 넘어가도록 하겠습니다.자바스크립트는 싱글 쓰레드 언어?자바스크립트의 기본 실행 환경은 단일 쓰레드 환경입니다. 즉, 자바스크립트는 하나의 호출 스택에서 한번의 하나의 작업이 처리된다는 뜻입니다. 이런 작업의 처리는 브라우저든, Node 환경이든 메인 이벤트 루프에서 관리되며 순차적으로 처리됩니다. DOM 조작, 이벤트 처리, UI 업데이트 등의 거의 모든 자바스크립트 동작은 메인 쓰..

개발/JavaScript 2025.01.11

개인적으로 느낀 Kotlin의 좋은 점과 애매한 점과 별로인 점(부제: 내가 느낀 최신 프로그래밍 언어의 경향들)

최근 취업을 하면서 안드로이드 개발자로 경력을 시작하게 되었습니다. 기존에는 자바스크립트(타입스크립트)와 리액트를 통한 웹 프론트엔드 개발을 공부해 왔었는데요. 코틀린은 2011년에 공개된 프로그래밍 언어로 최신 프로그래밍 언어라고 볼 수 있습니다. 최근에 만들어진 언어를 사용해 보면서 자바스크립트의 최신 라이브러리나 프레임 워크를 사용할 때와 비슷한 느낌을 받기도 하였고 특히 안드로이드 컴포즈를 사용하면서 더 많이 느껴진 점이 있습니다. 이런 점이 최근 개발 업계에서 전반적으로 추구하는 개발 방향이라고 느껴졌고 이 점을 한 번 정리해보고 싶어 글을 작성하게 되었습니다.요즘 언어들더 쉽게, 더 편하게최근 개발 경향성은 "더 쉽게, 더 편하게"라는 말로 요약할 수도 있겠다 싶을 정도로 간단하고 쉬워지는 것..

타입스크립트에서 타입을 직접 정의할 때 알고 있으면 좋은 제네릭들

타입스크립트를 사용할 때 타입을 조금 더 편하게 사용할 수 있는 팁들을 준비해보았습니다.Roll 타입으로 예쁘게 펼쳐보기type Roll = { [K in keyof T]: T[K];};// & {};Matt Pocock이 고안한 Roll이라는 타입은 네이버의 infer, never만 보면 두려워지는 당신을 위한 타입 추론에서 알게된 핵입니다. 다음과 같이 복잡한 타입을 사용하면 개발자는 해당 객체에 들어있는 타입이 정확히 무엇인지 확인하기 힘든데요. Roll을 이용하면 객체를 해부하여 볼 수 있게 됩니다.type A = { a: string; b: number; c: boolean;}type B = { d: boolean; e: number; f: string[];}t..

개발/TypeScript 2024.11.17

리액트의 context을 구현해보면서 context 최적화에 대해 알아보자

리액트의 context의 API는 Prop Drilling을 해결하기 위한 한 가지 방법으로 상위 컴포넌트에서 관리하는 상태를 자식 컴포넌트가 props을 받지 않고 해당 상태를 사용할 수 있게 만들어줍니다. 먼저 간단한 사용법을 알아보겠습니다.Context API의 사용방법context 만들기context api를 사용하기 위해 가장 먼저해야할 일은 context를 만드는 일입니다. 깊이 중첩되어 있는 자식에게 전달할 상태를 정하는 작업입니다.const MyContext = createContext({ count: 0, increase: () => { console.log("provide없음"); },});context의 생성은 위와 같이 아주 간단합니다. createContext함수에 전달..

리스트 렌더링과 컴포넌트 초기화에 활용되는 key prop.

리액트에서 리스트를 이용해 컴포넌트를 렌더링하도록 하면 key prop을 붙이는 것을 권장하고 있습니다. 만약 key를 사용하지 않으면 다음과 같은 에러를 콘솔에 출력하고 내부적으로는 인덱스를 key로 사용하게 됩니다.리액트에서 Key는 어떤 역할을 하길래 리스트의 렌더링에 필수적으로 사용하여야 할까요?리스트 항목을 순서대로 유지공식 문서에 따르면 리스트에서 key prop의 역할은 리스트 항목을 순서대로 유지하기 위해서입니다. key를 사용한다면 리스트의 각 요소를 식별하여 올바른 순서를 유지할 수 있도록 만듭니다. 그런데 리스트의 항목을 순서대로 유지한다는 것은 무슨 말일까요? 리스트라는 자료 구조 자체에서 이미 순서를 유지하기 때문에 key를 사용하지 않아도 순서는 유지되는 데 말입니다.key의 작..

자바스크립트 await는 이벤트 루프 내에서 어떻게 동작할까

지난 글에서 태스크 큐를 통해 자바스크립트의 코드 실행 순서를 알아보았습니다. 하지만 한 가지 의문점이 생겼는데요. Promise 객체는 마이크로 태스크 큐로 들어가지만 만약 await 키워드를 사용한다면 어떻게 될까요? 함수의 실행을 일시 정지하고 Promise가 resolve(혹은 reject) 될까지 기다린다는 사실은 알고 있을 겁니다. 하지만 이벤트 루프에서 어떻게 처리가 될까요? Promise가 fullfilled 혹은 rejected 될 때까지 이벤트 루프의 작동도 멈출까요?async / awaitasync와 await는 JavaScript에서 비동기 처리를 보다 읽기 쉽게 작성할 수 있도록 도와주는 문법입니다. 기본적으로 비동기 코드를 처리할 때 주로 Promise를 사용하게 되는데, asy..

개발/JavaScript 2024.10.23

동적 배열을 사용하는 자바스크립트에서 일어나는 일

최근 오픈소스에 기여를 하게 되었는데요. 그동안 번역 혹은 오역의 수정만 했지만 이번에는 코드를 수정한 것이 오픈소스 라이브러리에 반영되었습니다. 버그를 수정한 것은 아니고 성능을 향상시킨 수정이었는데요. 사실 정말 간단한 수정이었습니다. 배열을 만들 때, 새로운 빈 배열에 값을 계속 추가하는 방식에서 미리 배열의 크기를 정해놓고 인덱스에 맞게 값을 수정하는 방식이었습니다. 작은 수정이었지만 성능은 놀랍게도 약 47% 향상되었습니다.왜 이런 사소한 변화가 성능에 이토록 큰 영향을 주었을까요?동적 배열배열이란?배열과 같은 데이터 구조는 일반적으로 메모리에 순서대로, 연속해서 저장됩니다. 예를 들어 첫 번째 요소가 메모리의 주소 0x1000에 있다면, 배열의 두 번째 요소는 그 다음 메모리 주소(0x1000..

개발/JavaScript 2024.10.15

자바스크립트의 연산자 우선순위(feat. 이산수학 한 방울)

수학에서 여러 연산들이 복합적으로 사용될 때 연산자들 간에 우선 순위가 있는 것처럼 자바스크립트의 다양한 연산자들 사이에도 우선순위가 존재합니다. 이 우선 순위에 따라 연산자들이 평가되는 순서가 달라지게 됩니다. 사칙연산과 같은 경우는 수학과 일치하지만 다음과 같은 코드들의 결과를 예측하기는 쉽지 않습니다.let foo = {n: 1};let bar = foo;foo.x = foo = {n: 2};// foo와 bar의 값은?let i = 3;console.log(i++ + ++i * 2);// 출력 값은?let a = 10;let b = 20;a += b -= 5;// a, b 각각의 값은?let p = 5; // 0101 (2진수)let q = 3; // 0011 (2진수)console.log(p..

개발/JavaScript 2024.10.12

태스크큐를 중점으로 자바스크립트 코드의 실행 순서를 알아보자

자바스크립트 런타임은 콜 스택(Call Stack), 태스크 큐(Task Queue), 마이크로태스크 큐(Microtask Queue), 이벤트 루프(Event Loop)로 구성되어 있습니다. 이 이벤트 루프가 어떻게 동작하는지 잘 이해하고 있어야 최적화나 올바른 아키텍처 설계가 가능해집니다. 다음의 코드 실행 결과가 어떻게 될지 아시나요? console.log('Start');setTimeout(() => { console.log('setTimeout done');}, 0);Promise.resolve().then(() => { console.log('promise resolved');});console.log('End');정답은 다음과 같습니다.StartEndpromise resolvedsetTi..

개발/JavaScript 2024.09.25

타입스크립트 심층 분석 4 - 함수의 포함 관계는 뭔가 다르다. (공변성과 반공변성)

시리즈의 다른 글 보기 이전 글들에서 타입스크립트의 타입 간의 관계는 집합처럼 포함관계를 가진다고 설명했었습니다. 조금 더 전문적인 용어로 서브타이핑 혹은 덕타이핑 방식으로 타입을 판별하기 때문에 어떤 타입이 다른 타입의 요소를 모두 가지면 대체하여 사용하여도 문제가 없는 것으로 봅니다. 특히 서브타이핑의 방식으로 이해하면 서브 타입은 수퍼타입을 대체할 수 있습니다. 이대로 해석하면 어떤 타입이 들어갈 수 있는 자리에는 그 타입의 서브타입을 넣어도 아무 문제가 없어야 합니다. 하지만 다음과 같이 입력값 즉, 함수의 매게변수 사이에서는 더 구체적인 타입을 넣는 것이 허용되지 않습니다.Typescript Playground에서 보기interface Animal { name: string;}interface..

개발/TypeScript 2024.09.20

React에서 화면과 로직의 분리 도전기(with. context API)

지난 번 플러터를 사용하여 프로젝트를 진행하였을 때, MVVM패턴을 통해 화면과 로직이 분리되어 수정이 편하고 비즈니스 로직 또는 서버의 변화에 대한 대처가 용이하다고 느꼈습니다. 이번에는 화면과 로직을 분리하는 방식을 리액트에서도 적용하고 싶었지만 몇 가지 문제가 있었고 이를 어떻게 해결할지에 대한 고민을 정리한 글입니다. 사실 커스텀 훅을 사용하는 것이 더 나은 방법이지만 로직을 리액트에서 완전히 분리하여 독립적으로 사용하는 방법을 생각해보는 내용입니다. 즉 리액트로 작성되어 있지 않은 로직을 리액트 컴포넌트에서 그대로 사용할 수 있는 방법입니다.일단 코드만이라도 나누어보자간단한 이해를 위해 실제 분리가 아닌 코드를 나눌 뿐이므로 바쁘시다면 생략하고 실제로 화면과 로직 분리하기로 바로 넘어가주세요.로..

웹성능은 어떻게 개선할수 있을까요?

많은 개발자들의 성능 개선을 위해 자바스크립트의 코드를 개선하는 데 집중합니다. 하지만 웹 페이지의 성능에는 자바스크립트 뿐만 아니라 HTML, CSS, 파일의 크기, 네트워크 등 다양한 요소가 영향을 미칩니다. 물론 자바스크립트의 성능에 끼치는 영향이 다른 요소에 비해 큰 경우가 많지만 CSS 또한 분명히 성능에 영향을 끼칩니다. 오늘은 자바스크립트를 제외한 웹 성능을 개선할 때 신경 쓸만한 요소를 살펴보겠습니다.HTML 구조Dom의 깊이HTML 문서의 DOM(Document Object Model) 구조가 복잡하고 깊이가 깊을수록 브라우저가 문서를 렌더링하는 데 더 많은 시간을 소요하게 됩니다. 단순히 DOM에 포함된 HTML 요소의 개수도 영향을 끼치지만 그보다는 어떻게 배치되어 있는 지가 더 큰 ..

개발/기타 2024.09.02