diff --git a/docs/posts/cs/restful-api.mdx b/docs/posts/cs/restful-api.mdx
new file mode 100644
index 0000000..d01b98c
--- /dev/null
+++ b/docs/posts/cs/restful-api.mdx
@@ -0,0 +1,346 @@
+---
+title: 'RESTful API 설계 원칙'
+type: 'concept'
+language: 'CS'
+tags:
+ - API
+ - REST
+ - HTTP
+ - Web
+dateModified: 2025.10.10
+---
+
+# RESTful API
+
+REST(Representational State Transfer)는 웹의 장점을 최대한 활용하는 네트워크 아키텍처 스타일입니다. RESTful API는 REST 원칙을 따르는 API로, 자원(Resource)을 URI로 표현하고 HTTP 메서드를 통해 자원에 대한 행위를 정의합니다.
+
+## REST의 6가지 제약 조건
+
+REST 아키텍처는 다음 6가지 제약 조건을 따릅니다.
+
+**1. 클라이언트-서버 (Client-Server)**
+- 클라이언트와 서버가 독립적으로 분리되어 있어야 합니다.
+- 각각 독립적으로 개선될 수 있습니다.
+
+**2. 무상태성 (Stateless)**
+- 각 요청은 독립적이며, 서버는 클라이언트의 상태를 저장하지 않습니다.
+- 모든 요청에는 필요한 정보가 포함되어야 합니다.
+
+**3. 캐시 가능 (Cacheable)**
+- 응답은 캐시 가능 여부를 명시해야 합니다.
+- 클라이언트는 응답을 재사용하여 성능을 향상시킬 수 있습니다.
+
+**4. 계층화 시스템 (Layered System)**
+- 클라이언트는 직접 서버에 연결되었는지, 중간 서버(프록시, 게이트웨이 등)를 통해 연결되었는지 알 수 없어야 합니다.
+
+**5. 인터페이스 일관성 (Uniform Interface)**
+- 일관된 인터페이스를 통해 시스템 아키텍처를 단순화하고, 상호작용의 가시성을 높입니다.
+
+**6. 코드 온 디맨드 (Code on Demand) - 선택사항**
+- 서버가 클라이언트에게 실행 가능한 코드를 전송하여 기능을 확장할 수 있습니다.
+- 이는 선택적 제약 조건입니다.
+
+## HTTP 메서드와 CRUD 매핑
+
+REST API는 HTTP 메서드를 사용하여 자원에 대한 행위를 표현합니다.
+
+| HTTP 메서드 | CRUD | 역할 | 멱등성 |
+|------------|------|------|--------|
+| GET | Read | 자원 조회 | O |
+| POST | Create | 자원 생성 | X |
+| PUT | Update | 자원 전체 수정 | O |
+| PATCH | Update | 자원 부분 수정 | X |
+| DELETE | Delete | 자원 삭제 | O |
+
+### 멱등성 (Idempotent)
+
+같은 요청을 여러 번 수행해도 결과가 동일한 성질을 말합니다. GET, PUT, DELETE는 멱등성을 가지지만, POST와 PATCH는 멱등성을 보장하지 않습니다.
+
+#### 예시
+
+```javascript
+// GET - 멱등성 O (여러 번 조회해도 결과 동일)
+GET /api/users/123
+
+// POST - 멱등성 X (요청마다 새로운 자원 생성)
+POST /api/users
+{
+ "name": "홍길동",
+ "email": "hong@example.com"
+}
+
+// PUT - 멱등성 O (여러 번 수정해도 최종 결과 동일)
+PUT /api/users/123
+{
+ "name": "홍길동",
+ "email": "hong@example.com"
+}
+
+// DELETE - 멱등성 O (이미 삭제된 자원을 다시 삭제해도 결과 동일)
+DELETE /api/users/123
+```
+
+## URI 설계 규칙
+
+RESTful API의 URI는 자원을 명확하게 표현해야 합니다. 다음은 좋은 URI를 설계하기 위한 핵심 원칙들입니다.
+
+**1. 명사를 사용하고 복수형으로 표현**
+- 자원을 나타낼 때는 동사가 아닌 명사를 사용하고, 복수형으로 표현합니다.
+
+**2. 계층 관계는 슬래시(/)로 표현**
+- 자원 간의 계층 관계를 명확하게 나타냅니다.
+
+**3. URI 마지막에 슬래시(/) 포함하지 않기**
+- 불필요한 혼란을 방지합니다.
+
+**4. 하이픈(-)은 사용 가능, 언더스코어(_)는 지양**
+- 가독성을 위해 하이픈을 사용합니다.
+
+**5. 소문자 사용**
+- URI는 대소문자를 구분하므로 일관성을 위해 소문자를 사용합니다.
+
+**6. 파일 확장자는 URI에 포함하지 않기**
+- Content-Type 헤더로 미디어 타입을 지정합니다.
+
+```javascript
+// ✅ 좋은 예
+GET /api/users
+GET /api/users/123
+GET /api/users/123/orders
+GET /api/users/123/orders/456
+GET /api/order-items
+GET /api/users/123/profile-image
+
+// ❌ 나쁜 예
+GET /api/getUsers
+GET /api/user
+GET /api/users/123/
+GET /api/Users/123/ProfileImage
+GET /api/order_items
+GET /api/users/123/profile-image.png
+```
+
+## HTTP 상태 코드 활용
+
+적절한 HTTP 상태 코드를 사용하여 응답 결과를 명확히 전달합니다.
+
+| 상태 코드 | 의미 | 설명 | 사용 시점 |
+|----------|------|------|-----------|
+| **2xx - 성공** ||||
+| 200 OK | 요청 성공 | 요청이 성공적으로 처리됨 | GET, PUT, PATCH |
+| 201 Created | 자원 생성 성공 | 새로운 자원이 생성됨 | POST |
+| 204 No Content | 요청 성공, 응답 본문 없음 | 요청은 성공했지만 반환할 내용이 없음 | DELETE |
+| **3xx - 리다이렉션** ||||
+| 301 Moved Permanently | 영구 이동 | 자원의 URI가 영구적으로 변경됨 | URI 변경 |
+| 302 Found | 임시 이동 | 자원의 URI가 일시적으로 변경됨 | 임시 URI 변경 |
+| **4xx - 클라이언트 오류** ||||
+| 400 Bad Request | 잘못된 요청 | 요청 형식이 잘못되었거나 유효하지 않음 | 잘못된 파라미터 |
+| 401 Unauthorized | 인증 필요 | 인증이 필요한 요청 | 로그인 필요 |
+| 403 Forbidden | 권한 없음 | 인증은 되었지만 권한이 없음 | 권한 부족 |
+| 404 Not Found | 자원을 찾을 수 없음 | 요청한 자원이 존재하지 않음 | 존재하지 않는 URI |
+| 409 Conflict | 충돌 | 요청이 현재 서버 상태와 충돌 | 중복된 자원 생성 |
+| **5xx - 서버 오류** ||||
+| 500 Internal Server Error | 서버 내부 오류 | 서버에서 예상치 못한 오류 발생 | 서버 에러 |
+| 502 Bad Gateway | 게이트웨이 오류 | 게이트웨이나 프록시 서버에서 오류 발생 | 프록시 에러 |
+| 503 Service Unavailable | 서비스 이용 불가 | 서버가 일시적으로 요청을 처리할 수 없음 | 서버 과부하 |
+
+### 예시
+
+```javascript
+// 사용자 조회 성공
+GET /api/users/123
+Response: 200 OK
+{
+ "id": 123,
+ "name": "홍길동",
+ "email": "hong@example.com"
+}
+
+// 사용자 생성 성공
+POST /api/users
+Response: 201 Created
+Location: /api/users/124
+{
+ "id": 124,
+ "name": "김철수",
+ "email": "kim@example.com"
+}
+
+// 사용자 삭제 성공
+DELETE /api/users/123
+Response: 204 No Content
+
+// 존재하지 않는 사용자 조회
+GET /api/users/999
+Response: 404 Not Found
+{
+ "error": "User not found"
+}
+
+// 잘못된 요청
+POST /api/users
+{
+ "name": "" // 빈 이름
+}
+Response: 400 Bad Request
+{
+ "error": "Name is required"
+}
+```
+
+## RESTful API 설계 예시
+
+### 사용자 관리 API
+
+```javascript
+// 사용자 목록 조회
+GET /api/users
+
+// 특정 사용자 조회
+GET /api/users/123
+
+// 사용자 생성
+POST /api/users
+{
+ "name": "홍길동",
+ "email": "hong@example.com"
+}
+
+// 사용자 전체 수정
+PUT /api/users/123
+{
+ "name": "홍길동",
+ "email": "hong@example.com",
+ "phone": "010-1234-5678"
+}
+
+// 사용자 부분 수정 (이메일만 변경)
+PATCH /api/users/123
+{
+ "email": "newemail@example.com"
+}
+
+// 사용자 삭제
+DELETE /api/users/123
+```
+
+### 사용자의 주문 목록 조회
+
+```javascript
+// 특정 사용자의 모든 주문 조회
+GET /api/users/123/orders
+
+// 특정 사용자의 특정 주문 조회
+GET /api/users/123/orders/456
+
+// 특정 사용자의 새 주문 생성
+POST /api/users/123/orders
+{
+ "productId": 789,
+ "quantity": 2
+}
+```
+
+### 검색 및 필터링
+
+```javascript
+// 쿼리 파라미터를 사용한 검색
+GET /api/users?name=홍길동
+
+// 페이지네이션
+GET /api/users?page=1&limit=20
+
+// 정렬
+GET /api/users?sort=createdAt&order=desc
+
+// 복합 필터링
+GET /api/users?status=active&role=admin&page=1&limit=10
+```
+
+## REST vs GraphQL
+
+REST API의 대안으로 GraphQL이 있습니다. 각각의 특징을 비교하면 다음과 같습니다.
+
+| 특징 | REST | GraphQL |
+|------|------|---------|
+| 데이터 요청 | 여러 엔드포인트 | 단일 엔드포인트 |
+| 응답 형태 | 서버가 정의한 고정 구조 | 클라이언트가 필요한 데이터만 요청 |
+| Over-fetching | 발생 가능 (불필요한 데이터 포함) | 없음 (필요한 데이터만) |
+| Under-fetching | 발생 가능 (추가 요청 필요) | 없음 (한 번에 모든 데이터) |
+| 캐싱 | HTTP 캐싱 활용 용이 | 추가 구현 필요 |
+| 학습 곡선 | 낮음 | 높음 |
+
+#### 예시
+
+```javascript
+// REST API - 사용자 정보와 게시글을 가져오려면 2번의 요청 필요
+GET /api/users/123
+GET /api/users/123/posts
+
+// GraphQL - 한 번의 요청으로 필요한 데이터만 가져오기
+POST /graphql
+{
+ query {
+ user(id: 123) {
+ name
+ email
+ posts {
+ title
+ createdAt
+ }
+ }
+ }
+}
+```
+
+## 실무 적용 팁
+
+**1. API 버저닝**
+
+API가 변경될 때 기존 클라이언트에 영향을 주지 않도록 버전 관리를 합니다.
+
+```javascript
+// URI에 버전 포함
+GET /api/v1/users
+GET /api/v2/users
+
+// 헤더에 버전 포함
+GET /api/users
+Accept: application/vnd.company.v1+json
+```
+
+**2. 에러 응답 일관성 유지**
+
+에러 응답 형식을 일관되게 유지하여 클라이언트에서 처리하기 쉽게 합니다.
+
+```javascript
+{
+ "error": {
+ "code": "USER_NOT_FOUND",
+ "message": "사용자를 찾을 수 없습니다.",
+ "details": {
+ "userId": 123
+ }
+ }
+}
+```
+
+**3. HATEOAS (Hypermedia As The Engine Of Application State)**
+
+응답에 다음 가능한 행동을 링크로 포함하여 클라이언트가 API를 탐색할 수 있게 합니다.
+
+```javascript
+{
+ "id": 123,
+ "name": "홍길동",
+ "email": "hong@example.com",
+ "_links": {
+ "self": { "href": "/api/users/123" },
+ "orders": { "href": "/api/users/123/orders" },
+ "edit": { "href": "/api/users/123" },
+ "delete": { "href": "/api/users/123" }
+ }
+}
+```
+
+RESTful API는 웹의 기본 원칙을 따르면서도 확장 가능하고 유지보수가 쉬운 API를 설계할 수 있게 해줍니다. 위의 원칙들을 잘 이해하고 적용하면 클라이언트와 서버 간의 효율적인 통신을 구현할 수 있습니다.
diff --git a/docs/posts/cs/single-point-of-failure.mdx b/docs/posts/cs/single-point-of-failure.mdx
new file mode 100644
index 0000000..27457d1
--- /dev/null
+++ b/docs/posts/cs/single-point-of-failure.mdx
@@ -0,0 +1,75 @@
+---
+title: '단일 장애 지점(Single Point Of Failure)'
+type: 'concept'
+language: 'CS'
+tags:
+ - SPOF
+dateModified: 2025.09.29
+---
+
+# 단일 장애 지점(Single Point Of Failure)
+
+SPOF 문제는 개발 인프라를 구성할 때 빼 놓을 수 없는 고려점 입니다.
+
+**SPOF(Single Point of Failure)** 는 단일 구성 요소에 장애가 발생했을 때, 전체 시스템이 영향을 받아 서비스를 이용할 수 없게 되는 상황을 의미 합니다.
+예를 들어, 클라이언트가 요청을 보내는 서버가 하나뿐이라면, 해당 서버에 장애가 발생할 경우 서비스를 이용할 수 없게 됩니다.
+
+각 계층별로 SPOF는 반드시 고려해봐야 할 문제 입니다.
+예를 들어, 클라이언트가 서버에 요청을 진행하면 L4 로드밸런서가 요청을 받아 각 Proxy Server에 데이터를 넘기며, Proxy 서버는 요청을 내부의 WAS로 전달 합니다. WAS에서는 Database에 있는 값을 확인해 생성된 데이터를 Client에게 반환 합니다.
+
+```jsx
+client -> L4 Load Balancer -> Proxy Server -> WAS -> Database
+```
+---
+
+### L4 Load Balancer
+
+L4 로드밸런서는 TCP/UDP 레벨에서 요청을 분산 처리하는 역할을 합니다.
+
+해당 계층에서 SPOF를 방지하기 위한 방법은 다음과 같습니다.
+
+- **이중화 구성 (Active-Active 또는 Active-Passive)**
+- **VRRP(Virtual Router Redundancy Protocol)** 를 통한 고가용성 구성
+- **클라우드 환경에서는 관리형 L4 (예: AWS NLB, Azure Load Balancer)** 를 활용해 내결함성 확보
+
+**SPOF 예방 방안**
+
+- L4 LB를 두 대 이상 배치
+- 헬스 체크 기반의 자동 장애 전환(failover) 구성
+
+## Proxy Server
+
+Proxy 서버는 클라이언트 요청을 받아 내부 WAS로 전달하거나 캐싱, 인증, 보안 처리 등의 역할을 합니다.
+
+프록시가 하나일 경우 SPOF가 발생하므로 **수평 확장 및 L4 앞단 분산**이 필수입니다.
+
+**SPOF 예방 방안**
+
+- 여러 대의 프록시 서버를 L4 로드밸런서를 통해 분산
+- Stateless 설계로 프록시 간 장애 영향을 최소화
+- Proxy 레벨에서의 Failover 및 헬스 체크 기능 사용
+
+## WAS
+
+WAS는 실제 비즈니스 로직이 실행되는 계층이다. 하나의 WAS 인스턴스에 모든 처리를 맡길 경우, 서비스 전체 장애가 발생할 수 있습니다.
+
+**SPOF 예방 방안**
+
+- WAS 인스턴스를 **다중 구성(Auto Scaling 포함)**
+- Proxy 또는 L7 Load Balancer에서 **로드밸런싱**
+- **세션 클러스터링 또는 세션 스토리지 분리(Redis 등)** 를 통해 무상태 아키텍처 구현
+
+## Database
+
+데이터베이스는 서비스의 핵심 데이터를 저장하므로, 장애 시 영향도가 가장 큽니다.
+
+DB는 전통적으로 SPOF가 발생하기 쉬운 계층이므로, 고가용성 구성이 필수 입니다.
+
+**SPOF 예방 방안**
+
+- **Master-Slave 또는 Master-Master 복제 구성**
+- **리더-팔로워 구조 + 자동 Failover (예: RDS Multi-AZ, MySQL with MHA)**
+- **샤딩 또는 분산 DB** 도입 고려
+- 정기 백업 및 장애 복구 절차 수립
+
+SPOF는 모든 인프라 구성에서 반드시 고려해야 할 요소이며, 계층별로 고가용성을 확보하는 구조 설계가 안정적인 시스템 운영의 핵심입니다.
diff --git a/docs/posts/database/transaction-Isolation-level.mdx b/docs/posts/database/transaction-Isolation-level.mdx
new file mode 100644
index 0000000..f01c20a
--- /dev/null
+++ b/docs/posts/database/transaction-Isolation-level.mdx
@@ -0,0 +1,87 @@
+---
+title: 트랜잭션 격리 수준
+type: 'concept'
+language: Database
+tags:
+ - Database
+ - Transaction
+dateModified: 2025.09.28
+---
+
+import { ImageContainer } from '/src/components/ui/ImageContainer.tsx';
+
+# 트랜잭션 격리 수준(Transaction Isolation Level)이란?
+
+- 동시에 여러 트랜잭션이 처리될 때, 트랜잭션끼리 얼마나 서로 고립(격리)되어 있는지를 나타내는 것입니다.
+- 즉, 특정 트랜잭션이 다른 트랜잭션에서 변경한 데이터를 볼 수 있는지를 결정합니다.
+
+격리 수준은 크게 4가지로 나뉩니다.
+
+- Read Uncommitted (트렌젝션 레벨 0)
+- Read Committed (트렌젝션 레벨 1)
+- Repeatable Read (트렌젝션 레벨 2)
+- Serializable (트렌젝션 레벨 3)
+
+## Read Uncommitted
+
+- 다른 트랜잭션에서 커밋되지 않은 데이터를 읽을 수 있습니다.
+- 데이터 정합성에 심각한 문제가 발생할 수 있으므로, 일반적으로 사용을 권장하지 않습니다.
+- Dirty Read, Non-Repeatable Read, Phantom Read가 발생할 수 있습니다.
+
+## Read Committed
+
+- 다른 트랜잭션에서 커밋이 완료된 데이터만 읽을 수 있습니다.
+- 한 트랜잭션이 수행되는 동안 다른 트랜잭션은 대기합니다.
+- 대부분의 RDB에서 Default로 사용됩니다.
+- Dirty Read는 방지할 수 있으나, Non-Repeatable Read와 Phantom Read는 발생할 수 있습니다.
+
+## Repeatable Read
+
+- 트랜잭션이 시작되기 전에 커밋된 내용에 대해서만 읽을 수 있습니다.
+- MySQL에서 Default로 사용됩니다.
+- 새로운 레코드가 추가되는 경우에는 동일한 조회 결과를 보장하지 않으므로 Phantom Reads가 발생할 수 있습니다.
+
+## Serializable
+
+- 하나의 트랜잭션에서 사용하는 레코드는 다른 트랜잭션에서 절대 접근할 수 없습니다.
+- 가장 단순하면서도 엄격한 격리 수준으로, 데이터 정합성이 보장되지만 DB Lock이 많이 걸려 동시성이 가장 떨어집니다.
+
+# 트랜잭션의 이상 현상 (Anomaly)
+
+## Dirty Read
+
+- 한 트랜잭션에 의해 변경되었지만 아직 커밋되지 않은 데이터를 다른 트랜잭션에서 읽을 때 발생하는 현상입니다.
+- 이때 읽은 값이 롤백되면 잘못된 데이터가 반영되어 데이터 정합성 문제가 발생할 수 있습니다.
+
+
+
+## Non-Repeatable Read
+
+- 한 트랜잭션 내에서 동일한 SELECT 쿼리를 두 번 실행했을 때, 그 결과가 서로 다르게 나타나는 현상입니다.
+
+
+
+## Phantom Reads
+
+- 한 트랜잭션 안에서 같은 조건으로 두 번 읽을 때, 중간에 다른 트랜잭션이 데이터를 추가/삭제해서 결과가 달라지는 현상입니다.
+
+
+
+# 정리
+
+| | 설명 | 해결 가능한 격리 수준 |
+| ------------------- | ------------------------------------------------------------------------------------- | --------------------- |
+| Dirty Read | 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 문제 | READ COMMITTED 이상 |
+| Non-Repeatable Read | 같은 데이터를 두 번 읽었을 때 값이 달라지는 문제 | REPEATABLE READ 이상 |
+| Phantom Read | 같은 조건으로 조회했는데, 다른 트랜잭션이 데이터를 추가/삭제하여 결과가 달라지는 문제 | SERIALIZABLE |
+
+- 격리 수준이 낮을수록 동시성(성능)은 높아지지만, 데이터 정합성이 떨어질 위험이 커집니다.
+- 격리 수준이 높을수록 데이터 정합성은 보장되지만, 성능이 저하될 수 있습니다.
diff --git a/docs/posts/database/transaction.mdx b/docs/posts/database/transaction.mdx
new file mode 100644
index 0000000..7e4d8a3
--- /dev/null
+++ b/docs/posts/database/transaction.mdx
@@ -0,0 +1,86 @@
+---
+title: '트랜잭션(Transaction)'
+type: 'concept'
+language: 'SQL'
+tags:
+ - Database
+ - Transaction
+dateModified: 2025.09.21
+---
+
+# 트랜잭션(Transaction)이란?
+
+트랜잭션은 데이터베이스의 논리적 작업 단위입니다.
+데이터베이스의 상태를 바꾸기 위해 실행되는 일련의 연산들을 의미하며, 하나의 작업이 성공적으로 수행되면 데이터베이스는 영구적으로 변경됩니다. 반대로 실패하면 모든 변경 사항은 취소됩니다.
+
+---
+
+## 작업 단위란?
+
+DB에서 작업 단위(Unit of Work)는 하나의 논리적인 작업을 수행하는 최소 단위입니다. 즉, 여러 개의 SQL 명령문을 하나로 묶어 "이 작업은 반드시 함께 처리되어야 한다"라는 조건을 만족하는 연산 집합을 의미합니다.
+
+### 예제 1: 은행 계좌 이체
+- A 계좌에서 50,000원 출금
+- B 계좌에 50,000원 입금
+
+위 두 작업은 반드시 함께 실행되어야 합니다. 만약 중간에 오류가 발생해 A 계좌에서만 출금되고 B 계좌에 입금되지 않았다면 전체 작업은 취소(ROLLBACK)되어야 합니다.
+
+### 예제 2: 쇼핑몰 주문 처리
+- 상품 재고 감소
+- 주문 내역 저장
+- 결제 내역 저장
+
+세 가지 작업이 모두 성공해야만 주문이 정상적으로 완료됩니다. 하나라도 실패하면 전체를 취소(ROLLBACK)하여 처음 상태로 되돌립니다.
+
+## 트랜잭션과의 관계
+
+작업 단위는 트랜잭션이 보장하는 논리적인 작업 덩어리입니다. 트랜잭션은 작업 단위를 묶어서 한 번에 처리하거나 오류 발생 시 전부 취소합니다.
+따라서 트랜잭션은 **작업 단위의 온전한 실행을 보장**하는 역할을 합니다.
+
+# 트랜잭션의 특성 (ACID)
+
+트랜잭션이 올바르게 수행되기 위해서는 **ACID 원칙**을 준수해야 합니다.
+
+## 1. Atomicity (원자성)
+
+트랜잭션의 연산은 모두 수행되거나, 하나도 수행되지 않아야 합니다. 예를 들어 A 계좌에서 돈이 빠져나갔는데 B 계좌에 입금되지 않는 상황은 허용되지 않습니다.
+
+원자성은 롤백(ROLLBACK)과 세이브포인트(SAVEPOINT)를 통해 보장됩니다.
+
+```sql
+commit;
+
+update dept set dname = 'QC2' where deptno=70;
+savepoint SP1;
+
+delete from dept where deptno = 70;
+savepoint SP2;
+
+insert into dept values (50, '부서명', '지역명');
+
+rollback; -- 마지막 commit 시점으로 전체 취소
+rollback to savepoint SP1; -- SP1 이후 작업만 취소
+```
+
+## 2. Consistency (일관성)
+
+트랜잭션 전후로 데이터베이스의 무결성이 유지되어야 합니다.
+예를 들어 은행 계좌의 전체 잔액 합계는 변하지 않아야 합니다.
+
+일관성은 주로 트리거(Trigger) 등을 통해 자동으로 보장합니다.
+
+## 3. Isolation (고립성)
+
+여러 트랜잭션이 동시에 실행되더라도 서로의 작업에 영향을 주어서는 안 됩니다.
+한 트랜잭션의 결과는 해당 트랜잭션이 완료될 때까지 다른 트랜잭션에서 참조할 수 없습니다.
+
+## 4. Durability (지속성)
+
+트랜잭션이 완료되면 시스템 장애가 발생하더라도 결과는 유지되어야 합니다.
+이를 위해 Write Ahead Logging(WAL) 같은 기술이 사용됩니다.
+
+# 추가 단어 개념 정리
+- rollback : 실행된 트랜잭션을 취소하고 이전 상태로 되돌리는 것을 의미합니다.
+- savepoint : 트랜잭션 중간에 되돌아갈 지점을 지정하는 것을 의미합니다. ROLLBACK TO 명령으로 해당 시점 이후 작업만 취소가 가능합니다.
+- trigger : 특정 이벤트(insert, update, delete 등)가 발생했을 때 자동으로 실행되는 SQL 코드입니다. 일관성 유지에 활용됩니다.
+- WAL (Write Ahead Logging) : 변경 사항을 실제 DB에 적용하기 전에 로그에 먼저 기록하는 방식을 의미합니다. 장애가 발생해도 로그를 이용해 데이터를 복구할 수 있습니다.
\ No newline at end of file
diff --git a/docs/posts/fe-interview/storage-cookie-session.mdx b/docs/posts/fe-interview/storage-cookie-session.mdx
new file mode 100644
index 0000000..ecbb1d0
--- /dev/null
+++ b/docs/posts/fe-interview/storage-cookie-session.mdx
@@ -0,0 +1,73 @@
+---
+title: 쿠키, 세션, 웹스토리지의 차이점
+type: 'interview'
+language: 'FE-Interview'
+tags:
+ - Web Storage
+ - Cookie
+ - Session
+dateModified: 2025.10.06
+---
+
+## 답변
+
+쿠키, 세션, 웹스토리지는 모두 사용자 상태를 저장하는 방법이지만, 저장 위치와 유지 방식에서 차이점이 있습니다.
+
+- **쿠키(Cookie)** 는 클라이언트에 저장되지만, 서버에 자동 전송되는 데이터로, 주로 로그인 유지나 트래킹에 사용됩니다.
+- **세션(Session)** 은 서버에 저장되는 사용자 상태 정보로, 보안성이 높고 인증 관리에 주로 사용됩니다.
+- **웹 스토리지(Web Storage)** 는 브라우저에만 저장되는 데이터로, 서버로 전송되지 않아 성능이 좋고 상대적으로 용량이 크지만, 보안적으로 민감한 정보를 저장하는 데에는 부적합합니다.
+
+민감한 인증 정보는 가능한 HttpOnly, Secure, SameSite가 설정된 쿠키(또는 서버 세션)로 관리하고, localStorage에는 비민감한 UX 관련 데이터만 저장하는 것이 안전합니다.
+
+
+
+### Q. 세션 데이터를 구분하는 세션 ID는 어디에 저장되나요?
+
+일반적으로 서버는 로그인 시 세션 데이터를 생성하고, 브라우저에 세션 ID를 쿠키로 저장(Set-Cookie 헤더)합니다. 이후 요청 시 이 세션 ID가 함께 전송되어 서버에서 사용자를 식별합니다.
+
+
+
+### Q. 쿠키의 보안상 위험성에 대해 설명해주세요.
+
+쿠키는 자동 전송되는 특성 때문에 공격자가 사용자 권한으로 요청을 보낼 수 있어서 \*CSRF 방어가 필수적이며,
+JavaScript로 쿠키를 읽어 탈취할 수 있어 \*XSS 위험이 있습니다.
+
+이를 방지하기 위해서는 다음과 같은 옵션을 설정할 수 있습니다.
+
+- **HttpOnly** : HttpOnly 쿠키는 클라이언트 JS에서 접근 불가능하므로 XSS 기반 쿠키 탈취를 방지하는 데 유효합니다. (단, 서버에서만 설정 가능합니다.)
+- **Secure** : HTTPS 통신에서만 전송
+- **SameSite** : 쿠키가 크로스 사이트 컨텍스트에서 전송되는 방식을 제어하여 \*CSRF 공격을 방지합니다. (Strict, Lax, None 세 가지 모드가 있으며, None을 사용하려면 Secure 옵션이 반드시 필요합니다.)
+
+
+
+### Q. localStorage와 sessionStorage의 차이를 설명해주세요.
+
+모두 브라우저에 저장되는 key-value 형태의 데이터이지만,
+localStorage는 브라우저를 꺼도 유지되지만, sessionStorage는 탭이 닫히면 삭제된다는 점이 차이입니다.
+
+
+
+### Q. JWT와 위 스토리지들의 관련성에 대해 설명해주세요.
+
+JWT(Json Web Token)는 서버에 세션을 저장하지 않는 stateless 인증 방식으로, 확장성이 뛰어나지만 보안 관리(만료, 탈취, 재발급)에 특히 주의해야 합니다.
+
+저장 시에 HttpOnly Secure Cookie에 넣는 것이 보안상 안전한 방법입니다.
+
+
+
+### 요약
+
+| 구분 | 쿠키 (Cookie) | 세션 (Session) | 웹 스토리지 (Web Storage) |
+| --------- | --------------------------------- | ----------------------- | ------------------------------------------------------ |
+| 저장 위치 | 클라이언트(브라우저) | 서버 | 클라이언트(브라우저) |
+| 만료 시점 | 설정 가능 (기본 브라우저 종료 시) | 브라우저 종료 시 | sessionStorage: 종료 시 / localStorage: 명시적 삭제 시 |
+| 용량 제한 | 약 4KB | 서버 메모리 | 약 5MB (브라우저별 차이 있음) |
+| 보안 | 요청 시 자동 전송 → 탈취 위험 | 서버 관리로 비교적 안전 | JS 접근 가능 → XSS 취약 가능 |
+| 사용 예시 | 로그인 유지, 트래킹 | 로그인 인증 상태 관리 | 사용자 설정, 임시 데이터 저장 |
+
+
+
+### 용어
+
+- **XSS (Cross site Scripting)** : 교차 사이트 스크립팅은 웹사이트에 악성 클라이언트 코드를 삽입하여 민감한 정보를 탈취하거나, 사용자 행위를 대행하거나 웹 사이트를 변조하는 사이버 공격 기법입니다.
+- **CSRF(Cross site request forgery)** : 교차 사이트 간 요청 위조는 신뢰할 수 있는 사용자를 사칭하여 악성 요청이 웹 사이트에 전송되도록 유도하는 사이버 공격 기법입니다.
diff --git a/docs/posts/network/DNS.mdx b/docs/posts/network/DNS.mdx
new file mode 100644
index 0000000..fa85813
--- /dev/null
+++ b/docs/posts/network/DNS.mdx
@@ -0,0 +1,94 @@
+---
+title: 'DNS(Domain Name System)'
+type: 'concept'
+language: 'network'
+tags:
+ - Network
+ - IP
+ - Protocol
+ - Domain
+dateModified: 2025.10.12
+---
+
+import { ImageContainer } from '/src/components/ui/ImageContainer.tsx';
+
+# 1. DNS란?
+
+DNS(Domain Name System)이란 사용자가 웹브라우저에 사람이 읽을 수 있는 도메인 네임을 컴퓨터가 이해할 수 있는 ip주소로 변환하는 분산 데이터베이스 시스템을 의미합니다.
+
+- ```naver.com```이라는 도메인 명을 입력하면 DNS를 통해 해당 도메인 명과 매핑되어있는 IP 주소로 변환해 브라우저가 인터넷 자원을 로드할 수 있도록 도와줍니다.
+ - 도메인 이름 : 체계적인 문자로 표현한 호스트 이름
+ - www.naver.com 의 주소 중 naver.com 부분을 의미합니다.
+ - www는 호스트 네임(host name)이라고 불립니다.
+
+- DNS는 여러 개의 DNS 서버(혹은 네임 서버)들로 구성된 분산 시스템입니다.
+ - OSI 7 계층 중, 애플리케이션 계층에서 동작하는 프로토콜
+ - 기본적으로 UDP/53을 기반으로 사용하지만, 특수한 상황에서는 TCP/53도 사용
+
+## 도메인 네임 구조
+
+
+
+# 2. DNS 동작 방식
+
+
+
+1. 사용자가 브라우저에 www.naver.com 과 같은 도메인을 입력한 뒤, 엔터를 누릅니다.
+2. 현재 컴퓨터에 해당 도메인 명의 IP가 캐싱되어 있거나 C:\Windows\System32\drivers\etc\에 있는 host라는 파일에 있는지 확인하고 없으면 이 URL은 ISP(Internet Service Provider)가 관리하는 DNS resolver에 전송됩니다.
+3. DNS resolver는 캐싱 여부를 확인하고 없으면 root 서버에 도메인명을 보내 .com 도메인의 TLD(최상위 도메인) 서버의 IP주소를 알아냅니다.
+4. TLD 서버에 다시 URL을 요청하고 모든 도메인 네임에 대한 IP주소를 가지고 있는 Authrotitative Name Server의 IP를 반환합니다.
+5. Authrotitative Name Server을 통해 질의하여 해당 도메인과 매핑되는 DNS 레코드의 IP 주소 정보를 찾아서 반환합니다.
+6. 해당 도메인과 일치하는 IP주소를 응답 받습니다.
+7. DNS resolver는 이 IP주소를 클라이언트에게 다시 전송합니다.
+
+## DNS 질의 방식
+
+1. 재귀적 질의(Recursive Query)
+- 클라이언트(사용자)와 재귀적 DNS 서버 사이에서 발생
+- 클라언트 : 재귀적 DNS 서버에게 "내가 원하는 도메인의 IP 주소를 찾아줘"라고 요청
+- 재귀적 DNS 서버(DNS Resolver) : 클라이언트의 요청에 대한 최종적인 답변(IP 주소)을 찾아 클라이언트에게 전달
+
+클라이언트 입장에서는 단 한 번의 요청으로 모든 과정을 위임하는 셈입니다.
+
+2. 반복적 질의(Iterative Query)
+- 재귀적 DNS 서버가 다른 DNS 서버들(루트, TLD, 권한 있는 DNS 서버)에게 정보를 요청하는 과정
+- 재귀적 DNS 서버는 IP 주소를 찾기 위해 다음과 같은 과정 반복 (2번 DNS 동작 방식의 일부)
+ 1. 재귀적 DNS 서버 -> 루트 DNS 서버 (질의) : "내가 찾는 도메인의 정보를 어디서 얻을 수 있니?"
+ 2. 루트 DNS 서버 -> 재귀적 DNS 서버 (응답) : 루트 DNS 서버는 그 도메인의 TLD(최상위 도메인)를 담당하는 TLD DNS 서버의 주소를 알려줍니다.
+ 3. 재귀적 DNS 서버 -> TLD DNS 서버 (질의) : "내가 찾는 도메인의 정보를 어디서 얻을 수 있니?"
+ 4. TLD DNS 서버 -> 재귀적 DNS 서버 (응답) : TLD DNS 서버는 해당 도메인의 정보를 최종적으로 가지고 있는 권한 있는(Authoritative) DNS 서버의 주소를 알려줍니다.
+ 5. 재귀적 DNS 서버 -> 권한 있는 DNS 서버 (질의) : "내가 찾는 도메인의 정보를 어디서 얻을 수 있니?"
+ 6. 권한 있는 DNS 서버 -> 재귀적 DNS 서버 (응답) : 최종 IP 주소
+
+## DNS 주요 구성 요소
+
+각 요소는 DNS가 원활하게 작동하는데 중요한 역할을 합니다.
+
+1. DNS 리졸버(Resolver) : DNS의 요청을 받아들이고 해당 도메인의 IP 주소를 찾아주는 장치나 소프트웨어입니다.
+대부분의 인터넷 서비스 제공자(ISP)에서 이 역할을 수행합니다.
+2. 네임 서버(Name Server) : 도메인 이름과 그에 상응하는 IP 주소 정보를 저장하는 서버입니다. 네임 서버는 여러 종류가 있으며, 각각의 역할에 따라 루트 네임 서버, TLD 네임 서버, 권한있는 네임 서버로 구분됩니다.
+3. 존 파일(Zone File) : 권한있는 네임 서버에 저장된 파일로, 도메인과 IP 주소의 매핑 정보를 포함하고 있습니다.
+4. 레코드(Record) : DNS 레코드는 특정 도메인에 대한 정보를 저장하는 형식입니다.
+
+# 3. DNS 서버 요청 시 UDP를 사용하는 이유
+
+일반적으로 안정적인 데이터 송수신을 위해 TCP를 사용하는 경우가 대부분입니다. 그런데 왜 DNS 서버에 요청을 보낼 때 대부분 UDP를 사용할까요?
+
+1. TCP에 비해 빠른 전송
+ - TCP는 안정적인 데이터 전송을 위해 많은 절차 필요하여 전송 속도가 느릴 수 밖에 없습니다.
+ - 그러면 여기서 DNS 서버 요청 시에도 그런 절차가 필요하지 않을까? 라는 의문이 듭니다.
+ 아무리 속도가 빠르다고 해도 DNS 서버에 요청을 할 때 안정적으로 전송되지 않으면 문제가 생길 수 있기 때문입니다.
+ 게다가 UDP는 TCP와 달리 검출 프로세스가 없기 때문에 다른 사람이 악의적으로 패킷을 가로채서 내용을 변경하더라도 막을 방법이 없습니다. 그래도 왜 UDP를 더 많이 사용할까요?
+2. 요청 데이터의 크기가 작아 전송 계층에서 데이터를 쪼갤 필요 x
+ - 전송 계층에서 데이터그램 하나만으로 충분히 데이터를 담을 수 있으므로, TCP의 이점 중 하나인 순서 보장이 필요 없습니다.
+3. TLS 전송 계층에서 암호화 프로토콜이 자주 쓰이기 때문에 전송 계층에서 데이터의 변조가 발생하더라도 이를 통해 잡아낼 수 있습니다.
+
+- 다만, 2번에서 데이터의 크기가 커서 쪼개야 하거나, 상대 측 방화벽에서 UDP 프로토콜을 사용하는 데이터그램을 차단하는 경우 TCP를 사용해야 합니다.
+
+# 4. DNS 보안 문제
+
+DNS는 네트워크 보안에 있어 매우 중요한 역할을 합니다. 하지만, DNS가 악용될 경우 심각한 보안 문제를 초래할 수 있습니다.
+
+1. DNS 스푸핑(DNS Spoofing) : 공격자가 가짜 DNS 정보를 제공하여 사용자를 의도하지 않은 웹사이트로 유도하는 공격 방식입니다. 이를 통해 악성 웹사이트로 사용자를 유도하거나 개인 정보를 탈취할 수 있습니다.
+2. DNS DDoS 공격 : 분산 서비스 거부(DDoS) 공격은 다수의 장치로부터 DNS 서버에 과도한 요청을 보내 서버를 마비시키는 방식입니다. DNS 서버가 정상적으로 작동하지 않으면, 인터넷 연결에 문제가 생깁니다.
+3. DNSSEC : DNS 보안을 강화하기 위해 개발된 기술로, DNS 레코드가 조작되지 않았는지 검증하는 기능을 제공합니다. DNSSEC는 각 레코드에 디지털 서명을 부여해 사용자가 신뢰할 수 있는 DNS 정보를 받을 수 있도록 보장합니다.
\ No newline at end of file
diff --git a/docs/posts/network/forward-reverse-proxy.mdx b/docs/posts/network/forward-reverse-proxy.mdx
new file mode 100644
index 0000000..e5deda6
--- /dev/null
+++ b/docs/posts/network/forward-reverse-proxy.mdx
@@ -0,0 +1,64 @@
+---
+title: 포워드 프록시와 리버스 프록시
+type: 'concept'
+language: Network
+tags:
+ - Network
+ - Proxy
+dateModified: 2025.10.12
+---
+
+# 프록시란?
+
+- 프록시는 '대리'라는 뜻으로, 클라이언트와 서버 사이에 위치하며 통신을 중계하는 역할을 하는 서버입니다.
+- 프록시는 네트워크 상의 위치에 따라 포워드 프록시와 리버스 프록시로 나뉩니다.
+
+# 포워드 프록시 (Forward Proxy)
+
+`[클라이언트] → [포워드 프록시] → [인터넷] → [웹 서버]`
+
+- 클라이언트와 인터넷 사이에 위치합니다.
+- 클라이언트는 타겟 서버의 주소를 포워드 프록시에 전달하고, 포워드 프록시는 클라이언트를 대신해 해당 서버로 요청을 보내고 응답을 클라이언트에게 반환합니다.
+- 일반적으로 프록시라고 하면 포워드 프록시를 의미합니다.
+
+## 포워드 프록시의 장점
+
+### 캐싱
+
+- HTML, JavaScript, CSS, 이미지 등의 정적 리소스를 원본 서버로부터 캐싱합니다.
+- 이후 동일한 요청이 들어오면 원본 서버에 요청을 전달하지 않고 캐시된 데이터를 반환하여 응답합니다.
+
+### 액세스 제한
+
+- 특정 웹사이트나 불법적인 콘텐츠에 대한 접근을 차단하도록 설정할 수 있습니다.
+
+### 익명성
+
+- 모든 요청이 프록시 서버를 통해 전달되므로 사용자의 실제 IP 주소는 노출되지 않습니다.
+
+# 리버스 프록시 (Reverse Proxy)
+
+`[클라이언트] → [인터넷] → [리버스 프록시] → [웹 서버]`
+
+- 서버와 인터넷 사이에 위치합니다.
+- 클라이언트는 리버스 프록시에 요청을 보내고, 리버스 프록시가 이를 원본 서버로 전달하고 받은 응답을 클라이언트에게 반환합니다.
+
+## 리버스 프록시의 장점
+
+### 로드 밸런싱
+
+- 여러 서버로 트래픽을 분산시켜 서버 과부하를 방지합니다.
+- 특정 서버에 장애가 발생한 경우, 해당 서버로 요청이 전달되지 않도록 설정할 수 있습니다.
+
+### 서버 보안
+
+- 외부에서는 원본 서버가 아닌 프록시 서버의 IP만 알 수 있기 때문에, DDoS 등의 공격으로부터 원본 서버를 보호할 수 있습니다.
+
+### SSL 암호화
+
+- 클라이언트와 서버 간의 SSL/TLS 통신은 암호화·복호화 과정에서 원본 서버에 많은 계산 비용을 발생시킬 수 있습니다.
+- SSL/TLS 관련 작업을 프록시에 위임함으로써 원본 서버의 부담을 줄이고 리소스를 절약할 수 있습니다.
+
+### 캐싱
+
+- 포워드 프록시와 동일하게 리버스 프록시도 캐싱 기능을 수행할 수 있습니다.
diff --git a/docs/posts/network/http.mdx b/docs/posts/network/http.mdx
new file mode 100644
index 0000000..731c883
--- /dev/null
+++ b/docs/posts/network/http.mdx
@@ -0,0 +1,98 @@
+---
+title: 'HTTP 버전별 특징'
+type: 'concept'
+language: 'network'
+tags:
+ - HTTP
+ - Protocol
+dateModified: 2025.10.16
+---
+
+## HTTP 버전
+
+HTTP는 1.0부터 시작해 1.1, 2.0, 3.0에 이르기까지 계속해서 발전해왔습니다. HTTP 버전별 특징과 이전 버전의 단점을 어떻게 극복해 왔는지 살펴보겠습니다.
+
+### HTTP
+
+- HTTP (HyperText Transfer Protocol)은 월드 와이드 웹의 기반이 되는 프로토콜
+- HTTP의 변천사
+ - HTTP/0.9 : 원-라인 프로토콜
+ - HTTP/1.0 : 확장성 만들기
+ - HTTP/1.1 : 표준 프로토콜
+ - HTTP/2 : 더 나은 성능을 위한 프로토콜
+ - HTTP/3 : QUIC를 통한 HTTP
+
+### WWW (World Wide Web)
+
+- TCP/IP 프로토콜 기반의 하이퍼텍스트 시스템
+- 4개의 구성요소
+ - 하이퍼텍스트 문서를 표현하기 위한 텍스트 형식의 하이퍼텍스트 마크업 언어 (HTML)
+ - 하이퍼텍스트 문서를 교환하기 위한 '하이퍼텍스트 전송 프로토콜' (HTTP)
+ - 문서 읽기/쓰기를 위한 클라이언트인 '월드 와이드 웹(WorldWideWeb)'이라고 불리는 첫번째 브라우저
+ - 문서에 접근하도록 해주는 서버, 'httpd'의 초기 버전
+
+
+### HTTP/0.9
+
+- 요청은 단일 라인으로 구성되며 리소스에 대한 경로로 가능한 메서드는 `GET`만 존재
+- HTTP 헤더가 없었고, HTML 파일만 전송 가능
+
+### HTTP/1.0
+
+- 각 요청에 버전 정보가 포함되어 전송(HTTP/1.0이 GET 라인에 붙은 형태
+- 응답 값에 상태 코드 라인 추가
+- 요청 및 응답에 HTTP 개념 추가, 이로 인해 메타데이터 전송 가능
+- Content-Type이 추가되어 HTML 이외의 다른 타입의 문서도 전송 가능
+- 매 요청마다 새로운 TCP 연결을 맺고 끊어야 함
+
+```
+GET /mypage.html HTTP/1.0
+User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
+
+200 OK
+Date: Tue, 15 Nov 1994 08:12:31 GMT
+Server: CERN/3.0 libwww/2.17
+Content-Type: text/html
+
+A page with an image
+
+
+```
+
+### HTTP/1.1
+
+- 동일 도메인 간 TCP 연결 유지 (지속 연결) `Keep-Alive: timeout=5, max=1000`
+- 파이프라이닝 개념 도입
+ - 이전에 1개의 TCP 연결에 1:1 요청/응답만 가능했던 개선되어 여러 개의 요청을 보내는 것이 가능
+
+- 단점
+ - HTTP 문서 내에 포함된 다수의 리소스(image, css, script)를 처리하려면 요청할 리소스의 개수에 비례하여 Latency가 길어짐
+ - 클라이언트가 보낸 요청 순서와 동일하게 응답 순서를 맞춰야 함
+ - 이전 요청에 대한 응답이 지연될 경우 이후 응답 결과에 대한 처리가 지연(Head of Line Blocking, HOL Blocking)
+ - RTT(Round Trip Time) 증가
+ - 커넥션 한 개에 요청 하나를 처리하는 특성 때문에 매번 요청별로 connection을 만들게 되고 TCP 상에서 동작하는 HTTP의 특성상 3-way-handshake가 반복적으로 발생
+ - 불필요한 RTT 증가와 네트워크 지연을 초래하여 성능을 지연시킴
+
+### HTTP/2.0
+
+- HTTP/1.1을 완전하게 재작성한 것이 아니라 프로토콜의 성능에 초점을 맞춰 수정한 버전. Latency나 네트워크, 서버 리소스 사용량 등과 같은 성능 위주로 개선
+
+- Multiplexed Stream
+ - connection 1개로 동시에 여러 개의 메시지를 주고 받을 수 있으며, 응답은 순서에 상관없이 stream으로 주고 받음
+
+- Stream Prioritization
+ - 리소스 간의 의존관계에 따른 우선순위를 설정하여 리소스 로드 문제를 해결 (ex. 이미지 리소스보다 HTML 리소스 로드가 우선)
+
+- Header Compression
+ - HPACK 압축 방식으로 헤더를 압축하여 전송, 중복 헤더 내용의 경우 재전송 하지 않도록 처리
+
+- 단일 TCP 연결, 이로 인해 TCP 커넥션 지연 문제를 다소 해결할 수 있었으나, 패킷 손실 감지 및 재전송 시 모든 스트림 차단되는 단점 존재
+
+### HTTP/3.0
+
+- UDP 기반의 프로토콜인 QUIC(Quick UDP Internet Connection)을 사용
+- 여러 스트림을 실행하고 각 스트림에 대해 독립적으로 패킷 손실 감지 및 재전송하기 때문에 문제가 있는 스트림만 차단
+
+-----
+#### 참고문서
+[MDN HTTP의 진화](https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/Evolution_of_HTTP)
\ No newline at end of file
diff --git a/docs/posts/node.js/event-loop.mdx b/docs/posts/node.js/event-loop.mdx
new file mode 100644
index 0000000..4bf99bc
--- /dev/null
+++ b/docs/posts/node.js/event-loop.mdx
@@ -0,0 +1,57 @@
+---
+title: 'Node.js의 이벤트 루프 이해하기'
+type: 'concept'
+language: 'Node.js'
+tags:
+ - Node.js
+dateModified: 2025.09.21
+---
+
+## 이벤트 루프란?
+이벤트 루프(Event Loop)는 Node.js 환경에서 동기 코드와 비동기 코드의 실행을 조정하고 조율하는 디자인 패턴이자 핵심 메커니즘입니다.
+
+## 이벤트 루프가 필요한 이유
+JavaScript는 동기적이며 싱글 스레드라는 특징을 가지고 있습니다.
+이러한 특징은 파일 읽기, 네트워크 요청, CPU 바운드 작업(계산이 오래 걸리는 작업)을 진행할 때 전체 스레드(메인 스레드)가 멈추는 문제가 발생할 수 있습니다.
+이벤트 루프는 이러한 싱글 스레드 환경에서 비동기 작업을 효율적으로 처리할 수 있게 합니다.
+
+## 이벤트 루프의 구현
+이벤트 루프는 Node.js 런타임을 구성하는 핵심 외부 종속성 중 하나인 `libuv` 라이브러리를 통해 구현됩니다.
+`libuv`는 C로 작성된 크로스 플랫폼 라이브러리로, 비동기 I/O 처리를 지원하며, 이벤트 루프를 구현하여 콜 스택에 어떤 작업을 쌓을지 관장합니다.
+
+## 이벤트 루프의 동작 순서
+이벤트 루프의 실행은 동기 코드 실행 > 비동기 작업 위임 > 이벤트 루프 단계별 콜백 처리 순서로 이루어집니다.
+
+### 1. 이벤트 루프 생성
+### 2. 동기 코드 실행
+생성된 이벤트 루프에 진입하기 전에, 동기 코드가 이벤트 루프 바깥에서 처음부터 끝까지 순차적으로 실행됩니다.
+### 3. 비동기 작업 위임
+동기 코드를 실행하는 동안 `fs.readFile()`나 `setTimeout()` 같은 비동기 함수를 만나면, 해당 작업은 `libuv`에게 위임됩니다.
+`libuv`는 위임받은 비동기 작업을 처리하기 위해 다음과 같이 결정합니다.
+ 1. OS 커널 지원 확인: `libuv`는 운영체제 커널이 해당 작업을 네이티브 비동기 메커니즘으로 지원하는지 확인합니다. 네트워크 I/O(예: 데이터베이스 쿼리, HTTP 요청)처럼 지원되는 작업은 커널에게 요청하고, 워커 스레드 풀을 사용하지 않습니다.
+ 2. 스레드 풀 사용: 커널이 비동기를 지원하지 않거나 시간이 오래 걸리는 작업(블로킹 위험이 있는 작업)은 `libuv`가 관리하는 워커 스레드 풀(Thread Pool)에 위임됩니다.
+ ◦ 사용되는 작업 예시: 파일 시스템(fs 모듈의 동기 작업 제외), DNS 조회, `crypto.pbkdf2()`와 같은 고비용 암호화 함수, `Zlib` 작업 등이 스레드 풀을 사용합니다.
+ ◦ 스레드 풀 크기: `libuv`는 기본적으로 4개의 스레드를 가진 스레드 풀을 생성합니다. `UV_THREADPOOL_SIZE` 환경변수로 최대 1024개까지 늘릴 수 있습니다. (`libuv` 1.30.0 기준)
+### 4. 콜 스택 비우기
+동기 코드가 모두 실행되면 콜 스택은 비워집니다.
+### 5. 이벤트 루프의 순환 6단계 (매크로태스크)
+동기 코드 실행이 완료되고 콜 스택이 비면, 이벤트 루프는 6개의 페이즈(Phase)를 순서대로 방문하며 각 페이즈가 관리하는 매크로태스크 큐의 콜백을 실행합니다.
+ (페이즈에서 페이즈로 넘어가는 것을 `Tick`이라고 합니다.)
+ 1. **Timer Phase (타이머 단계)**: `setTimeout`, `setInterval` 타이머 만료 콜백을 처리합니다.최소 힙 기반으로 관리됩니다.
+ 2. **Pending Callbacks Phase (보류 중인 콜백 단계)**: 이전 루프에서 시스템 한도 등으로 인해 처리되지 못한 I/O 콜백이나 일부 시스템 콜백을 처리합니다.
+ 3. **Idle, Prepare Phase (유휴, 준비 단계)**: Node.js 내부 관리를 위한 단계로, JavaScript 코드를 실행하지 않습니다.
+ 4. **Poll Phase (폴링 단계)**
+ ◦ 새로운 I/O 이벤트를 가져오고 콜백을 실행합니다. 파일 I/O 완료, 네트워크 응답 도착 등 대부분의 I/O 콜백이 실행됩니다.
+ ◦ 큐가 비어있으면 다음 페이즈로 이동하기 전 일정 시간 대기할 수 있습니다.
+ 5. **Check Phase (확인 단계)**: `setImmediate()` 콜백을 처리합니다.
+ 6. **Close Callbacks Phase (종료 콜백 단계)**: `socket.on('close', ...)`와 같은 close 이벤트 핸들러를 처리합니다.
+
+## 마이크로태스크 큐
+이벤트 루프에 속하지는 않지만, 비동기 실행 순서에서 마이크로태스크(Microtask)는 매크로태스크보다 높은 우선순위를 가집니다.
+(마이크로태스크 큐는 `libuv`가 아닌 Node.js 런타임 내부에 독립적으로 구현되어 있습니다.)
+현재 실행 중인 매크로태스크가 완료된 직후, 이벤트 루프가 다음 단계(Phase)로 넘어가기 전에 완전히 비워집니다.
+
+1. `process.nextTick` Queue (nextTickQueue): 모든 마이크로태스크 중 가장 높은 우선순위를 가집니다.
+2. Promise Queue (microTaskQueue): `Promise.then()`, `.catch()`, `.finally()` 콜백을 담고 있으며, `process.nextTick` 다음으로 실행됩니다.
+
+이러한 동작 원리 덕분에 Node.js는 싱글 스레드의 한계를 극복하고 효율적인 비동기 처리를 수행할 수 있습니다.
\ No newline at end of file
diff --git a/docs/posts/react/react-race-condition.mdx b/docs/posts/react/react-race-condition.mdx
new file mode 100644
index 0000000..79adbb1
--- /dev/null
+++ b/docs/posts/react/react-race-condition.mdx
@@ -0,0 +1,220 @@
+---
+title: 'React에서 Race Condition 방지하기'
+type: 'concept'
+language: 'React'
+tags:
+ - React
+ - Race Condition
+dateModified: 2025.09.24
+---
+
+# React에서 Race Condition 방지하기
+
+## Race Condition
+
+Race Condition은 두 개 이상의 비동기 작업이 동시에 실행되면서 예상치 못한 결과가 적용되어 버그나 비일관성을 만드는 상황을 말합니다.
+
+서버 개발 혹은 네트워크 프로그래밍에서 주로 다루는 개념이나, 프론트엔드 환경에서도 발생할 수 있는 상황입니다.
+
+비동기 데이터 패칭과 상태 업데이트가 빈번하게 일어나는 프론트엔드 환경에서도 race condition을 적절히 방지하는 것이 중요합니다.
+
+
+
+## 프론트엔드에서 Race Condition이 발생하는 상황 예시
+
+#### 1. 최신 데이터가 아닌 데이터가 노출되는 검색창
+
+```js
+function SearchComponent() {
+ const [query, setQuery] = useState('');
+ const [result, setResult] = useState('');
+
+ useEffect(() => {
+ if (!query) return;
+
+ // query가 바뀔 때마다 새로운 fetch 요청 발생
+ fetch(`/api/search?q=${query}`)
+ .then((res) => res.json())
+ .then((data) => {
+ // 응답이 도착하면 결과 업데이트
+ setResult(data.result);
+ });
+ }, [query]);
+
+ return (
+
+ );
+}
+```
+
+위와 같이 코드를 작성했을 때, query가 바뀔 때마다 요청하는 데이터의 응답 속도는 네트워크 환경에 따라 달라지게 됩니다.
+
+처음 입력한 검색어 '안녕' 보다 '안'의 요청에 대한 응답이 늦게 도착하는 경우, 최신 검색어인 '안녕'에 대한 결과가 아닌 '안'에 대한 결과가 화면에 표시됩니다.
+
+즉, 사용자에게 엉뚱한 결과가 노출되는 race condition이 발생합니다.
+
+#### 2. 페이지 전환 시 이전 페이지 데이터가 늦게 도착하는 경우
+
+```js
+function UserPage({ userId }) {
+ const [user, setUser] = useState(null);
+
+ useEffect(() => {
+ fetch(`/api/user/${userId}`)
+ .then((res) => res.json())
+ .then((data) => setUser(data));
+ }, [userId]);
+
+ return (
+
+
사용자 정보
+
{JSON.stringify(user, null, 2)}
+
+ );
+}
+```
+
+위 상황에서 사용자가 userId=1 → userId=2로 빠르게 이동하면,
+/api/user/2 요청보다 /api/user/1 응답이 늦게 도착해 화면에 잘못된 유저 정보가 나타날 수 있습니다.
+
+
+
+## React 환경에서 Race Condition 방지 방법
+
+#### 1. useEffect의 cleanUp 함수 사용하기
+
+React의 useEffect 내부에서는 콜백으로 직접 비동기 함수를 넣을 수 없습니다.
+
+```js
+// ❌ 잘못된 코드
+//'effect callbacks are synchronous to prevent race conditions. put the async function inside' 에러 발생
+
+useEffect(async () => {
+ const res = await fetch('/api/data');
+ const json = await res.json();
+ setData(json);
+}, []);
+```
+
+이는 React 팀에서 race condition 방지를 위해 의도적으로 막아둔 것입니다.
+
+useEffect 콜백 자체는 동기적이어야 하며, 비동기 처리는 내부에서 따로 호출해야 합니다.
+
+```js
+// ✅ 올바른 코드
+useEffect(() => {
+ let ignore = false;
+
+ async function fetchData() {
+ const res = await fetch('/api/data');
+ const json = await res.json();
+ if (!ignore) setData(json); // 최신 요청만 반영
+ }
+
+ fetchData();
+
+ return () => {
+ ignore = true; // cleanup으로 이전 요청 무시
+ };
+}, [id]);
+```
+
+위와 같이 useEffect의 콜백함수 내부에 비동기 함수를 넣어서 사용할 수 있습니다.
+
+다만 useEffect 내에 비동기 함수가 존재하면 내부에서 비동기 함수가 생성, 실행을 반복하므로 이전 비동기 함수에 대한 처리를 해주어야 합니다.
+
+여기서는 ignore 플래그를 사용해 클린업 시점 이후에 도착하는 응답은 무시하도록 했습니다.
+
+#### 2. Abort Controller로 이전 요청 취소하기
+
+fetch API는 AbortController를 지원합니다.
+
+이를 이용하면 컴포넌트가 언마운트되거나 의존성이 바뀔 때 이전 요청 자체를 취소할 수 있습니다.
+
+```js
+useEffect(() => {
+ const controller = new AbortController();
+
+ async function fetchData() {
+ try {
+ const res = await fetch(`/api/search?q=${query}`, {
+ signal: controller.signal,
+ });
+ const json = await res.json();
+ setResult(json);
+ } catch (err) {
+ if (err.name !== 'AbortError') {
+ console.error(err);
+ }
+ }
+ }
+
+ fetchData();
+
+ // cleanup 단계에서 이전 요청 취소
+ return () => {
+ controller.abort();
+ };
+}, [query]);
+```
+
+이렇게 하면 query가 바뀔 때마다 이전 요청은 자동 취소되므로, 뒤늦은 응답이 화면에 반영되지 않습니다.
+
+#### 3. unique id로 최신 요청만 반영하기
+
+비동기 요청마다 고유한 ID(ex: 타임스탬프)를 부여하고, 응답 시점에 '가장 최신 요청인지' 확인 후 상태를 반영합니다.
+
+```js
+const lastRequestId = useRef(0);
+
+useEffect(() => {
+ const requestId = Date.now();
+ lastRequestId.current = requestId;
+
+ async function fetchData() {
+ const res = await fetch(`/api/search?q=${query}`);
+ const json = await res.json();
+
+ if (lastRequestId.current === requestId) {
+ setResult(json);
+ }
+ }
+
+ fetchData();
+}, [query]);
+```
+
+이 방식은 AbortController를 지원하지 않는 환경에서 유용합니다.
+
+#### 4. 데이터 페칭 라이브러리 사용하기
+
+React Query, SWR과 같은 데이터 패칭 라이브러리를 사용할 수 있습니다.
+
+이러한 라이브러리들은 요청 중복/취소/최신화 관리 기능을 내장하고 있어 race condition의 위험을 줄여줍니다.
+
+```js
+// React Query 예시
+import { useQuery } from '@tanstack/react-query';
+
+function Search({ query }) {
+ const { data, isLoading } = useQuery({
+ queryKey: ['search', query],
+ queryFn: () => fetch(`/api/search?q=${query}`).then((res) => res.json()),
+ enabled: !!query, // query가 있을 때만 실행
+ });
+
+ if (isLoading) return
로딩 중...
;
+ return
검색 결과: {data.result}
;
+}
+```
+
+
+
+## 정리
+
+- Race condition은 프론트엔드에서도 빈번히 발생하는 문제로, 올바른 관리 없이는 사용자 경험이 깨지거나 심각한 버그로 이어질 수 있으므로 항상 고려해야 합니다.
+
+- React에서는 AbortController, 요청 식별자(unique id) 관리, 혹은 React Query/SWR 같은 라이브러리를 통해 효과적으로 방지 가능합니다.
diff --git a/package.json b/package.json
index b793ac7..0f677e2 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,7 @@
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
+ "react-resizable-panels": "^3.0.6",
"react-router-dom": "^7.4.1"
},
"devDependencies": {
diff --git a/public/docs-assets/database/dirty-read.png b/public/docs-assets/database/dirty-read.png
new file mode 100644
index 0000000..b587dd8
Binary files /dev/null and b/public/docs-assets/database/dirty-read.png differ
diff --git a/public/docs-assets/database/non-repeatable-read.png b/public/docs-assets/database/non-repeatable-read.png
new file mode 100644
index 0000000..961088d
Binary files /dev/null and b/public/docs-assets/database/non-repeatable-read.png differ
diff --git a/public/docs-assets/database/phantom-read.png b/public/docs-assets/database/phantom-read.png
new file mode 100644
index 0000000..1144778
Binary files /dev/null and b/public/docs-assets/database/phantom-read.png differ
diff --git a/public/docs-assets/network/DNS-1.png b/public/docs-assets/network/DNS-1.png
new file mode 100644
index 0000000..c5ad821
Binary files /dev/null and b/public/docs-assets/network/DNS-1.png differ
diff --git a/public/docs-assets/network/DNS-2.png b/public/docs-assets/network/DNS-2.png
new file mode 100644
index 0000000..3eadcd6
Binary files /dev/null and b/public/docs-assets/network/DNS-2.png differ
diff --git a/public/manifest.json b/public/manifest.json
index afbccd7..0f71482 100644
--- a/public/manifest.json
+++ b/public/manifest.json
@@ -3,7 +3,7 @@
"name": "디룩(Delook)",
"author": "@waterbinnn",
"homepage_url": "https://www.delook.co.kr/",
- "version": "1.0.9",
+ "version": "1.0.10",
"description": "개념 학습부터 기술 면접 준비까지, 성장하는 개발자의 새 탭",
"action": {
"default_popup": "popup.html",
diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx
index 2502dd1..cb0089a 100644
--- a/src/components/layout/Layout.tsx
+++ b/src/components/layout/Layout.tsx
@@ -14,7 +14,7 @@ export function Layout() {