최근 글
91개의 글RAG 제대로 이해하기 - LLM에 '내 지식'을 붙이는 법
LLM은 똑똑하지만 두 가지 약점이 있습니다. 모르는 걸 아는 척(할루시네이션) 하고, 학습 시점 이후의 최신 정보나 우리 회사 내부 문서를 모른다는 점입니다.이 둘을 가장 현실적으로 해결하는 방법이 RAG(Retrieval-Augmented Generation, 검색 증강 생성) 입니다.이 글에서는 RAG가 무엇이고, 어떤 흐름으로 동작하며, 실무에서 어
트랜스포머와 어텐션 - LLM은 어떻게 다음 단어를 예측할까
ChatGPT에게 질문하면 그럴듯한 문장이 술술 나옵니다. 그런데 그 내부를 들여다보면, LLM이 실제로 하는 일은 놀랍도록 단순합니다. "지금까지의 문장 다음에 올 단어를 확률적으로 고르는 것", 그게 전부입니다.이 단순한 예측을 무섭게 잘하게 만든 구조가 트랜스포머(Transformer) 이고, 그 심장이 어텐션(Attention) 입니다.이 글에서는
토큰과 토크나이저 - LLM이 글자를 읽는 방식
LLM API를 써보면 "토큰"이라는 단위를 자주 만납니다. 요금도 토큰으로 매기고, 컨텍스트 한도도 토큰으로 표시됩니다.그런데 토큰은 우리가 생각하는 "단어"나 "글자"와 정확히 일치하지 않습니다. LLM은 사람처럼 글자를 읽는 게 아니라, 자기만의 방식으로 텍스트를 조각내서 읽기 때문입니다.이 글에서는 토큰이 무엇이고, 토크나이저가 어떻게 동작하며, 이
임베딩(Embedding) 완전 이해 - 의미를 숫자로 바꾸기
컴퓨터는 "사과"와 "바나나"가 비슷하고 "사과"와 "자동차"가 다르다는 걸 어떻게 알까요? 글자만 비교하면 "사과"와 "사고"가 더 비슷해 보일 텐데 말이죠.이 문제를 푸는 열쇠가 임베딩(Embedding) 입니다. 텍스트의 의미를 숫자 벡터로 바꿔, 의미가 비슷하면 숫자도 가깝게 만드는 기술입니다.이 글에서는 임베딩이 무엇이고, 왜 유사도가 계산되며,
프롬프트 엔지니어링 실전 - 원하는 답을 얻는 법
같은 모델에게 같은 일을 시켜도, 어떻게 묻느냐에 따라 결과 품질이 극단적으로 갈립니다. "요약해줘"와 "3문장으로, 핵심 지표 중심으로, 존댓말로 요약해줘"는 전혀 다른 답을 냅니다.프롬프트 엔지니어링은 마법 주문이 아니라, 모델에게 원하는 것을 오해 없이 전달하는 커뮤니케이션 기술입니다.이 글에서는 실무에서 바로 쓰는 프롬프트 구성 원칙, 대표 기법,
파인튜닝 vs RAG vs 프롬프트 - 언제 무엇을 쓸까
LLM으로 뭔가 만들려고 하면 곧 이 갈림길을 만납니다. "우리 데이터를 어떻게 넣지? 파인튜닝? RAG? 아니면 프롬프트로 어떻게든?"세 가지는 경쟁 기술이 아니라 서로 다른 문제를 푸는 도구입니다. 잘못 고르면 돈과 시간을 크게 낭비합니다.이 글은 세 방법의 본질적 차이를 짚고, "언제 무엇을 쓸지"를 판단하는 의사결정 프레임워크에 집중합니다. RAG
LoRA와 QLoRA - 적은 자원으로 LLM 파인튜닝하기
LLM을 우리 도메인에 맞게 길들이고 싶을 때 가장 먼저 떠오르는 건 파인튜닝입니다. 그런데 수십억 개 파라미터를 통째로 다시 학습하려면 GPU가 몇 장씩 필요합니다.이 부담을 확 낮춘 기법이 LoRA이고, 거기서 메모리를 한 번 더 줄인 것이 QLoRA입니다.이 글에서는 두 기법이 왜 나왔고, 원리가 무엇이며, 실무에서 언제 쓰는지를 정리합니다.1. 풀
추론 모델과 Test-Time Compute - LLM이 '생각'한다는 것
같은 문제를 줘도 어떤 모델은 곧바로 답을 뱉고, 어떤 모델은 한참 "생각"한 뒤 답을 냅니다.후자가 요즘 말하는 추론 모델(reasoning model) 이고, 그 배경에는 test-time compute라는 개념이 있습니다.이 글에서는 LLM이 답 전에 생각을 길게 하는 게 왜 성능을 올리는지, 그리고 언제 추론 모델을 쓰고 언제 일반 모델이 나은지를
함수 호출(Function Calling) - LLM에게 도구를 쥐여주기
LLM은 학습된 지식으로 그럴듯한 문장을 만들지만, 실시간 재고를 조회하거나 결제를 취소하거나 정확한 계산을 하지는 못합니다.이 한계를 넘는 표준적인 방법이 함수 호출(Function Calling), 즉 LLM에게 도구(tool)를 쥐여주는 것입니다.이 글에서는 함수 호출이 정확히 어떤 구조로 동작하는지, 스키마는 어떻게 정의하고 실행 루프는 어떻게 도는
AI 에이전트 이해하기 - ReAct와 계획-실행 루프
함수 호출로 LLM에 도구를 쥐여줬다면, 그다음 질문은 자연스럽습니다. "목표만 던지면 알아서 여러 단계를 밟아 끝내주면 안 되나?"이 아이디어가 AI 에이전트(agent) 이고, 그 대표적인 동작 방식이 ReAct와 계획-실행 루프입니다.이 글에서는 에이전트가 무엇이고, 어떤 루프로 도는지, 그리고 실패·무한루프를 어떻게 막으며 현실적으로 어디까지 되는지
MCP(Model Context Protocol) - AI에 표준 연결 단자 달기
함수 호출로 도구를 연결하고 에이전트까지 만들다 보면 곧 새로운 고민이 생깁니다. "이 도구 연결을 매번, 앱마다, 모델마다 다시 짜야 하나?"이 파편화 문제를 표준으로 풀려는 시도가 MCP(Model Context Protocol) 입니다.이 글에서는 MCP가 왜 나왔고, 어떤 구조이며, 개발자에게 어떤 의미인지를 제가 아는 범위에서 개념 중심으로 정리합
pgvector 실전 - PostgreSQL로 벡터 검색하기
RAG를 만들려면 임베딩 벡터를 어딘가에 저장하고, 질문 벡터와 가까운 것들을 빠르게 찾아야 합니다.전용 벡터 DB(Pinecone, Qdrant 등)를 도입할 수도 있지만, 이미 쓰고 있는 PostgreSQL에 pgvector 확장만 얹으면 대부분의 실무 요구는 충분히 해결됩니다.이 글에서는 pgvector 설치부터 컬럼 설계, 검색 쿼리, 인덱스 트레이
LLM 평가 - 답변 품질을 어떻게 측정할까
프롬프트를 고치고, RAG를 붙이고, 모델을 바꿉니다. 그런데 정말 나아진 걸까요?일반 소프트웨어라면 테스트가 초록불이면 됩니다. 하지만 LLM은 같은 질문에 매번 다른 문장으로 답하고, 정답도 하나가 아닙니다.이 글에서는 왜 LLM 평가가 어려운지, 그리고 실무에서 품질을 수치로 관리하는 방법을 정리합니다.1. 왜 평가가 어려운가전통적인 테스트는 expe
할루시네이션 - LLM이 거짓말하는 이유와 줄이는 법
LLM에게 존재하지 않는 API 함수를 자신 있게 알려주거나, 없는 논문을 그럴듯한 제목과 저자까지 붙여 인용하는 경험, 다들 한 번쯤 있으실 겁니다.이렇게 모델이 사실이 아닌 내용을 사실처럼 생성하는 현상을 할루시네이션(hallucination, 환각)이라고 부릅니다.이 글에서는 할루시네이션이 왜 발생하는지 그 원리부터, 실무에서 줄이는 방법, 그리고 "
컨텍스트 윈도우와 롱컨텍스트 - 길다고 다 좋을까
"이번 모델은 컨텍스트 100만 토큰!" 같은 홍보를 자주 봅니다. 그래서 "문서를 통째로 넣으면 RAG 같은 거 필요 없는 거 아냐?"라는 생각이 들기도 합니다.하지만 컨텍스트가 길다고 무조건 좋은 것은 아닙니다. 길이에는 대가가 따르고, 길다고 잘 읽는 것도 아닙니다.이 글에서는 컨텍스트 윈도우가 무엇인지, 왜 길이가 만능이 아닌지, 그리고 컨텍스트를
구조화된 출력 - LLM에서 안정적으로 JSON 받기
LLM을 챗봇이 아니라 시스템의 한 부품으로 쓰기 시작하면, 곧 이 벽에 부딪힙니다."답변을 자연어로 받으면 코드에서 어떻게 파싱하지?" LLM의 출력을 다음 단계 코드가 소비하려면, 자유서술이 아니라 예측 가능한 구조(주로 JSON) 로 받아야 합니다.이 글에서는 자유서술의 문제부터, JSON 모드·스키마 강제, 함수 호출과의 관계, 검증과 실패 대응까지
LLM 추론 최적화 - 양자화와 KV 캐시
LLM을 직접 서빙해보면 학습보다 추론(inference) 이 더 골치 아프다는 걸 금방 알게 됩니다. GPU 메모리는 순식간에 꽉 차고, 토큰은 느리게 나오고, 비용은 요청량에 비례해 불어납니다.다행히 추론을 가볍게 만드는 두 가지 핵심 기술이 있습니다. 바로 양자화(Quantization) 와 KV 캐시(KV Cache) 입니다.이 글에서는 추론이 왜
로컬 LLM 실행 - Ollama로 내 PC에서 모델 돌리기
LLM을 쓰려면 무조건 API 키를 발급받고 요청마다 돈을 내야 할까요? 꼭 그렇지는 않습니다. 요즘은 내 노트북에서 직접 모델을 돌리는 것이 놀랄 만큼 쉬워졌습니다.그 중심에 있는 도구가 Ollama 입니다. 마치 docker run 하듯 ollama run 한 줄로 모델을 받아 실행할 수 있습니다.이 글에서는 왜 로컬에서 돌리는지, Ollama를 어떻게
멀티모달 LLM - 이미지를 이해하는 모델
지금까지 LLM은 텍스트만 읽고 텍스트만 답하는 존재였습니다. 하지만 이제는 이미지를 던져주고 "이게 뭐야?" 라고 물을 수 있습니다.스크린샷을 붙여 버그를 물어보고, 차트를 보여주며 요약을 시키고, 손글씨 영수증을 표로 바꾸는 일이 한 번의 프롬프트로 됩니다. 이것이 멀티모달 LLM(Multimodal LLM) 입니다.이 글에서는 멀티모달이 무엇인지, 어
LLM 앱 보안 - 프롬프트 인젝션 막기
전통적인 웹 보안에 SQL 인젝션이 있다면, LLM 시대에는 프롬프트 인젝션(Prompt Injection) 이 있습니다. 이름은 비슷하지만 성질이 훨씬 고약합니다.SQL 인젝션은 코드와 데이터를 분리하면 막을 수 있지만, LLM은 명령과 데이터를 똑같은 자연어로 받아들이기 때문에 근본적으로 구분이 어렵습니다.이 글에서는 프롬프트 인젝션이 무엇인지, 왜 위
Clean Architecture - 의존성 규칙과 레이어 분리
Clean Architecture는 의존성 규칙을 통해 비즈니스 로직을 프레임워크와 독립적으로 만드는 아키텍처 패턴입니다. 이 글에서는 Clean Architecture의 핵심 원칙과 실무 적용 방법을 정리합니다.1. 레이어 구조┌─────────────────┐│ Presentation │ (UI, Controllers)├──────────────
디자인 패턴 - 실무에서 자주 쓰는 패턴
디자인 패턴은 반복되는 설계 문제에 대한 검증된 해결책입니다. 이 글에서는 실무에서 자주 사용하는 디자인 패턴을 정리합니다.1. 싱글톤 패턴class Database { private static instance: Database; private constructor() {} static getInstance(): Database { if (!
Domain-Driven Design - 도메인 중심 설계
DDD(Domain-Driven Design)는 비즈니스 도메인을 중심으로 소프트웨어를 설계하는 방법론입니다. 이 글에서는 DDD의 핵심 개념과 실무 적용 방법을 정리합니다.1. 핵심 개념Entity**: 고유 식별자를 가진 객체Value Object**: 값으로 정의되는 불변 객체Aggregate**: 관련 엔티티를 묶는 루트Repository**: 영
이벤트 기반 아키텍처 - 느슨한 결합과 확장성
이벤트 기반 아키텍처는 이벤트를 통해 서비스 간 통신하는 패턴입니다. 이 글에서는 이벤트 버스, 메시지 큐, 이벤트 소싱 등을 정리합니다.1. 이벤트 버스class EventBus { private handlers = new Map(); subscribe(eventType, handler) { if (!this.handlers.has(eventT
마이크로서비스 아키텍처 - 분산 시스템 설계
마이크로서비스는 애플리케이션을 작은 독립적인 서비스로 분해하는 아키텍처 패턴입니다. 이 글에서는 마이크로서비스의 장단점과 실무 적용 방법을 정리합니다.1. 마이크로서비스 특징독립적 배포**: 각 서비스를 독립적으로 배포기술 다양성**: 서비스마다 다른 기술 스택 사용 가능확장성**: 필요한 서비스만 확장2. 서비스 통신// 동기 통신 (HTTP/REST)
SOLID 원칙 - 객체지향 설계 원칙
SOLID는 객체지향 설계의 5가지 원칙으로, 유지보수 가능한 코드를 작성하는 가이드라인입니다. 이 글에서는 각 원칙의 의미와 실무 적용 방법을 정리합니다.1. Single Responsibility Principle (SRP)하나의 클래스는 하나의 책임만 가져야 합니다.// ❌ 나쁜 예class User { save() {} sendEmail() {
AWS 기초 - 클라우드 인프라 이해하기
AWS는 클라우드 컴퓨팅 플랫폼으로, 서버, 스토리지, 데이터베이스 등을 온디맨드로 제공합니다. 이 글에서는 AWS의 핵심 서비스와 실무에서 자주 사용하는 패턴을 정리합니다.1. 핵심 서비스EC2**: 가상 서버S3**: 객체 스토리지RDS**: 관리형 데이터베이스Lambda**: 서버리스 함수CloudFront**: CDN2. EC2 인스턴스인스턴스 생
CI/CD 파이프라인 - 자동화된 배포 전략
CI/CD는 지속적 통합과 지속적 배포를 자동화하여 개발 생산성을 크게 향상시킵니다. 이 글에서는 GitHub Actions, GitLab CI 등을 활용한 CI/CD 파이프라인 구축 방법을 정리합니다.1. CI/CD 개념CI (Continuous Integration)**: 코드 변경을 자동으로 빌드하고 테스트CD (Continuous Deploymen
Docker 기초 - 컨테이너와 이미지 이해하기
Docker는 컨테이너 기반 가상화 기술로, 애플리케이션을 환경에 독립적으로 실행할 수 있게 해줍니다. 이 글에서는 Docker의 기본 개념과 실무에서 자주 사용하는 명령어를 정리합니다.1. 기본 개념이미지(Image)**: 실행 가능한 패키지컨테이너(Container)**: 이미지의 실행 인스턴스Dockerfile**: 이미지를 빌드하기 위한 스크립트2
Kubernetes 기초 - 컨테이너 오케스트레이션
Kubernetes는 컨테이너 오케스트레이션 플랫폼으로, 대규모 컨테이너 배포와 관리를 자동화합니다. 이 글에서는 Kubernetes의 핵심 개념과 기본 리소스를 정리합니다.1. 핵심 개념Pod**: 하나 이상의 컨테이너 그룹Deployment**: Pod의 배포와 업데이트 관리Service**: Pod에 대한 네트워크 접근 제공Namespace**: 리
모니터링과 로깅 - 프로덕션 시스템 관찰
프로덕션 시스템의 모니터링과 로깅은 안정적인 서비스를 운영하는 핵심입니다. 이 글에서는 메트릭 수집, 로그 관리, 알림 설정 방법을 정리합니다.1. 메트릭 수집// Prometheus 스타일 메트릭const httpRequestDuration = new promClient.Histogram({ name: "http_request_duration_seco
Terraform 기초 - Infrastructure as Code
Terraform은 Infrastructure as Code 도구로, 인프라를 코드로 정의하고 관리할 수 있습니다. 이 글에서는 Terraform의 기본 개념과 실무 사용법을 정리합니다.1. 기본 구조main.tfprovider "aws" { region = "ap-northeast-2"}resource "aws_s3_bucket" "my_bucket"
Next.js API Routes - 서버리스 함수로 백엔드 구현
Next.js API Routes는 서버리스 함수로 백엔드 API를 구현할 수 있게 해줍니다. 프론트엔드와 백엔드를 같은 프로젝트에서 관리할 수 있어, 작은 프로젝트나 프로토타입에 적합합니다.1. 기본 API Route 구조// app/api/users/route.ts (App Router)import { NextRequest, NextResponse }
Next.js 캐싱 전략 - ISR, SSG, SSR 캐시 제어
Next.js는 다양한 캐싱 전략을 제공하여 성능을 최적화합니다. 이 글에서는 fetch 옵션, revalidate, generateStaticParams 등을 활용한 캐싱 전략을 정리합니다.1. fetch 캐시 옵션// app/products/page.tsx// 1. 기본 캐시 (force-cache)const data = await fetch("htt
Next.js 폰트 최적화 - next/font로 웹폰트 성능 개선
Next.js의 next/font는 웹폰트를 자동으로 최적화하여 레이아웃 시프트(CLS)를 방지하고 로딩 성능을 개선합니다. Google Fonts, 로컬 폰트 모두 지원하며, 자동으로 폰트 파일을 최적화합니다.1. Google Fonts 사용import { Inter } from "next/font/google";const inter = Inter({
Next.js Image 최적화 - 자동 이미지 최적화와 성능 개선
Next.js의 Image 컴포넌트는 이미지를 자동으로 최적화하고, 지연 로딩, 반응형 크기 조정 등을 제공합니다. 이 글에서는 next/image를 사용하여 이미지 성능을 개선하는 방법을 정리합니다.1. 기본 사용법import Image from "next/image";function ProductCard({ product }: { product: Pr
Next.js Metadata API - SEO와 소셜 미디어 최적화
Next.js 13+ App Router에서는 metadata 객체나 generateMetadata 함수로 SEO 메타데이터를 선언적으로 관리할 수 있습니다. 이 글에서는 페이지별 메타데이터 설정과 동적 메타데이터 생성 방법을 정리합니다.1. 정적 메타데이터// app/about/page.tsxexport const metadata = { title:
Next.js Middleware - 요청 가로채기와 엣지 런타임
Next.js Middleware는 요청이 완료되기 전에 실행되는 코드로, 리다이렉트, 헤더 수정, 인증 체크 등을 처리할 수 있습니다. Edge Runtime에서 실행되어 매우 빠른 응답 시간을 제공합니다.1. 기본 Middleware 구조// middleware.ts (프로젝트 루트)import { NextResponse } from "next/ser
Node.js 기초 - 이벤트 루프와 비동기 처리
Node.js는 비동기 I/O와 이벤트 기반 아키텍처로 동작하는 JavaScript 런타임입니다. 이 글에서는 Node.js의 핵심 개념인 이벤트 루프, 비동기 처리, 모듈 시스템을 정리합니다.1. 이벤트 루프Node.js는 단일 스레드에서 이벤트 루프를 통해 비동기 작업을 처리합니다.console.log("1");setTimeout(() => { co
Node.js Cluster - 멀티코어 활용과 성능 최적화
Node.js는 기본적으로 단일 스레드로 동작하지만, Cluster 모듈을 사용하면 멀티코어를 활용할 수 있습니다. 이 글에서는 Cluster로 CPU 집약적 작업의 성능을 향상시키는 방법을 정리합니다.1. 기본 Clusterconst cluster = require("cluster");const http = require("http");const num
Node.js 에러 처리 - 비동기 에러 핸들링 패턴
Node.js에서 비동기 에러를 올바르게 처리하는 것은 안정적인 애플리케이션을 만드는 핵심입니다. 이 글에서는 콜백, Promise, async/await에서의 에러 처리 패턴을 정리합니다.1. 콜백 에러 처리const fs = require("fs");fs.readFile("file.txt", "utf8", (err, data) => { if (err
Express.js 기초 - RESTful API 서버 구축
Express.js는 Node.js를 위한 미니멀한 웹 프레임워크입니다. 이 글에서는 Express로 RESTful API 서버를 구축하는 기본 패턴을 정리합니다.1. 기본 서버const express = require("express");const app = express();app.get("/", (req, res) => { res.json({ me
Node.js 보안 - 실무 보안 체크리스트
Node.js 애플리케이션의 보안은 다층 방어 전략으로 접근해야 합니다. 이 글에서는 실무에서 자주 놓치는 보안 이슈와 대응 방법을 정리합니다.1. 의존성 보안npm audit로 취약점 검사npm audit자동 수정npm audit fix2. 환경 변수 관리// .env 파일 (git에 커밋하지 않음)require("dotenv").config();con
Node.js Streams - 대용량 데이터 효율적 처리
Node.js Streams는 대용량 데이터를 메모리 효율적으로 처리할 수 있게 해줍니다. 파일 읽기/쓰기, HTTP 요청/응답 등에서 스트림을 활용하면 메모리 사용량을 크게 줄일 수 있습니다.1. 스트림 타입Readable**: 데이터를 읽을 수 있는 스트림Writable**: 데이터를 쓸 수 있는 스트림Duplex**: 읽기/쓰기 모두 가능Transf
React 접근성(a11y) 가이드
React로 UI를 만들 때 기본적인 접근성(a11y) 원칙을 지키기 위한 체크리스트를 정리해 둔 글입니다.1. 시맨틱 마크업div 남용 대신 적절한 HTML 태그를 쓰는 기준과, 스크린 리더가 어떻게 읽는지 간단한 예를 메모합니다.2. 포커스 관리모달, 드롭다운, 토스트 등에서 포커스를 어떻게 이동/복원할지에 대한 패턴과 주의점을 정리합니다.3. ARIA
Framer Motion으로 React 애니메이션 다루기
Framer Motion을 사용해서 React 컴포넌트에 자연스러운 모션을 추가할 때 기본적으로 알아 두면 좋은 개념들을 메모합니다.1. motion 컴포넌트 기본motion.div와 animate, initial, transition 속성으로 단순한 등장/퇴장 애니메이션을 만드는 패턴을 정리합니다.2. 레이아웃 애니메이션layout과 AnimatePres
React 코드 스플리팅과 Suspense 패턴
번들 크기를 줄이고 초기 로딩 속도를 개선하기 위해 코드 스플리팅과 Suspense를 어떻게 조합할지에 대한 간단한 메모입니다.1. lazy와 Suspense 기본React.lazy와 Suspense를 이용해 라우트 단위, 위젯 단위로 코드를 분리하는 패턴을 정리합니다.2. 폴백 UI 설계스피너만 두는 대신, 스켈레톤, 최근 데이터, 간단한 문구 등 사용자
React 컴포넌트 합성과 재사용 패턴
컴포넌트를 합성해서 재사용성을 높이고, prop drilling이나 거대한 컴포넌트를 피하는 패턴들을 간단히 정리합니다.1. Children 기반 합성children과 렌더 props를 활용해 레이아웃과 로직을 분리하는 패턴을 예시와 함께 정리합니다.2. Compound Components`, ` 같은 컴포넌트를 compound 패턴으로 설계할 때의 인터페
React Concurrent Features - useTransition과 useDeferredValue
React 18의 Concurrent Features는 우선순위에 따라 렌더링을 조절할 수 있게 해줍니다. useTransition과 useDeferredValue를 사용하면 사용자 입력을 즉시 반영하면서도, 무거운 업데이트는 지연시킬 수 있습니다.1. useTransition으로 우선순위 조절import { useTransition, useState }
React Context 성능 최적화 - 리렌더 줄이는 실전 패턴
Context는 전역 상태처럼 편하지만, 설계가 나쁘면 작은 변경에도 트리 전체가 리렌더될 수 있습니다. 이 글은 Context 사용 시 성능을 안정적으로 유지하는 패턴만 짧게 정리합니다.1. 문제가 되는 구조큰 객체를 한 Context에 몰아 넣기Provider value가 렌더마다 새로 생성되기2. 1차 처방: Provider value 안정화cons
React Error Boundary - 에러 처리와 사용자 경험 개선
React에서 컴포넌트 렌더링 중 발생한 에러를 우아하게 처리하고, 앱 전체가 크래시되지 않도록 보호하는 방법을 Error Boundary로 구현할 수 있습니다. 이 글에서는 Error Boundary의 기본 개념과 실무에서 활용하는 패턴을 정리합니다.1. Error Boundary란?Error Boundary는 클래스 컴포넌트로만 구현 가능하며, com
React 폼 상태 관리 전략
React에서 폼을 관리할 때 useState만으로 처리할지, 라이브러리를 쓸지, 어디까지 커스텀 훅으로 뽑을지에 대한 기준을 정리하는 글입니다.1. 컨트롤드 vs 언컨트롤드각 방식의 장단점과, 실제로 어떤 화면에서 무엇을 선택하는 게 좋은지 간단한 예시와 함께 비교합니다.2. 라이브러리 선택 기준react-hook-form, Formik 등의 특징을 짚어
React Hooks 베스트 프랙티스 - 실무에서 자주 놓치는 포인트
React Hooks는 함수 컴포넌트에서 상태와 생명주기를 다루는 강력한 도구입니다. 이 글에서는 useState, useEffect, useCallback, useMemo 등을 실무에서 올바르게 사용하는 방법과 자주 발생하는 실수들을 정리합니다.1. useState 초기값과 함수형 업데이트// ❌ 나쁜 예: 객체를 직접 수정const [user, set
React 성능 최적화 - 렌더링 최소화와 메모이제이션 전략
React 애플리케이션의 성능을 개선하려면 불필요한 렌더링을 줄이고, 비용이 큰 계산을 메모이제이션하는 것이 핵심입니다. 이 글에서는 실무에서 자주 사용하는 성능 최적화 기법들을 정리합니다.1. React.memo로 컴포넌트 메모이제이션const ExpensiveComponent = React.memo(({ data }: { data: Data }) =>
React Portal - DOM 트리 밖으로 컴포넌트 렌더링하기
React Portal은 컴포넌트를 부모 컴포넌트의 DOM 계층 구조 밖에 렌더링할 수 있게 해주는 기능입니다. 모달, 툴팁, 드롭다운 같은 UI 요소를 z-index 문제 없이 구현할 때 유용합니다.1. Portal 기본 사용법import { createPortal } from "react-dom";function Modal({ children, isO
React ref와 forwardRef - DOM 접근과 컴포넌트 간 ref 전달
React에서 DOM 요소에 직접 접근하거나, 자식 컴포넌트의 메서드를 호출할 때 ref를 사용합니다. 이 글에서는 useRef, forwardRef, useImperativeHandle의 사용법과 실무 패턴을 정리합니다.1. useRef 기본 사용법function TextInput() { const inputRef = useRef(null); con
React Router 베스트 프랙티스
React Router로 라우팅을 구성할 때 자주 부딪히는 문제들을 정리하고, 실무에서 많이 쓰는 패턴을 간단히 메모해 둔 글입니다.1. 라우트 구조 설계중첩 라우트, 레이아웃 컴포넌트, 코드 스플리팅을 어떻게 배치할지에 대한 기준을 잡습니다.2. URL 설계 원칙자원 중심 RESTful URL, 검색/필터/정렬 파라미터를 어떻게 나눌지에 대한 가이드입니다
React Server Components - 서버에서 렌더링되는 컴포넌트
React Server Components(RSC)는 서버에서만 실행되고, 클라이언트로 JavaScript 번들을 전송하지 않는 새로운 컴포넌트 모델입니다. Next.js 13+ App Router에서 기본으로 사용되며, 성능과 번들 크기 최적화에 큰 도움을 줍니다.1. Server Components vs Client Components// Server
React 상태 파생(derived state) vs memo - 어디에 두는 게 맞을까?
React에서 자주 생기는 실수는 “계산 가능한 값”을 별도 state로 들고 가면서 동기화 버그를 만드는 것입니다. 이 글은 derived state를 피하는 기준과, useMemo/계산 함수를 어디에 둘지 판단하는 실무 규칙을 정리합니다.1. 결론부터파생 가능한 값은 state로 두지 말고 계산한다계산이 비싸서 병목이 보일 때만 useMemo를 고려한
Zustand로 가벼운 React 상태 관리하기
Redux만 쓰기엔 부담스럽고, Context만으로는 아쉬울 때 쓸 수 있는 가벼운 상태 관리 라이브러리인 Zustand를 간단히 정리합니다.1. 기본 스토어 정의작은 예제로 create 함수로 스토어를 만들고, 컴포넌트에서 훅으로 사용하는 패턴을 기록합니다.2. 상태 분리와 구조피쳐별로 스토어를 나누는 전략, setter 네이밍, Immer와의 조합 등을
Storybook으로 React 컴포넌트 문서화
Storybook을 사용해 React 컴포넌트를 카탈로그처럼 정리하고, 디자인 시스템에 가까운 구조를 만드는 과정을 기록하는 글입니다.1. 기본 세팅과 스토리 작성프로젝트에 Storybook을 설치하고, 버튼/입력 같은 기본 컴포넌트에 스토리를 작성하는 흐름을 정리합니다.2. Controls와 Docs 탭 활용디자이너/기획자도 확인하기 쉬운 문서 화면을 만
React Testing Library - 사용자 중심 테스트 작성하기
React Testing Library는 사용자가 컴포넌트를 어떻게 사용하는지를 중심으로 테스트를 작성하도록 유도하는 테스트 도구입니다. 구현 세부사항보다는 사용자 관점의 동작을 검증하는 것이 핵심 철학입니다.1. 기본 사용법import { render, screen } from "@testing-library/react";import userEvent
E2E 테스트 - 사용자 시나리오 기반 테스트
E2E(End-to-End) 테스트는 사용자 관점에서 전체 시스템을 테스트하는 방법입니다. 이 글에서는 Cypress, Playwright 등을 활용한 E2E 테스트 작성 방법을 정리합니다.1. Cypress 기본describe("User Flow", () => { it("should login and view profile", () => { cy
통합 테스트 - 시스템 컴포넌트 간 상호작용 검증
통합 테스트는 여러 컴포넌트가 함께 동작하는지 검증하는 테스트입니다. 이 글에서는 통합 테스트 작성 방법과 실무 패턴을 정리합니다.1. 통합 테스트 개념단위 테스트**: 개별 함수/모듈통합 테스트**: 여러 모듈의 상호작용E2E 테스트**: 전체 시스템2. API 통합 테스트const request = require("supertest");const ap
Jest 기초 - JavaScript 테스트 프레임워크
Jest는 JavaScript 테스트 프레임워크로, 단위 테스트, 통합 테스트를 작성하고 실행할 수 있습니다. 이 글에서는 Jest의 기본 사용법과 실무 패턴을 정리합니다.1. 기본 테스트// math.test.jsfunction add(a, b) { return a + b;}test("adds 1 + 2 to equal 3", () => { expe
Mocking과 Stubbing - 테스트 격리와 제어
Mocking과 Stubbing은 테스트를 격리하고 외부 의존성을 제어하는 방법입니다. 이 글에서는 Jest, Sinon 등을 활용한 모킹 패턴을 정리합니다.1. Mock vs Stub vs SpyMock**: 행동을 검증하는 가짜 객체Stub**: 특정 값을 반환하는 가짜 객체Spy**: 실제 함수 호출을 추적2. Jest Mock// 함수 모킹cons
TDD - 테스트 주도 개발
TDD(Test-Driven Development)는 테스트를 먼저 작성하고 코드를 작성하는 개발 방법론입니다. 이 글에서는 TDD의 원칙과 실무 적용 방법을 정리합니다.1. TDD 사이클Red: 실패하는 테스트 작성Green: 테스트를 통과하는 최소 코드 작성Refactor: 코드 개선2. 예시// 1. Red: 실패하는 테스트test("should c
단위 테스트 - 함수와 모듈 테스트 작성
단위 테스트는 개별 함수나 모듈을 독립적으로 테스트하는 방법입니다. 이 글에서는 단위 테스트 작성 원칙과 실무 패턴을 정리합니다.1. 테스트 원칙격리**: 외부 의존성 없이 테스트빠름**: 빠르게 실행되어야 함반복 가능**: 항상 같은 결과명확함**: 테스트 의도가 명확해야 함2. 테스트 구조describe("Calculator", () => { des
TypeScript 고급 타입 - 유틸리티 타입과 조건부 타입
TypeScript의 고급 타입 기능을 활용하면 타입을 더 정확하고 재사용 가능하게 만들 수 있습니다. 이 글에서는 유틸리티 타입, 조건부 타입, 매핑된 타입 등을 정리합니다.1. 유틸리티 타입interface User { id: number; name: string; email: string; age: number;}// Partial: 모든 속
TypeScript 기초 - 타입 시스템과 기본 문법
TypeScript는 JavaScript에 정적 타입 시스템을 추가한 언어입니다. 컴파일 시점에 타입 오류를 발견할 수 있어, 대규모 프로젝트에서 코드 안정성을 크게 향상시킵니다.1. 기본 타입let name: string = "kwkang";let age: number = 30;let isActive: boolean = true;let items: st
TypeScript tsconfig.json 완전 정리
TypeScript의 tsconfig.json은 컴파일 옵션과 프로젝트 설정을 관리하는 핵심 파일입니다. 이 글에서는 주요 옵션과 실무에서 자주 사용하는 설정을 정리합니다.1. 기본 구조{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020", "D
TypeScript 데코레이터 - 클래스와 메서드 메타데이터
TypeScript 데코레이터는 클래스, 메서드, 프로퍼티에 메타데이터를 추가하는 실험적 기능입니다. Angular, NestJS 같은 프레임워크에서 널리 사용되며, tsconfig.json에서 활성화해야 합니다.1. 데코레이터 설정// tsconfig.json{ "compilerOptions": { "experimentalDecorators":
TypeScript 제네릭 심화 - 제약 조건과 고급 패턴
TypeScript 제네릭은 타입을 파라미터화하여 재사용 가능한 타입과 함수를 만들 수 있게 해줍니다. 이 글에서는 제네릭 제약 조건, 조건부 타입과의 조합, 실무 패턴을 정리합니다.1. 기본 제네릭function identity(arg: T): T { return arg;}const str = identity("hello");const num = id
TypeScript 네임스페이스 - 모듈과 네임스페이스 비교
TypeScript 네임스페이스는 코드를 논리적으로 그룹화하는 방법이지만, ES6 모듈이 더 권장됩니다. 이 글에서는 네임스페이스의 사용법과 모듈과의 차이점을 정리합니다.1. 네임스페이스 기본namespace Utils { export function formatDate(date: Date): string { return date.toISOStri
TypeScript 타입 가드 - 런타임 타입 체크와 타입 좁히기
TypeScript 타입 가드는 런타임에 타입을 체크하여 타입을 좁혀(narrow) 타입 안정성을 보장합니다. 이 글에서는 typeof, instanceof, 커스텀 타입 가드 등을 정리합니다.1. typeof 타입 가드function processValue(value: string | number) { if (typeof value === "strin
TypeScript 유틸리티 타입 완전 정리
TypeScript는 자주 사용하는 타입 변환을 위한 내장 유틸리티 타입을 제공합니다. 이 글에서는 Partial, Required, Pick, Omit, Record 등 모든 유틸리티 타입을 정리합니다.1. Partial모든 속성을 선택적으로 만듭니다.interface User { id: number; name: string; email: stri
Kotlin 정리 - 실무에서 바로 쓰는 문법과 패턴
Kotlin은 Null 안정성, 간결한 문법, 함수형 스타일을 지원하는 JVM 언어로, 안드로이드와 백엔드(Spring Boot)에서 모두 널리 사용됩니다. 이 글에서는 실무에서 자주 사용하는 문법과 패턴을 간략히 정리합니다.1. 변수와 Null 안정성val name: String = "kwkang" // 불변var age: Int = 10
Next.js 16 정리 - React 18 시대의 풀스택 프레임워크
Next.js 16은 React 18을 기반으로 하는 풀스택 웹 프레임워크로, 서버 컴포넌트(App Router), 스트리밍, 캐시, 미들웨어 등 프론트엔드와 백엔드를 모두 아우를 수 있는 기능을 제공합니다. 이 글에서는 Next.js 16에서 핵심적으로 알아야 할 개념과, 실무에서 자주 쓰게 될 부분 위주로 간략히 정리합니다.1. 프로젝트 구조와 App
React 18 정리 - Concurrent Rendering과 실무 포인트
React 18은 Concurrent Rendering과 자동 배칭, Suspense 개선 등을 통해 UI를 더 부드럽게 만들고, 서버 렌더링을 강화한 버전입니다. Next.js 13+ / 16 같은 프레임워크에서도 React 18 기능을 전제로 설계되어 있기 때문에, 핵심 개념은 꼭 알고 있어야 합니다.1. 자동 배칭(Automatic Batching)
Spring Boot 정리 - 실무 서비스 구조와 핵심 개념
Spring Boot는 Spring 기반 애플리케이션을 빠르게 시작하고 운영할 수 있도록 도와주는 프레임워크입니다. 복잡한 XML 설정 없이, 스타터 의존성과 자동 설정(auto configuration)으로 대부분의 기본 구성을 대신해 줍니다.1. 프로젝트 구조가장 기본적인 Spring Boot 프로젝트 구조는 다음과 같습니다.src └ main
Spring Boot로 REST API 만들기 - JPA까지 한 번에 정리
Spring Boot로 백엔드 서비스를 만들 때 가장 많이 하는 일이 REST API + JPA로 CRUD 서버 만들기입니다. 이 글에서는 프로젝트 구조 → 엔티티/DTO 설계 → 컨트롤러/서비스/리포지토리 레이어 분리 → 예외 처리까지 실무 패턴 위주로 정리합니다. 예제 코드는 Kotlin 기준이지만, Java로도 거의 동일하게 적용할 수 있습니다.1
MySQL 쿼리 기본과 인덱스 설계
MySQL에서 성능 좋은 쿼리를 작성하려면 기본 문법 + 인덱스 구조 + 실행 계획(EXPLAIN) 세 가지를 같이 이해해야 합니다. 이 글에서는 가장 자주 쓰는 SELECT 쿼리 패턴과, 인덱스 설계 시 꼭 챙겨야 할 포인트를 정리합니다.1. 기본 SELECT 쿼리 패턴SELECT id, name, statusFROM usersWHERE status =
Spring Boot JPA 쿼리 전략 - 메서드 이름, JPQL, QueryDSL까지
Spring Data JPA를 사용할 때는 쿼리를 어디까지 자동으로 맡기고, 어디부터 직접 작성할지를 정하는 것이 중요합니다. 이 글에서는 Spring Boot + JPA 환경에서 자주 쓰는 쿼리 작성 방법을 단계별로 정리합니다.1. 메서드 이름 기반 쿼리가장 단순한 방법은 메서드 이름을 규칙대로 쓰면 JPA가 알아서 쿼리를 만들어 주는 방식입니다.int
React Query 심화 - 캐싱 전략과 무한 스크롤, 에러 핸들링
React Query는 클라이언트에서 서버 상태(데이터)를 관리하는 데 특화된 라이브러리입니다. 이 글에서는 기본 useQuery/useMutation에서 한 단계 나아가, 캐싱 전략, 무한 스크롤, 에러 핸들링을 중심으로 정리합니다.1. 캐시 전략: staleTime, cacheTimeconst { data, isFetching } = useQuery(
React에서 getBoundingClientRect 활용하기
React에서 getBoundingClientRect 활용하기getBoundingClientRect는 DOM 요소의 크기와 화면에서의 위치를 정확히 파악할 수 있는 메서드입니다. 이 메서드는 React에서 특정 요소가 화면에 보이는지 감지하거나, Lazy Loading, 애니메이션 트리거 등을 구현할 때 매우 유용합니다. 아래는 getBoundingClie
Next.js에서 Utterances 댓글 시스템 구현하기
Next.js에서 Utterances 댓글 시스템 구현하기Utterances는 GitHub 이슈를 활용하여 웹사이트에 간단하게 댓글 시스템을 추가할 수 있는 오픈 소스 프로젝트입니다. Next.js 프로젝트에 Utterances를 삽입하는 방법과, 테마 전환 시 깜빡임이 발생하는 방식과 깜빡임을 방지하는 방식을 각각 소개합니다.1. Utterances 기본
React useMemo, useCallback, memo 차이점
useCallback, useMemo, 그리고 memo는 모두 React에서 성능 최적화를 위해 사용되는 도구이지만, 각각의 목적과 사용 사례가 다릅니다. 아래에서 그 차이점을 설명하겠습니다.1. useCallback목적**: 함수를 메모이제이션하여 불필요한 재생성을 방지.사용 대상**: 함수.사용 예시**: import React, { useCall
Next.js App Router 정리
Next.js의 App Router는 13버전부터 도입된 새로운 라우팅 방식으로, 기존의 Pages Router보다 더 현대적이고 유연한 기능을 제공합니다. App Router를 통해 서버 컴포넌트와 클라이언트 컴포넌트를 효과적으로 관리하며 React 18의 기능을 최대한 활용할 수 있습니다. 아래는 App Router의 주요 개념과 특징, 활용법을 정리한
React Query useMutation
React Query useMutation 사용법React Query는 React 앱에서 데이터를 fetch하고 캐시하는 것을 간단하게 만들어주는 라이브러리입니다. useMutation은 React Query에서 제공하는 함수 중 하나로, 데이터를 create, update, delete하는데 사용됩니다.useMutation 사용법useMutation 함수
React Query useQuery
react query v4 설치yarn add @tanstack/react-queryreact query 브라우저 호환아무 버전이나 다 되는 줄 알았는데, 호환하는 브라이저가 있는걸 알았다.Chrome >= 73Firefox >= 78Edge >= 79Safari >= 12.0iOS >= 12.0opera >= 53react query 설정하기quertCl
mysql query 순서
mysql query 순서FROM : 조회 테이블 확인 SELECT부터 처리할 것 같지만, 쿼리의 가장 첫 번째 실행 순서는 FROM 절입니다. FROM 절에서는 테이블의 모든 데이터를 가져옵니다.WHERE : 데이터 추출 조건 확인 FROM절에서 읽어온 데이터중에서 조건에 일치하는 데이터만 가져옵니다.GROUP BY : 컬럼 그룹화 WHERE
