Node.js 실행 흐름과 이벤트 루프 단계 정리

개요 Node.js가 스크립트를 실행할 때 어떤 구성요소가 어떤 순서로 초기화되고 동작하는지 정리 바이너리 기동부터 모듈 로딩, V8 파싱과 실행, 이벤트 루프와 비동기 작업 처리까지의 전체 흐름을 개발자 관점에서 간결하게 설명 핵심 개념 V8 엔진, Ignition 바이트코드와 JIT 최적화 libuv, 비동기 I O 백엔드와 이벤트 루프 단계 모듈 시스템, CommonJS와 ES Module의 로딩 차이 전역 실행 컨텍스트와 런타임 내장 객체 마이크로태스크 큐와 process.nextTick의 우선순위 실행 순서 요약 Node 바이너리 시작 런타임 초기화와 내부 바인딩 준비 모듈 로더 기동 및 엔트리 파일 로드 V8 파싱과 바이트코드 컴파일 전역 실행 컨텍스트 구성과 최상위 코드 실행 비동기 작업 등록 이벤트 루프 진입 비동기 콜백 처리 반복 graph TD A[Node 시작] --> B[V8, libuv 초기화] B --> C[모듈 로딩] C --> D[파싱 및 컴파일] D --> E[최상위 코드 실행] E --> F[이벤트 루프] F --> G[비동기 처리 반복]단계별 동작 1단계 Node 바이너리 시작 node yourfile.js 실행으로 C++ 엔트리 포인트가 기동됨 V8, libuv, 내부 바인딩 계층이 초기화되고 런타임 전역 상태가 준비됨 ...

November 11, 2025

DI가 결합도를 낮추는 원리와 최소 예시

개념/배경 DI(Dependency Injection, 의존성 주입)의 핵심 아이디어는 명확함 객체가 자신이 사용할 의존 객체를 스스로 생성하지 않고, 외부로부터 전달받아 사용하는 것임 이 단순한 설계 변경만으로도 코드의 변경 용이성, 테스트 편의성, 그리고 전체 시스템의 확장성에서 거대한 차이가 발생함 문제 상황: 강한 결합 (Tight Coupling) 전형적인 문제 패턴은 클래스 내부에서 다른 구체적인 클래스(Concrete Class)를 new 키워드로 직접 생성하여 사용하는 것임 의존 대상의 구현이 변경되면, 해당 객체를 사용하는 클래스 내부 코드도 반드시 함께 수정해야 함 단위 테스트(Unit Test)를 작성할 때, 테스트 대상 객체가 의존하는 실제 객체들까지 모두 함께 엮여 들어와 테스트가 복잡하고 무거워짐 예를 들어 Gamer가 BlueSwitchKeyboard를 직접 생성해 사용한다면, Gamer는 BlueSwitchKeyboard라는 구체적인 구현에 영구적으로 고정됨 만약 키보드 종류를 RedSwitchSilentKeyboard로 바꾸려면 Gamer 클래스의 내부 코드를 직접 수정해야 함 이 상태를 결합도가 높다고 부름 ...

November 9, 2025

KISS 원리: 소프트웨어 설계에서 불필요한 복잡성 줄이기

개요 KISS는 Keep It Simple, Stupid 또는 Keep It Simple and Straightforward의 약자이며 1960년대 미 해군에서 출발한 설계 원칙입니다. 소프트웨어에서는 불필요한 복잡성을 제거하고 이해와 변경이 쉬운 구조를 지향합니다. 목표는 적은 개념과 짧은 경로로 같은 가치를 제공하는 시스템을 만드는 것임 핵심 개념 단순함 추구: 필요 최소의 개념, 규칙, 구성 요소 유지 이해 용이성: 읽고 추론하기 쉬운 흐름과 명명 유지보수 용이성: 응집도 높이고 결합도 낮춰 변경 영향 최소화 적용 방법 처음부터 모든 시나리오를 포괄하려 하지 말고 현재 요구에 맞춘 최소 기능으로 시작 큰 만능 모듈 대신 작고 역할이 분리된 구성으로 나누기 공개 인터페이스를 최소화하고 기본값을 합리적으로 설계 데이터 흐름을 단방향으로 단순화하고 예외 경로는 명시적으로 처리 관련 원칙 DRY: 중복 제거로 변경 비용과 오류 가능성 감소 YAGNI: 지금 필요 없는 기능은 만들지 않음 간단 예시 모든 옵션을 받는 doSomething(config) 하나로 처리하려는 유혹을 경계. 대신 doSimpleA, doSimpleB처럼 명확한 역할의 작은 함수로 분리하고 기본 동작을 안전하게 설계함. 설정이 꼭 필요할 때만 제한된 형태로 노출 ...

November 3, 2025

TypeScript Parameters 유틸리티 타입 개념과 안전한 활용

개념/배경 Parameters는 TypeScript가 제공하는 제네릭 유틸리티 타입으로, 특정 함수 타입의 매개변수 타입들을 튜플로 추출하는 데 사용됨 함수 래핑, 고차 함수, 어댑터 계층에서 기존 함수 시그니처를 재사용해 타입 안정성을 유지하고 중복 선언을 줄이는 목적에 적합함 문법 type Parameters<T extends (...args: any) => any> = T extends ( ...args: infer P ) => any ? P : never; T가 함수 타입이면 매개변수 목록을 튜플 타입 P로 추출 T가 함수 타입이 아니면 never 반환 추출 결과는 튜플이므로 인덱스 접근, 스프레드, 부분 적용 등 튜플 연산과 조합 가능 사용 예시 기본 추출 ...

November 1, 2025

MySQL InnoDB 버퍼 풀 개념과 동작 원리, 크기 설정 가이드

개요 InnoDB 버퍼 풀은 데이터와 인덱스 페이지를 메모리에 캐싱하는 영역임 디스크 I/O를 획기적으로 줄여 지연 시간을 낮추는 게 목적임 InnoDB 스토리지 엔진(트랜잭션, MVCC, 행 단위 락 지원) 성능의 심장부라 할 수 있음 쉽게 말해, 자주 쓰는 데이터와 인덱스를 디스크 대신 메모리에 올려두고 처리하는 구조임 버퍼 풀 구성 요소 버퍼 풀에는 주로 이런 페이지(기본 16KB)가 올라옴 데이터 페이지: 실제 테이블 로우(Row)가 저장된 페이지 인덱스 페이지: B-Tree 인덱스 노드 페이지 (PK 및 세컨더리 인덱스 포함) 기타 관리 페이지: UNDO 페이지, 트랜잭션/MVCC 관리에 필요한 메타데이터 등 핵심 개념 페이지 캐싱 InnoDB는 디스크 데이터를 페이지 단위로 다룸 클라이언트가 특정 로우를 읽고 싶어 하면, 그 로우가 속한 페이지 전체를 버퍼 풀로 가져옴 이후 같은 페이지에 있는 다른 로우를 읽을 때는 디스크를 다시 보지 않고 버퍼 풀(메모리)에서 바로 조회함 ...

October 31, 2025

NestJS Swagger 가이드 — ApiProperty와 PickType/OmitType/PartialType 사용법

개요 @nestjs/swagger는 NestJS와 Swagger(OpenAPI) 스펙을 연결해 API 문서를 자동 생성하는 모듈임 DTO(Data Transfer Object) 클래스에 메타데이터를 부여해 타입과 예시, 설명 등을 Swagger UI에 노출하는 흐름으로 작동함 핵심 도구는 @ApiProperty와 DTO 유틸리티 타입들(PickType, OmitType, PartialType)임 ApiProperty 개념과 사용 @ApiProperty는 DTO 속성 단위로 문서화 메타데이터를 부여하는 데코레이터임 타입, 설명, 예시, 필수 여부 등을 정의해 Swagger UI에 명확한 스키마 제공 코드와 문서가 한 소스에서 유지되어 일관성 확보에 유리함 간단 사용 예시 class CreateUserDto { @ApiProperty({ description: "사용자 이름", example: "John Doe" }) name: string; }이 속성 정의만으로 Swagger 스키마에 name 필드의 설명과 예시가 노출됨 ...

October 30, 2025

Prisma cursor 기반 페이지네이션 동작 원리와 skip: 1의 의미

개요 Prisma에서 cursor는 특정 레코드 지점부터 결과를 읽기 시작하는 기준점으로 동작함 skip: 1은 해당 cursor 레코드를 결과에서 제외하기 위한 옵션으로, 페이지 간 중복을 제거하는 데 사용함 핵심 동작 cursor는 그 지점부터 시작 await prisma.user.findMany({ cursor: { id: 100 }, take: 5, orderBy: { id: "asc" }, }); // 결과: 100부터 시작해 5개 반환 skip: 1은 cursor에 해당하는 레코드를 건너뜀 await prisma.user.findMany({ cursor: { id: 100 }, skip: 1, take: 5, orderBy: { id: "asc" }, }); // 결과: 101부터 5개 반환 예시로 보는 차이 데이터가 아래와 같다고 가정 ...

October 29, 2025

Prisma findMany 가이드: where, select/include, 정렬·페이징, in/비교 연산자

개요 Prisma의 findMany는 다중 레코드 조회용 메서드 기본값은 대상 모델의 모든 레코드 반환 where 필터, select/include, 정렬, 페이징, 중복 제거 등 옵션 지원 옵션 조합으로 조건 기반 조회를 간결하게 구성 가능 기본 사용법 가장 단순한 호출 형태 const users = await prisma.user.findMany();주요 옵션 옵션은 필요한 것만 선택적으로 사용 where: 조건 필터링 select: 필드 서브셋 선택 include: 관계 데이터 로드 orderBy: 정렬 기준 지정 skip, take: 오프셋 기반 페이징 distinct: 특정 필드 기준 중복 제거 where로 조건 필터링 단일 조건부터 복합 조건까지 표현 가능 ...

October 28, 2025

JavaScript 함수는 왜 일급 객체인가 — 의미와 활용

개요 JavaScript에서 함수는 일급 객체로 취급됨 이는 함수가 값처럼 변수에 담기고, 인수로 전달되고, 반환값으로 나오며, 객체의 프로퍼티로 저장될 수 있음을 의미함 이 특성 덕분에 고차 함수, 콜백, 클로저, 함수 합성 같은 패턴이 자연스럽게 구현됨 핵심 개념 변수에 할당 가능 다른 함수의 인수로 전달 가능 다른 함수의 반환값으로 사용 가능 객체의 프로퍼티로 저장 가능 간단 예시 변수에 할당 const greet = (name) => `Hello, ${name}`;인수로 전달 const run = (fn, v) => fn(v); run(greet, "Bob");반환값으로 사용 및 클로저 const mul = (m) => (v) => v * m; mul(2)(5);객체 프로퍼티로 저장해 메서드 구성 ...

October 27, 2025

InnoDB에서 PK 없는 테이블의 동작과 트레이드오프

개념과 배경 InnoDB는 데이터를 클러스터형 인덱스 기준으로 저장하는 스토리지 엔진임 대부분의 테이블에서 이 클러스터형 인덱스는 프라이머리 키가 담당함 사용자가 명시적으로 PK를 정의하지 않은 경우에도 InnoDB는 테이블에 클러스터 키를 반드시 갖도록 함 이때 결정 규칙이 존재함 먼저 NOT NULL 제약을 가진 유니크 인덱스가 있으면 그것을 클러스터형 인덱스로 사용 그런 인덱스가 없으면 내부 6바이트 row_id를 생성해 숨김 PK로 사용 세컨더리 인덱스는 항상 클러스터 키를 포함하여 룩업을 수행함 따라서 명시적 PK가 없더라도 내부적으로는 클러스터 키가 존재하며 저장과 탐색 경로의 기준으로 동작함 ...

October 26, 2025