SQL Server nvarchar와 nchar 길이 단위 오해 바로잡기

개요 nvarchar와 nchar를 사용할 때 n이 곧 문자 개수라고 가정하는 경우가 많음 하지만 SQL Server에서 nchar(n), nvarchar(n)의 n은 문자 개수가 아니라 2바이트 단위의 길이, 즉 바이트 페어(byte-pair) 개수로 정의됨 문자 집합 범위에 따라 한 문자가 1개 혹은 2개의 바이트 페어를 사용할 수 있어 저장 가능한 문자의 실제 개수는 달라짐 핵심 개념과 정의 nchar(n), nvarchar(n)의 n은 0~4000 바이트 페어 범위의 길이 의미 하나의 바이트 페어는 2바이트로, 내부적으로 UTF-16 코드 유닛 단위로 이해 가능 유니코드 BMP 범위(0~65,535) 문자는 보통 1 바이트 페어 사용 보조 평면 범위(65,536~1,114,111) 문자는 서러게이트 페어로 2 바이트 페어 사용 따라서 n이 문자의 최대 개수를 보장하지 않음 char(n), varchar(n)은 n이 바이트 수 의미라는 점에서 유사한 맥락이나, nvarchar/nchar는 바이트 페어 기준이라는 차이 존재 추가 기본값 규칙 ...

February 9, 2026

JavaScript Array.prototype.reduce 개념과 안전한 활용 가이드

개요 Array.prototype.reduce는 배열을 하나의 값으로 축약하는 표준 API 배열의 각 요소에 대해 리듀서 함수를 순차 실행하고 누산기 값을 반환 집계, 변환, 그룹핑, 파이프라인 구성 등 다양한 패턴에 사용 구문 arr.reduce(callback[, initialValue]) callback에 누산 로직 정의 initialValue가 있으면 누산기의 시작값으로 사용, 없으면 배열의 첫 요소가 시작값 매개변수 callback(accumulator, currentValue, currentIndex, array) accumulator: 누산된 값 currentValue: 현재 요소 값 currentIndex: 현재 인덱스 array: 원본 배열 initialValue (옵션) 누산기의 초기값 제공하지 않으면 배열 첫 요소가 초기값이 되어 콜백은 두 번째 요소부터 시작 반환값 축약 결과로 얻은 최종 누산값 동작 방식 왼쪽에서 오른쪽으로 순회하며 callback을 한 번씩 호출 initialValue 미제공 빈 배열이면 TypeError 발생 요소가 하나뿐이면 그 요소를 그대로 반환하며 callback은 호출되지 않음 initialValue 제공 배열이 비어 있어도 initialValue를 그대로 반환하며 callback은 호출되지 않음 희소 배열의 빈 슬롯은 건너뜀 누산기는 어떤 타입도 가능하며 객체, 맵, 프라미스 등으로 확장 가능 주의 사항과 베스트 프랙티스 가능한 항상 initialValue 지정 권장 빈 배열 입력 시 예외 방지, 타입 안정성 확보 누산기 불변성 유지 권장 객체 누산 시 얕은 복사 또는 구조 분해 사용 고려 콜백은 순수 함수 지향 외부 상태 변경 최소화, 테스트 용이성 확보 읽기 어려운 과도한 축약 로직은 map, filter, for…of 등으로 분리 고려 희소 배열에서 빈 슬롯은 콜백이 호출되지 않음에 유의 오른쪽에서 왼쪽으로 처리해야 하면 reduceRight 사용 간단 예시 합계 계산 ...

February 8, 2026

class-transformer와 class-validator로 DTO 변환·검증 패턴 정리

개요 클라이언트에서 서버로 들어오는 요청 데이터를 DTO로 다루면 변환과 검증의 경계를 명확히 유지 가능함 class-transformer는 입력을 클래스 인스턴스로 변환하는 역할, class-validator는 변환된 인스턴스의 유효성 검증 역할 두 라이브러리를 함께 쓰면 DTO 레이어에서 데이터 정합성을 선제적으로 보장 가능함 핵심 개념 DTO 데이터 전송 객체, 외부 입력을 내부 도메인으로 들이기 전 구조와 제약을 고정하는 경계 class-transformer plain object ↔ 클래스 인스턴스 변환, 노출/제외 필드 제어 class-validator 데코레이터 기반 유효성 규칙 선언, 실행 시 검증 에러 수집 설치 npm install class-transformer class-validator사용 흐름과 최소 예시 입력 JSON 수신 → DTO 클래스로 변환 → DTO 인스턴스 검증 → 실패 시 에러 응답, 성공 시 비즈니스 로직으로 전달 import { Expose, Exclude, plainToInstance } from 'class-transformer' import { IsInt, IsString, validate } from 'class-validator' class UserDTO { @IsString() @Expose() name: string @IsInt() @Expose() age: number @Exclude() password?: string } const dto = plainToInstance(UserDTO, payload) const errors = await validate(dto) if (errors.length) { // 검증 실패 처리 }포인트 ...

February 7, 2026

TypeScript에서 declare function의 개념과 사용 시점

개요 TypeScript의 declare 키워드는 외부에서 이미 구현된 값의 타입 정보를 컴파일러에 알려주는 용도임 실제 구현은 다른 런타임 환경이나 스크립트에 존재하고, TypeScript는 타입 검사만 수행함 선언은 자바스크립트 코드로 출력되지 않음 핵심 개념 declare function: 외부에 존재하는 함수의 시그니처만 제공하는 선언 사용 위치: 주로 .d.ts 선언 파일, 필요 시 .ts에서도 가능하지만 빌드 결과물에는 코드가 생성되지 않음 목적: 컴파일 타임에 타입을 인지시켜 오류를 줄이고, IDE 보조 기능을 활성화함 언제 사용하나 타입 정보가 없는 외부 자바스크립트 라이브러리 사용 시 글로벌로 노출된 함수나 변수를 TypeScript가 모를 때 JS와 TS 혼용 프로젝트에서 점진적 마이그레이션을 진행할 때 예시 글로벌 함수 선언 // 이미 어딘가에서 구현된 전역 함수가 있다고 가정 // my-globals.d.ts declare function myGlobalFunction(msg: string): void이렇게 선언하면 TypeScript가 함수 존재와 시그니처를 인식함 ...

February 6, 2026

JavaScript 깊은 복사 vs 얕은 복사, structuredClone 사용 가이드

개요 값 복사에서 가장 흔한 실수는 얕은 복사와 깊은 복사의 차이를 간과하는 것임 이 글은 JSON 해킹이나 라이브러리 대신 브라우저와 런타임이 제공하는 structuredClone으로 깊은 복사를 안정적으로 수행하는 방법과 주의점을 정리함 얕은 복사 JavaScript의 전개 연산자 …로 만드는 복사는 기본적으로 얕은 복사임 겉 모양과 1단계 속성은 복제되지만 중첩된 객체는 동일 참조를 공유함 const myOriginal = { someProp: "with a string value", anotherProp: { withAnotherProp: 1, andAnotherProp: true } } const myShallowCopy = { ...myOriginal } myShallowCopy.aNewProp = "a new value" console.log(myOriginal.aNewProp) // ^ logs `undefined` myShallowCopy.anotherProp.aNewProp = "a new value" console.log(myOriginal.anotherProp.aNewProp) // ^ logs `a new value` 기본형 값은 값 자체가 복사되지만 객체 같은 참조형은 레퍼런스가 복사됨 따라서 중첩된 구조를 안전하게 분리하려면 깊은 복사가 필요함 ...

February 5, 2026

Ramda 핵심 개념 정리와 R.prop 안전한 속성 접근, 커링·조합·주의사항

개요 Ramda는 JavaScript와 TypeScript에서 함수형 프로그래밍을 실용적으로 적용하기 위한 유틸리티 모음집임 순수 함수, 불변성, 커링, 함수 조합을 일관된 인터페이스로 제공하며, 매개변수 순서를 함수 → 데이터로 통일해 조합과 부분 적용을 자연스럽게 만듦 이 글은 R.prop을 중심으로 Ramda 핵심 함수의 개념과 사용법, 타입 고려사항, 흔한 함정과 우회 전략을 정리함 R.prop 개념과 문법 목적과 동작 원리 객체의 특정 속성 값을 안전하게 조회하는 읽기 전용 도구 속성이 없거나 undefined일 수 있는 상황에서 런타임 예외 없이 undefined 반환 커링 지원으로 속성 이름을 고정해 재사용 가능한 픽커 함수 구성에 유리함 시그니처 ...

February 4, 2026

SWC로 TypeScript/JavaScript 빌드 가속하기 — Babel·tsc 대비 장점과 NestJS 적용 포인트

개요 SWC는 Rust로 작성된 초고속 TypeScript/JavaScript 컴파일러 겸 트랜스파일러 동일한 작업을 수행하는 Babel이나 tsc 대비 10~20배 수준의 성능 향상이 보고됨 Rust로 구현되어 JS 런타임 기반 도구 대비 낮은 오버헤드와 높은 병렬 처리 효율 확보 핵심 개념 목적 TS/JS 소스 코드를 목표 런타임에서 실행 가능한 코드로 빠르게 변환 특징 타입 체크 미포함, 변환에 집중해 극단적 속도 추구 적용 범위 컴파일 단계와 테스트 실행, 개발 서버 부팅, CI 빌드 가속에 유효 채택 사례 Next.js에 기본 통합됨, 서버 프레임워크에서도 선택지로 확산 중 ...

February 3, 2026

Vite 개요와 작동 원리 — ESM 기반 개발 서버, esbuild 프리번들, Rollup 빌드

개요 차세대 프론트엔드 빌드 도구 Vite 요약 Vue.js 창시자 Evan You가 만들었고, 개발 중 대기 시간을 줄이는 데 초점 맞춤 프랑스어로 vite는 빠름을 의미함 핵심 가치 개발 서버 즉시 기동에 가까운 체감 속도 HMR이 가볍고 빠르게 동작 의존성 프리번들을 esbuild로 처리해 개발 경험 가속 프로덕션 빌드는 Rollup으로 안정적 번들 생성 배경과 문제 기존 번들러(Webpack) 방식은 시작 시 전체 그래프를 사전 번들링하는 구조 프로젝트 규모가 커질수록 첫 기동이 지연 코드 변경 반영 또한 번들 재생성 비용으로 지연 발생 개발 체감 문제 ...

February 2, 2026

Vitest 완벽 가이드

개요 Vite 기반의 테스트 프레임워크 Vitest 소개 및 실무 사용 패턴 정리 Jest와 거의 동일한 API를 제공하고, Vite의 ESM/HMR을 활용해 빠른 재실행을 제공함 Vite 프로젝트에서는 최소 설정으로 바로 사용 가능 빠른 실행과 재실행, watch 효율 높음 Jest API 호환성 높아 러닝 커브 낮음 TypeScript 네이티브 지원 1. 기본 구조 테스트 파일 명명 규칙 *.spec.ts 또는 *.test.tsdescribe(name, fn) 관련 테스트를 그룹화하는 컨테이너 import { describe, it, expect } from 'vitest' describe('계산기', () => { it('두 수를 더한다', () => { expect(1 + 2).toBe(3) }) it('두 수를 뺀다', () => { expect(5 - 3).toBe(2) }) }) 첫 번째 인자: 그룹 이름 두 번째 인자: 테스트 콜백 중첩 describe 구성 가능 it(name, fn) / test(name, fn) 개별 테스트 케이스 정의, 두 API는 동일 동작 ...

February 1, 2026

class-transformer의 @Expose/@Exclude, @Type, plainToInstance, excludeExtraneousValues 정확히 이해하고 쓰기

개요 API DTO를 다룰 때 class-transformer의 @Expose, @Exclude, @Type와 plainToInstance, excludeExtraneousValues 옵션을 정확히 이해해야 데이터 노출 제어와 변환 일관성을 확보할 수 있음 아래는 개념 정의와 동작 방향, 자주 생기는 오해 정리 및 최소 예시 @Expose와 @Exclude 핵심 개념 @Expose: 변환 대상으로 명시적 노출 표시 @Exclude: 변환에서 제외 표시 기본 전략은 include-all에 가까움. 즉 아무 옵션 없이 변환하면 대부분의 필드가 그대로 따라옴. 진짜 필드 필터링을 원하면 @Exclude 사용 또는 excludeExtraneousValues 옵션과 함께 @Expose 사용 필요 동작 원리 ...

January 31, 2026