-
Notifications
You must be signed in to change notification settings - Fork 0
Database ‐ The Optimizer and Histograms
woojin edited this page Aug 12, 2026
·
2 revisions
- 인덱스가 있다고 무조건 인덱스를 사용하는 것이 아니다.
| 상황 | I/O 패턴 | 비용 |
|---|---|---|
| 인덱스로 소량 조회 | 랜덤 I/O x 소량 | 낮음 |
| 인덱스로 대량 조회 | 랜덤 I/O x 대량 | 매우 높음 |
| 풀 스캔 | 순차 I/O x 전체 | 일정 |
- 조회해야 할 행이 테이블의 상당 부분을 차지하면 랜덤 I/O 비용이 순차 I/O 비용을 넘어서는 순간이 온다. 옵티마이저는 이 비용을 비교해서 총 비용이 더 낮은 쪽을 선택하는 것이다.
- 고정 비율은 없다. 보통 테이블의 10~15% 이상 읽으면 풀 스캔으로 전환된 가능성이 높다.
- MySQL에는 고정된 비율 임계값이 없다. 옵티마이저는 I/O 비용 + CPU 비용을 합산한 후 총 비용을 비교해서 판단한다. 비용은 통계 정보(행 수, 카디널리티, 페이지 수)와 비용 상수에 의해 결정된다. 따라서 테이블의 크기, 행의 길이, 인덱스의 구조, 버퍼 풀에 캐시된 데이터 비율 등에 따라 전환 시점이 달라진다.
- 옵티마이저는 쿼리를 실행할 수 있는 여러 가지 방법을 만들고 각 방법의 비용(Cost)을 추정한 뒤, 가장 비용이 낮은 방법을 선택한다. 이것이 비용 기반 최적화(Cost-Based Optimization)다.
| 비용 유형 | 설명 | 예시 |
|---|---|---|
| I/O 비용 | 디스크 또는 버퍼 풀에서 페이지를 읽는 비용 | 인덱스 페이지 읽기, 데이터 페이지 읽기 |
| CPU 비용 | 행을 비교하고 평가하는 연산 비용 | WHERE 조건 검사, 키 비교, 정렬 |
- 총 비용 = I/O 비용 + CPU 비용이다. 옵티마이저는 이 총 비용이 가장 낮은 실행 계획을 선택한다.
- 비용 계산의 기준이 되는 숫자들은
mysql.server_cost와mysql.engine_cost두 테이블에 저장한다.
-- 서버 비용 상수 조회
SELECT cost_name, cost_value, default_value
FROM mysql.server_cost;| cost_name | cost_value | default_value |
|---|---|---|
disk_temptable_create_cost |
NULL | 20.0 |
disk_temptable_row_cost |
NULL | 0.5 |
key_compare_cost |
NULL | 0.05 |
memory_temptable_create_cost |
NULL | 1.0 |
memory_temptable_row_cost |
NULL | 0.1 |
row_evaluate_cost |
NULL | 0.1 |
-
row_evaluate_cost= 0.1 - 행 하나를 읽어 WHERE 조건에 맞는지 평가하는 비용이다. 풀 스캔처럼 많은 행을 훑을수록 이 값이 차곡차곡 쌓인다. -
key_compare_cost= 0.05 - 키 2개를 비교하는 비용이다. 주로 정렬(ORDER BY)이나 인덱스 키 비교에서 발생한다. -
memory_temptable_create_cost= 1.0 - 메모리에 임시 테이블 하나를 만드는 비용이다. GROUP BY, DISTINCT, 일부 서브쿼리처럼 중간 결과를 담을 공간이 필요할 때 발생한다. -
disk_temtable_create_cost= 20.0 - 디스크에 임시 테이블 하나를 만드는 비용이다. 메모리 임시 테이블이 한계를 넘어 디스크로 내려갈 때 발생한다. -
disk_temptable_row_cost= 0.5 - 디스크 임시 테이블에 행 하나를 처리하는 비용이다.
-- 엔진 비용 상수 조회
SELECT engine_name, cost_name, cost_value, default_value
FROM mysql.engine_cost;-
io_block_read_cost= 1.0 - 디스크에서 페이지를 읽는 비용 -
memory_block_read_cost= 0.25 - 버퍼 풀(메모리)에서 페이지를 읽는 비용 - 디스크 읽기가 메모리 읽기보다 4배 비싸다. 따라서 이 비율이 옵티마이저의 판단에 큰 영향을 미친다. 버퍼 풀에 데이터가 많이 캐시되어 있으면 I/O 비용이 낮아져서 옵티마이저가 더 적극적으로 인덱스를 사용할 수 있다.
- 이런 내용을 토대로 결국 옵티마이저는 비용이 가장 낮은 계획을 고른다.
- InnoDB의 통계 정보는 기본적으로 디스크에 영구 저장된다. 이것을 영구 통계(Persistent Statistics)라고 한다.
-- InnoDB 통계 관련 설정 확인
SHOW VARIABLES LIKE 'innodb_stats%';| Variable_name | Value | 의미 |
|---|---|---|
innodb_stats_persistent |
ON | 통계를 디스크에 영구 저장한다 |
innodb_stats_auto_recalc |
ON | 행의 10% 이상 변경 시 통계를 자동 재계산한다 |
innodb_stats_persistent_sample_pages |
20 | 통계 계산 시 인덱스당 20페이지를 샘플링한다 |
-- 테이블 단위 통계 조회
SELECT database_name, table_name, n_rows,
clustered_index_size, sum_of_other_index_sizes, last_update
FROM mysql.innodb_table_stats
WHERE database_name = 'shop';| database_name | table_name | n_rows | clustered_index_size | sum_of_other_index_sizes | last_update |
|---|---|---|---|---|---|
| shop | category | 47 | 1 | 1 | 2026-05-19 12:05:03 |
| shop | member | 2,911,814 | 19,897 | 19,507 | 2026-06-04 12:42:34 |
| shop | order_item | 8,784,119 | 30,144 | 31,157 | 2026-05-19 12:17:38 |
| shop | orders | 4,858,780 | 18,998 | 25,997 | 2026-06-08 15:04:05 |
| shop | product | 4,863,628 | 24,958 | 43,913 | 2026-06-05 11:19:45 |
| shop | review | 2,995,457 | 11,952 | 13,538 | 2026-05-19 12:18:52 |
-
n_rows: 테이블의 추정 행 수다. 옵티마이저가 "이 테이블을 전부 읽으면 몇 행을 만나는가"를 계산할 때 출발점으로 삼는 값이다. -
clustered_index_size: 클러스터형 인덱스(Clustered Index). 즉 실제 행 데이터가 저장된 본체의 크기다. 단위는 페이지(Page)이고, InnoDB의 한 페이지는 기본 16KB다. -
sum_of_other_index_sizes: 클러스터형 인덱스를 뺀 나머지 세컨더리 인덱스(Secondary Index)들의 크기를 모두 더한 값이다. 이 역시 페이지 단위다. -
last_update: 이 통계가 마지막으로 갱신된 시각이다. 이 값이 오래됐다면 통계가 현실과 어긋나 있을 수 있다는 신호다. - 그런데 이 값은 샘플링 기반 추정 값이기 때문에 정확한 행 수는 아니다. 따라서 실제
COUNT(*)와 비교하면 차이가 날 수 있다.
-- 인덱스 단위 통계 조회
SELECT index_name, stat_name, stat_value, sample_size, stat_description, last_update
FROM mysql.innodb_index_stats
WHERE database_name = 'shop'
AND table_name = 'orders'
AND index_name = 'idx_orders_member_id';| index_name | stat_name | stat_value | sample_size | stat_description | last_update |
|---|---|---|---|---|---|
| idx_orders_member_id | n_diff_pfx01 | 2,032,515 | 20 | member_id | 2026-... |
| idx_orders_member_id | n_diff_pfx02 | 5,133,739 | 20 | member_id, order_id | 2026-... |
| idx_orders_member_id | n_leaf_pages | 8,742 | NULL | Number of leaf pages in the index | 2026-... |
| idx_orders_member_id | size | 10,035 | NULL | Number of pages in the index | 2026-... |
-
index_name: 통계 대상 인덱스 이름이다. 여기서는idx_orders_member_id하나만 조회했다. -
stat_name: 이 행이 어떤 통계인지를 가리키는 이름표이다. 인덱스 하나의 통계가 여러 행으로 나뉘어 저장되는데, 그 종류를 구분하는 키다.-
n_diff_pfx01: 인덱스 선두 1개 컬럼(member_id)의 고유값 수, 즉 카디널리티 추정치다. -
n_diff_pfx02: 선두 2개 컬럼(member_id, order_id)을 묶었을 때의 고유값 수다. 여기서 pfx는 프리픽스(prefix, 앞쪽 컬럼)를 뜻하고, 뒤의 숫자는 선두에서 몇 번째 컬럼까지 묶었는지를 가리킨다.order_id가 PK라 거의 모든 행이 유일하므로 값이 전체 행 수에 가깝게 나온다. -
n_leaf_pages: 인덱스의 리프 페이지(Leaf Page, 실제 키가 저장된 최하단 페이지) 수다. -
size: 리프와 내부 노드를 모두 합한 인덱스 전체 페이지 수다.
-
-
stat_value: 해당 통계의 값이다. -
sample_size: 그 값을 구하려고 샘플링한 페이지 수다. 전수 조사가 아님을 보여준다. 샘플링이 필요 없는 실측 메타정보는 이 값이NULL이다. -
stat_description: 사람이 읽으라고 붙은 설명이다. 어떤 컬럼 조합인지, 또는 무엇을 센 값인지 알려준다.
- 통계가 오래되거나 부정확하다면
ANALYZE TABLE을 실행하면 된다. - 이렇게 실행하면 InnoDB가
innodb_stats_persistent_sample_pages(기본 20) 페이지를 다시 샘플링하여 통계를 갱신한다. - 따라서
mysql.innodb_table_stats와mysql.innodb_index_stats가 즉시 업데이트된다. - Mysql 8.4 InnoDB에서
ANALYZE TABLE은 통계 계산 중에도 INSERT, UPDATE, DELETE가 가능하고, 다른 쿼리를 막지도 않으므로 운영 환경에서 부담 없이 실행할 수 있다. - 다만 통계가 갱신되면 옵티마이저 실행 계획이 바뀔 수 있어 실행 후에는 주요 쿼리 실행 계획이 의도대로인지 확인하는 것이 안전하다.
-
innodb_stats_auto_recalc= ON 이면 통계가 자동으로 재계산된다. - 테이블 행의 10% 이상이 변경되면 자동 재계산이 트리거된다.
- 그리고 이 재계산은 비동기(백그라운드)로 실행된다. 즉, 트리거 직후에도 수 초 동안 오래된 통계가 남아 있을 수 있다. 즉시 갱신이 필요하면
ANALYZE TABLE을 수동으로 실행해야 한다.
운영 중 통계 관련으로 주의해야 할 상황들 정리
- 배치 작업 후 : 야간 배치로 대량 INSERT/DELETE를 수행한 직후에는 통계가 부정확할 수 있다. 배치 작업 스크립트 마지막에
ANALYZE TABLE을 추가하는게 필요할 수 있다.- 배포 직후 : 새 인덱스를 추가하면 해당 인덱스의 통계가 자동으로 생성된다. 하지만 대량 데이터가 이미 있는 테이블에 인덱스를 추가하면, 즉시
ANALYZE TABLE로 정확한 통계를 확보하는 것이 좋다.- 실행 계획이 갑자기 바뀌었을 때 : 어제까지 빨랐는데 갑자기 느려졌다는 보고를 받으면 통계를 먼저 의심한다.
ANALYZE TABLE을 실행하고 실행 계획이 달라지는지 확인한다.
- 인덱스가 있는 컬럼은 옵티마이저가 분포를 들여다볼 수단이 있다.
- 반면 인덱스가 없는 컬럼은 그 수단이 없다. 기본 통계만으로는 추정할 방법이 없다.
- MySQL 8.0에서 도입된 히스토그램(Histogram)은 바로 이 문제를 해결한다. 히스토그램은 컬럼의 값 분포 통계를 옵티마이저에게 제공하여 편향된 데이터에서도 어느 정도 정확한 행 수 추정을 가능케 한다.
-- orders.order_status 컬럼에 히스토그램 생성
ANALYZE TABLE orders UPDATE HISTOGRAM ON order_status;-- 히스토그램 정보 조회
SELECT COLUMN_NAME,
JSON_EXTRACT(HISTOGRAM, '$.\"histogram-type\"') AS histogram_type,
JSON_EXTRACT(HISTOGRAM, '$.\"number-of-buckets-specified\"') AS buckets,
JSON_EXTRACT(HISTOGRAM, '$.\"sampling-rate\"') AS sampling_rate
FROM information_schema.COLUMN_STATISTICS
WHERE TABLE_NAME = 'orders' AND COLUMN_NAME = 'order_status';| COLUMN_NAME | histogram_type | buckets | sampling_rate |
|---|---|---|---|
| order_status | "singleton" | 100 | 0.0148... |
-
COLUMN_NAME: 히스토그램이 생성된 대상 컬럼이다. -
histogram_type: 히스토그램의 유형이다. 값마다 한 칸을 쓰는singleton과 여러 값을 범위로 묶는equi-height두 가지가 있다. -
buckets: 히스토그램을 만들 때 쓸 버킷(칸) 수의 상한이다.WITH n BUCKETS로 지정하지 않으면 기본값 100이 들어간다. 주의할 점은, 이 값은 "최대 몇 칸까지 쓸 수 있는가"라는 상한일 뿐 실제로 만들어진 칸 수가 아니다. -
sampling_rate: 히스토그램을 만들 때 테이블에서 얼마나 표본을 뽑았는지를 나타내는 비율(0~1)이다.0.0148...은 전체의 약 1.48%만 읽어 분포를 추정했다는 뜻이 된다. 1.0이면 전수 조사다. MySQL은histogram_generation_max_mem_size(기본 20MB) 메모리 한도 안에서 가능한 만큼만 샘플링이므로 테이블이 클수록 이 비율은 낮아진다. 즉 히스토그램도 인덱스 통계와 마찬가지로 샘플링 기반 추정이며, 그래서 빈도 값에 약간의 오차가 있을 수 있다.
- Singleton 히스토그램의 버킷은 [값, 누적 빈도] 쌍으로 저장된다.
- 누적 빈도는 줄자에서 각 칸이 끝나는 위치다. 첫 칸부터 지금 칸까지를 모두 더한 값이라 갈수록 커지기만 하고, 마지막 칸은 반드시 1.0이 된다.
- 자체 빈도는 그 칸 하나의 너비, 곧 그 값이 실제로 차지하는 비율이다. (현재 칸이 끝난 위치 − 직전 칸이 끝난 위치)로 구한다.
| 유형 | 조건 | 버킷 구조 | 정밀도 |
|---|---|---|---|
| Singleton | 고유 값 수 <= 버킷 수 | [값, 누적 빈도] |
높음 (각 값의 정확한 빈도) |
| Equi-Height | 고유 값 > 버킷 수 | [하한, 상한, 누적 빈도, 고유 값 수] |
중간 (범위로 근사) |
- 히스토그램은 인덱스가 아니다. 인덱스는 데이터 접근 경로를 제공하고 히스토그램은 옵티마이저의 행 수 추정을 돕는 통계일 뿐이다.
- 쿼리 실행시 실시간으로 참조되는 구조가 아니라, 실행 계획을 선택하는 단계에서만 사용된다.
| 비교 항목 | 인덱스 | 히스토그램 |
|---|---|---|
| 역할 | 데이터 접근 경로 | 행 수 추정 보조 |
| DML 오버헤드 | INSERT/UPDATE/DELETE 시 유지 비용 발생 | 없음 (행이 변경될 때마다 유지하지 않음) |
| 저장 위치 | B+Tree (디스크) | information_schema (딕셔너리) |
| 갱신 방식 | DML 발생 시 자동 반영 | 기본은 수동, MySQL 8.4부터 자동 갱신 설정 가능 |
- 히스토그램은 DML 오버헤드가 없다는 것이 큰 장점이다. 인덱스를 추가하면 INSERT/UPDATE/DELETE가 느려지지만, 히스토그램은 그런 부작용이 없다.
- 히스토그램을 만들 때 수동 갱신(MANUAL UPDATE)과 자동 갱신(AUTO UPDATE) 중 하나를 선택할 수 있다.
-- 갱신 옵션을 생략하면 MANUAL UPDATE가 적용된다.(수동 갱신)
ANALYZE TABLE orders UPDATE HISTOGRAM ON order_status;-- (자동 갱신)
ANALYZE TABLE orders UPDATE HISTOGRAM ON order_status AUTO UPDATE;- 단,
AUTO UPDATE도 INSERT나 UPDATE가 발생할 때마다 히스토그램을 즉시 고치는 기능이 아니다. InnoDB 통계 자동 재계산은 백그라운드에서 비동기로 실행되므로 갱신이 조금 늦을 수 있다.
- 인덱스가 있는 컬럼에서는 히스토그램 효과가 제한적이다. 인덱스가 있으면 옵티마이저가 인덱스 다이브를 통해 더 정확한 행 수를 추정할 수 있기 때문이다. 히스토그램은 인덱스가 없는 컬럼에서 선택도 추정의 주된 소스 역할을 한다.
| 상황 | 히스토그램 효과 |
|---|---|
| 값 분포가 심하게 편향된 컬럼 (인덱스 없음) | 높음 |
| WHERE 절에 자주 등장하는 컬럼 (인덱스 없음) | 높음 |
| 조인 조건의 필터링에 사용되는 컬럼 | 중간 |
| 이미 인덱스가 있는 컬럼 | 낮음 (인덱스 다이브가 우선) |
| 고유 값이 1~2개인 컬럼 | 낮음 (분포가 단순) |
- 히스토그램을 만들 수 없는 경우도 있다. 암호화된 테이블, TEMPORARY 테이블, 공간 데이터 컬럼, JSON 컬럼, 그리고 단일 컬럼 유니크 인덱스가 있는 컬럼에는 히스토그램을 생성할 수 없다.
- Java - Class
- Java - Java Memory
- Java ‐ Solving Concurrency Issues with Synchronized
- Java - synchronized
- Java ‐ Instance Variable & Local Variable vs final
- Java ‐ Object
- Java ‐ Immutable Object
- Java ‐ String
- Java ‐ Wrapper Class
- Java ‐ ENUM
- Java ‐ Nested Class & Inner Class & Local Class & Anonymous Class
- Java ‐ Generic
- Java ‐ ArrayList
- Java ‐ LinkedList
- Java ‐ List
- Java ‐ Set
- Java ‐ Hash
- Java ‐ HashSet
- Java ‐ Map & Stack & Queue
- Java ‐ Iterate & Sort
- Java - Process & Thread
- Java - Thread Creation & Execution
- Java - Thread Control & LifeCycle
- Java - Memory Visibility
- Java - Advanced Synchronization
- Java - Producer/Consumer Problem
- Java - Synchronization & Atomic Operation
- Java - Concurrent Collection
- Java - Thread Pool & Executor Framework
- Java - Character Encoding
- Java - I/O
- Java - File & Files
- Java - Reflection
- Java - Annotation
- Java - Lambda
- Java - Functional Interface
- Java - Lambda vs Anonymous Class
- Java - Method Reference
- Java - Stream API
- Java - Optional
- Java - Default Method
- Java - Parallel Stream
- Java - Functional Programming
- Java - JVM & GC & SOLID
- Java - Data Storage and Memory Allocation: Primitive vs. Reference
- Java ‐ Static Keyword: Efficient Resource Management at the Class Level
- Java ‐ OOP
- Java ‐ Collection Framework Selection Standard
- Java ‐ Multi Threading & Concurrent Programming
- Java ‐ Exception Handling & Advanced Java
- Java ‐ Java 8+
- Java ‐ Java Application Performance Tuning
- Java - CAS
- Java - Virtual Thread
- Java - Benchmark
- Kotlin - Variables, Types, and Operators in Kotlin
- Kotlin - Control Flow in Kotlin
- Kotlin - Object-Oriented Programming in Kotlin
- Kotlin - Functional Programming in Kotlin
- Kotlin - Key Features of Kotlin
- Kotlin - Generics in Kotlin
- Kotlin - Lazy Initialization and Delegation in Kotlin
- Kotlin - Advanced Functional Programming in Kotlin
- Kotlin - Operator Overloading and Kotlin DSL
- Kotlin - Annotations and Reflection in Kotlin
- Kotlin - Miscellaneous Topics in Kotlin
- Coroutine - Limitations of Thread-Based Work & the Emergence of Coroutines
- Coroutine - runBlocking
- Coroutine - CoroutineDispatcher
- Coroutine - Controlling Coroutines with Job
- Coroutine - Receiving Results from Coroutines
- Coroutine - Coroutine Context
- Coroutine - Structured Concurrency
- Coroutine - Exception Handling
- Coroutine - Suspended Functions
- Coroutine - Understanding Coroutines
- Coroutine - Advanced Coroutines
- Coroutine - Coroutine Testing
- Spring - OOP & Spring
- Spring - Spring Container & Spring Bean
- Spring - Singleton Container
- Spring - Dependency Injection
- Spring - Bean LifeCycle Callback
- Spring - Bean Scope
- Spring ‐ Web Server, Web Application server
- Spring ‐ Servlet
- Spring ‐ Servlet & JSP & MVC
- Spring ‐ MVC Framework
- Spring ‐ Spring MVC
- Spring - Thymeleaf
- Spring - Message & Internationalization
- Spring - Validation
- Spring - Bean Validation
- Spring - Cookie & Session
- Spring - Filter & Interceptor
- Spring - API Exception Handling
- Spring - Spring Type Converter
- Spring - File Upload
- Spring - Connection Pool & DataSource
- Spring - Transaction
- Spring ‐ Spring Exception Abstraction
- Spring - Database Access
- Spring ‐ Spring Transaction
- Spring ‐ Spring Transaction Propagation
- Spring ‐ Thread Local
- Spring ‐ Template Method Pattern & Callback Pattern
- Spring ‐ Dynamic Proxy
- Spring ‐ Spring Proxy
- Spring ‐ Bean Processor
- Spring ‐ @Aspect AOP
- Spring ‐ Spring AOP
- Spring ‐ Spring AOP Application
- Spring - MyBatis
- Spring ‐ URL Encoding
- Spring - Cache Annotation
- Spring - Retry
- Spring Security - Initialization
- Spring Security - Authentication Process
- Spring Security - Authentication Architecture
- Spring Security - Authentication Status Persistence Processing Mechanism
- Spring Security - Session Management
- Spring Security - Exception Handling
- Spring Security - Mechanisms for responding to Malicious Attacks
- Spring Security - Authorization Process
- Spring Security - Authorization Architecture
- Spring Security - Multiple Security Settings
- Spring Security - Redis Redundancy Settings
- Spring Security - Event
- Spring Security - Integration
- Spring Security - OAuth 2.0
- Spring Security - OAuth 2.0 Authorization Type
- Spring Security - Open ID Connect
- Spring Security - OAuth 2.0 Client
- Spring Security - OAuth 2.0 Client Fundamentals
- Spring Security - OAuth 2.0 oauth2Login
- Spring Security - OAuth 2.0 oauth2Client
- Spring Security - OAuth 2.0 Resource Server
- Spring Security - OAuth 2.0 Resource Server API
- Spring Security - OAuth 2.0 Verification
- [🔖Spring Security - OAuth 2.0 MAC & RSA Token Verification]
- Spring Security - OAuth 2.0 Resource Server Permission Implementation
- Spring Security - OAuth 2.0 opaque()
- Spring Security - Integrating OAuth 2.0 Client and Resource Server
- Spring Security - Authorization Server
- Spring Security - Authorization Server Main Domain Class
- Spring Security - Authorization Server Endpoint Protocol
- Spring Batch - Scheduler vs Batch
- Spring Batch - Batch Concept
- Spring Batch - Batch Domain
- Spring Batch - Job
- Spring Batch - Step
- Spring Batch - Flow
- Spring Batch - Chunk Process
- Spring Batch - ItemReader
- Spring Batch - ItemWriter
- Spring Batch - ItemProcessor
- Spring Batch - Retry & Error Handling
- Spring Batch - Multi Threads Processing
- [Spring Batch - Batch Event Listener]
- [Spring Batch - Batch Test]
- [Spring Batch - File Processing]
- [Spring Batch - Read and Write Operations in Relational Databases and NoSQL]
- [Spring Batch - FaultTolerant & ItemStream]
- [Spring Batch - Partitioning]
- Spring Batch ‐ Tasklet vs Chunk
- [Spring Batch - Class 2]
- [Spring Batch - Class 3]
- [Spring Batch - Class 4]
- [Spring Batch - Class 5]
- [Spring Batch - Class 6]
- [Spring Batch - Class 7]
- Database - Database Introduction
- Database - Search & Sort
- Database - Data Processing
- Database - Aggregation & Grouping
- Database - Inner Join
- Database - Outer Join & Etc Join
- Database - Sub Query
- Database - UNION
- Database - CASE
- Database - Index
- Database - Data Integrity
- Database - Transaction
- Database - Why Database Design Matters
- Database - Concept Modeling
- Database - Logical Data Modeling
- Database - Identifying Relationship & Non-Identifying Relationship
- Database - Normalization
- Database - Physical Data Modeling
- Database - Common Code Design
- Database - Hierarchical Structure Design
- Database - Data Change History Design
- Database - SOFT DELETE
- Database - Statistics Table Design
- Database - Inheritance Relationship Design
- Database - Entity-Attribute-Value (EAV) Model
- Database - JSON Schema Design
- Database - Database Performance and MySQL Architecture
- Database - Execution Plans 1 - Mastering EXPLAIN
- Database - Execution Plans 2 - Mastering ANALYZE
- Database - Diagnosing Full Table Scans and Composite Index Basics
- Database ‐ Index Internal Structures 1 ‐ B-Tree & B+Tree
- Database - Index Internal Structures 2 - Clustered and Secondary Indexes
- Database - Diagnosing Using filesort and Early Termination
- Database - ICP, Covering, and Skip Scans
- Database - Merge, MRR, New Features, Hints, and Operations
- 🔖Database - The Optimizer and Histograms
- Database - Join Optimization
- Database - Optimizing Sort, Pagination, and Grouping
- Database - Streaming Aggregation and Pre-aggregated Tables
- MySQL ‐ Solving Concurrency Problems using Database-Level Locking
- MySQL - Multi Column Index
- MySQL - Covering Index & RDB vs ElasticSearch Diff
- MySQL - ORDER BY
- MySQL - INSERT
- MySQL - AUTO_INCREMENT_LOCK
- MySQL - Index Dive Using In Query
- MySQL - Why don't use prefix index in default
- MySQL - MySQL LockType
- MySQL - DeadLock Case
- MySQL - NoOffset For Query Tuning
- MySQL ‐ Skip Locked for Session
- MySQL - Checking DB Metrics with SQL Queries
- MySQL - Data Modeling for Practical Service Development
- MySQL - Basic CRUD in MySQL
- MySQL ‐ MySQL Internal Architecture and Storage Engines
- MySQL - MySQL Horizontal Scaling
- MySQL ‐ Operational‐Level System Design
- MySQL - MySQL Fundamentals
- MySQL - Why You Should Use MySQL: JOIN
- MySQL - Must-Know SQL Anti-Patterns
- MySQL - Learning Data Modeling Through Practical Examples
- MySQL - Foreign Key & Strategic Patterns
- MySQL - Advanced Topics in MySQL
- Redis ‐ Redis
- Redis ‐ Redis Manual
- Redis ‐ Redis Cache Strategy
- Redis ‐ Redis Master-Slave
- Redis - Redis Cluster Mode
- Redis - Redis Cluster Example
- Redis - Redis Data Structure
- Redis - Redis Server
- Redis - Reduce DB write load using Redis
- Redis - Solving Concurrency Issues (1)
- Redis ‐ Solving Concurrency Issues (2)
- Redis - Solving Concurrency Issues (3)
- Redis - Implementing Popular Searches
- Redis - API Rate Limiting
- Redis - Geospatial
- Redis - DAU Counting Application
- Redis - Session Management Application
- Redis - Redis Transaction ACID
- Redis - Redis Data Persistence
- Redis - Redis Keys Management
- Redis - Decoupling microservices with Redis Pub/Sub
- Redis - Redis Pipelining & RTT(Round Trip Time)
- Redis - Redis Streams
- Redis - Hash Slot Rebalancing
- JPA - Java Persistence API
- JPA - Entity Mapping & PK Strategy
- JPA ‐ JPA Association Mapping
- JPA - Proxy Association
- JPA - Value Type
- JPA - Dirty Checking vs. Merge: Understanding the Difference in JPA
- JPA - Cascading and Orphan Removal in JPA
- JPA - Introduction to Object-Oriented Query Languages in JPA
- JPA - Spring Data JPA
- JPA ‐ Solving Concurrency Issues with Pessimistic Locking
- JPA ‐ Solving Concurrency Issues with Optimistic Locking
- JPA - Lazy Loading and Performance Optimization in JPA
- JPA - ManyToOne Important Things
- JPA - OneToMany Important Things
- JPA - OSIV
- MicroService Architecture - Service Communications Patterns(RESTful API)
- MicroService Architecture - Service Communications Patterns(GraphQL)
- MicroService Architecture - Service Communications Patterns(gRPC)
- MicroService Architecture - API Gateway Patterns
- MicroService Architecture - Asynchronous Communications Patterns
- MicroService Architecture - Data Management Patterns
- MicroService Architecture - CQRS Patterns
- MicroService Architecture - Distributed Transactions
- [MicroService Architecture - Event-Driven Architecture]
- [MicroService Architecture - Resilience & Observability and Monitoring]
- [MicroService Architecture - Security Patterns]
- [MicroService Architecture - Testing Strategies]
- [MicroService Architecture - Scalability & Caching Patterns]
- [MicroService Architecture - Deployment Patterns]
- [MicroService Architecture - Serverless Architecture]
- [MicroService Architecture - GraphQL]
- [MicroService Architecture - Evolution of Distributed Systems and Their Drawbacks]
- [MicroService Architecture - Protocol Buffers]
- [MicroService Architecture - gRPC Communication Patterns]
- [MicroService Architecture - gRPC Optimization Strategies and Implementation]
- MicroService Architecture - 2PC
- MicroService Architecture - TCC
- MicroService Architecture - SAGA
- Apache Kafka - Kafka Introduction
- Apache Kafka - Kafka CLI
- Apache Kafka - Kafka Producer Application
- Apache Kafka - Kafka Consumer Application
- Apache Kafka - Idempotent Producer & Transactional Producer & Transactional Consumer
- Apache Kafka - Kafka Streams
- Apache Kafka - Kafka Connect
- Apache Kafka - Kafka Topic/Producer/Consumer
- Apache Kafka - Producer Mechanism
- Apache Kafka - Consumer Mechanism
- Apache Kafka - Multi Node Kafka Cluster
- Apache Kafka - Producer & Consumer Serialization/DeSerialization
- Apache Kafka - Topic Segment Management
- Apache Kafka - KSQLDB Stream
- Apache Kafka - KSQLDB Table
- Apache Kafka - KSQLDB Application
- Apache Kafka - Group by & Mview
- [Apache Kafka - Join]
- [Apache Kafka - Time & Windows]
- [Apache Kafka - Connecting KSQLDB to Kafka Connect]
- [Apache Kafka - Kafka Connect]
- [Apache Kafka - JDBC Source Connector]
- [Apache Kafka - JDBC Sink Connector]
- [Apache Kafka - Debezium MySQL CDC Source Connector]
- [Apache Kafka - Schema Registry]
- Apache Kafka - Differences Between RocksDB and In-Memory KeyValueStore in GlobalKTable
- Apache Kafka - Kafka Streams
- [Apache Kafka - Kafka Connect]
- [Apache Kafka - Idempotent Producers and Transactional Producers & Consumers]
- [Apache Kafka - CDC(Change Data Capture)]
- [Apache Flink - Apache Flink Architecture]
- [Apache Flink - Stream Processing]
- [Apache Flink - Data Stream API & Window]
- [Apache Flink - State Management]
- HTTP - Internet Network
- HTTP - URI & Browser Request Flow
- HTTP - HTTP Basic
- HTTP - HTTP Method
- HTTP - HTTP Method Application
- HTTP - HTTP Status Code
- HTTP ‐ HTTP Default Header
- HTTP - HTTP Cache & Condition Request
- AWS - AWS CDK(Cloud Development Kit)
- AWS - Signed URL
- AWS - PreSigned URL
- AWS - Cognito
- AWS - Signed URL Logic
- Docker - Docker
- Docker ‐ Docker CLI
- Docker ‐ Docker Volume
- Docker - Dockerfile Image
- Docker ‐ Docker Compose Container Management
- Docker ‐ Deploy(feat. AWS ECR)
- Docker - Cloud Native Technology
- Docker - Docker Essentials(1)
- Docker - Docker Essentials(2)
- Docker - Docker Network and Storage
- Docker - Building and Managing Containerized Application
- Docker - Container Orchestration
- Docker - Docker Security
- Docker - Logging and Monitoring
- Docker - Advanced Docker Usage
- Docker - Container-to-Container Communication
- [Docker - Docker Image Layer를 활용한 Cache 패턴과 Dangling Image]
- [Docker - Dockerfile 최적화를 위한 빌드 캐싱 및 멀티 스테이지 빌드 패턴]
- [Docker - GitHub Container Registry(GHCR)]
- [Docker - Docker Network 3가지]
- Kubernetes - Probe
- Kubernetes - ConfigMap & Secret
- Kubernetes - PV/PVC & Deployment & Service & HPA
- Kubernetes - Helm & Kustomize
- Kubernetes - Pod 1
- [Kubernetes - Pod 2]
- Kubernetes - Controller 1
- [Kubernetes - Controller 2]
- [Kubernetes - Object]
- [Kubernetes - Ingress & Nginx Application]
- [Kubernetes - Node Scheduling]
- [Kubernetes - Monitoring]
- [Kubernetes - Logging]
- Kubernetes - Deployment using Amazon EKS
- Jenkins - Jenkins Fundamentals & Environment Setup
- Jenkins - Jenkins Jobs: Freestyle & Pipeline
- Jenkins - Jenkins Pipeline Project
- Jenkins - Implementing Continuous Integration(CI) with Jenkins
- Nginx ‐ Nginx Introduction
- Nginx ‐ Nginx Supplementary Summary
- Nginx ‐ Deploying Domain with Nginx
- Nginx ‐ Implementing HTTPS with Nginx
- Nginx ‐ Backend Deployment via Nginx Reverse Proxy
- Nginx ‐ Load Balancing with Nginx
- Nginx - Core Concept
- [Nginx - Advanced Concept]
- [Nginx - Advanced Reverse Proxy]
- Monitoring - Log Level & Filter
- Monitoring - Log Collection with ELK Stack
- Monitoring - Log Monitoring with Kibana
- Monitoring - Server Monitoring with Prometheus and Grafana with Discord Alerts
- Test - Load Testing Fundamentals
- Test - Identifying Bottlenecks with Load Testing
- [Test - Resolving Bottlenecks and Improving Performance]
- Test - JUnit5
- Test - Mockito
- Test - TestContainers
- Test - JMeter
- Test - Chaos Monkey
- Test - ArchUnit
- Test - Appendix: Tips for Better Testing
- [gRPC - Writing .proto Files with Protocol Buffers]
- [gRPC - Various Communication Patterns in gRPC]
- [gRPC - gRPC Optimization Techniques and Advanced Features]
- TDD - Introduction to TDD
- TDD - Iterating with TDD
- TDD - Managing System Data
- TDD - Handling Unexpected Test Failures
- TDD - Abstraction & Reusability
- TDD - Building a Testing DSL
- TDD - Managing Test Context
- TDD - Driving Input Code with Output Tests
- TDD - Pagination Test
- [PostgreSQL - Docker만을 사용하는 경량화된 환경 구성 방법]
- [PostgreSQL - PostgreSQL에서 제공하는 데이터 타입]
- [PostgreSQL - PostgreSQI의 JSONB, 역인덱싱과 활용 방법]
- [PostgreSQL - 데이터베이스 성능을 위한 최적화 패턴 및 전략]
- [PostgreSQL - 트랜잭션과 ACID, Isolation 수준별 차이]
- [PostgreSQL - Database Lock 교착상태와 읽기/쓰기 성능을 보장하는 MVCC 모델]
- [PostgreSQL - pgvector와 벡터 저장, 유사도 검색 패턴 개념]
- [PostgreSQL - 벡터 인덱스 최적화와 벡터 검색과 전문 검색 결합 패턴]
- [PostgreSQL - PostgreSQL 플러그인]
- [PostgreSQL - PostGIS - 공간 쿼리와 GIST 인덱스, 지리 타입과 공간 쿼리를 위한 타입과 기본 함수]
- [PostgreSQL - pg_search - 검색 엔진 없이 텍스트 검색 구현과 주의사항]
- [PostgreSQL - 단일 인스턴스 한계를 극복하는 분산 패턴과 스케줄링, 분산 환경 구축 방법]
- [PostgreSQL - Citus - 분산 테이블과 분산 쿼리를 위한 Extension과 데이터 분산 처리]
- [PostgreSQL - pg_cron - PostgreSQL로 구성하는 CronJob]
- [PostgreSQL - 스케줄러 + 분산 처리를 동시에 도입하는 주기적 집계 쿼리 패턴]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - Kafka + Debezium을 활용한 CDC 패턴 설계]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - Temporal을 활용한 워크플로우 패턴]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - Docker와 경량 이미지를 활용한 환경 구축 방법]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - Kafka에서의 메시지 Delivery Guarantee]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - 실시간 동기화의 핵심 CDC]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - MySQL Binary Log 기반의 CDC]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - Binary Log 기반의 CDC 구현 플랫폼 Debezium이란?]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - Debezium Architecture]
- [Workflow-Driven Techniques for Large-Scale Traffic Processing - Debezium Architecture Best Practice와 주의사항]
- Reactive Programming - Everything About Reactive Programming & Core Concepts of Reactive Programming
- Reactive Programming - Mastering Reactor Operators in WebFlux & A Deep Dive into WebFlux Operators
- Reactive Programming - Best Practices and Optional Patterns in WebFlux & Key Practical Patterns for WebFlux Development
- Reactive Programming - Practical WebFlux Patterns with Spring Boot & Building Applications with Spring Boot and WebFlux
- ElasticSearch - Elasticsearch Core Concepts
- ElasticSearch - Basic Search Features & Architecture
- ElasticSearch - Korean Optimized Search
- ElasticSearch - Defining Data Types: Understanding Mappings
- ElasticSearch - Commonly Used Search APIs
- ElasticSearch - Managing Documents (1)
- ElasticSearch - Managing Documents (2)
- ElasticSearch - Analysis and Mapping
- ElasticSearch - All About Search
- ElasticSearch - Query Joins
- ElasticSearch - Processing Query Results
- ElasticSearch - Aggregations
- ElasticSearch - Tips for Improving Search Results
- [ElasticSearch - Elasticsearch Overview]
- [ElasticSearch - Elasticsearch Internals]
- [ElasticSearch - Monitoring]
- [ElasticSearch - Troubleshooting]
- Design Pattern - Strategy
- Design Pattern - Factory Method
- Design Pattern - Abstract Factory
- Design Pattern - Singleton
- Design Pattern - Observer
- Design Pattern - Publisher - Subscriber
- Design Pattern - Decorator
- Design Pattern - Adapter
- Design Pattern - Builder
- Design Pattern - Template Method
- Design Pattern - Facade
- Design Pattern - Proxy
- Design Pattern - Command
- Design Pattern - Chain of Responsibility
- Design Pattern - State
- Design Pattern - Composite
- [Clean Spring - Domain-Driven Development]
- [Clean Spring - Domain-Driven Development with Design Patterns]
- [Clean Spring - Developing Membership Application with Hexagonal Architecture]
- [Clean Spring - JPA and Domain Model Patterns]
- [Clean Spring - Designing a Consistent Domain Model with Aggregates]
- [Clean Spring - Web API Adapter]
- [Clean Spring - Hexagonal Architecture: Ports]
- [Clean Spring - Hexagonal Architecture: Application Components]
- [Clean Spring - Test Improvement & Architecture Validation]
- [Clean Spring - Developing Application Components]
- (Effective Java Item 1) Java ‐ 생성자 대신 정적 팩토리 메서드를 고려하라
- (Effective Java Item 2) Java - 생성자에 매개변수가 많다면 빌더를 고려하라
- (Effective Java Item 3) Java - private 생성자나 열거 타입으로 싱글턴임을 보증하라
- (Effective Java Item 4) Java - 인스턴스화를 막으려거든 private 생성자를 사용하라
- (Effective Java Item 5) Java - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
- (Effective Java Item 6) Java ‐ 불필요한 객체 생성을 피하라
- (Effective Java Item 7) Java - 다 쓴 객체 참조를 해제하라
- (Effective Java Item 8) Java - finalizer와 cleaner 사용을 피하라
- (Effective Java Item 9) Java - try‐finally보다는 try‐with‐resources를 사용하라
- (Effective Java Item 10) Java ‐ equals는 일반 규약을 지켜 재정의하라
- (Effective Java Item 11) Java ‐ equals를 재정의하려거든 hashCode도 재정의하라
- (Effective Java Item 12) Java - toString을 항상 재정의하라
- (Effective Java Item 13) Java ‐ clone 재정의는 주의해서 진행하라
- (Effective Java Item 14) Java ‐ Comparable을 구현할지 고려하라
- (Effective Java Item 15) Java ‐ 클래스와 멤버의 접근 권한을 최소화하라
- (Effective Java Item 16) Java ‐ public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라
- (Effective Java Item 17) Java ‐ 변경 가능성을 최소화하라
- (Effective Java Item 18) Java ‐ 상속보다는 컴포지션을 사용하라
- (Effective Java Item 19) Java ‐ 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라
- (Effective Java Item 20) Java ‐ 추상 클래스보다는 인터페이스를 우선하라
- (Effective Java Item 21) Java ‐ 인터페이스는 구현하는 쪽을 생각해 설계하라
- (Effective Java Item 22) Java ‐ 인터페이스는 타입을 정의하는 용도로만 사용하라
- (Effective Java Item 23) Java ‐ 태그 달린 클래스보다는 클래스 계층구조를 활용하라
- (Effective Java Item 24) Java ‐ 멤버 클래스는 되도록 static으로 만들라
- (Effective Java Item 25) Java ‐ 톱레벨 클래스는 한 파일에 하나만 담으라
- (Effective Java Item 26) Java ‐ 로 타입은 사용하지 말라
- (Effective Java Item 27) Java ‐ 비검사 경고를 제거하라
- (Effective Java Item 28) Java ‐ 배열보다는 리스트를 사용하라
- (Effective Java Item 29) Java ‐ 이왕이면 제네릭 타입으로 만들라
- (Effective Java Item 30) Java ‐ 이왕이면 제네릭 메서드로 만들라
- (Effective Java Item 31) Java - 한정적 와일드카드를 사용해 API 유연성을 높이라
- (Effective Java Item 32) Java - 제네릭과 가변인수를 함께 쓸 때는 신중하라
- (Effective Java Item 33) Java ‐ 타입 안전 이종 컨테이너를 고려하라
- (Effective Java Item 34) Java - int 상수 대신 열거 타입을 사용하라
- (Effective Java Item 35) Java - ordinal 메서드 대신 인스턴스 필드를 사용하라
- (Effective Java Item 36) Java ‐ 비트 필드 대신 EnumSet을 사용하라
- (Effective Java Item 37) Java ‐ ordinal 인덱싱 대신 EnumMap을 사용하라
- (Effective Java Item 38) Java ‐ 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라
- (Effective Java Item 39) Java ‐ 명명 패턴보다 애너테이션을 사용하라[Effective Java Item 39]
- (Effective Java Item 40) Java ‐ @Override 어노테이션을 일괄되게 사용하라
- (Effective Java Item 41) Java ‐ 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라
- (Effective Java Item 42) Java ‐ 익명 클래스보다는 람다를 사용하라
- (Effective Java Item 43) Java ‐ 람다보다는 메서드 참조를 사용하라
- (Effective Java Item 44) Java - 표준 함수형 인터페이스를 사용하라
- (Effective Java Item 45) Java - 스트림은 주의해서 사용하라
- (Effective Java Item 46) Java - 스트림에서는 부작용 없는 함수를 사용하라
- (Effective Java Item 47) Java - 반환 타입으로는 스트림보다 컬렉션이 낫다
- (Effective Java Item 48) Java ‐ 스트림 병렬화는 주의해서 사용하라
- (Effective Java Item 49) Java ‐ 매개변수가 유효한지 검사하라
- (Effective Java Item 50) Java ‐ 적시에 방어적 복사본을 만들라
- (Effective Java Item 51) Java ‐ 메서드 시그니처를 신중히 설계하라
- (Effective Java Item 52) Java ‐ 다중정의는 신중히 사용하라
- (Effective Java Item 53) Java ‐ 가변인수는 신중히 사용하라
- (Effective Java Item 54) Java - null이 아닌, 빈 컬렉션이나 배열을 반환하라
- (Effective Java Item 55) Java ‐ 옵셔널 반환은 신중히 하라
- (Effective Java Item 56) Java ‐ 공개된 API 요소에는 항상 문서화 주석을 사용하라
- (Effective Java Item 57) Java ‐ 지역변수의 범위를 최소화하라
- (Effective Java Item 58) Java ‐ 전통적인 for문보다는 for‐each문을 사용하라
- (Effective Java Item 59) Java ‐ 라이브러리를 익히고 사용하라
- (Effective Java Item 60) Java ‐ 정확한 답이 필요하다면 float와 double은 피하라
- (Effective Java Item 61) Java ‐ 박싱된 기본 타입보다는 기본 타입을 사용하라
- (Effective Java Item 62) Java ‐ 다른 타입이 적절하다면 문자열 사용을 피하라
- (Effective Java Item 63) Java ‐ 문자열 연결은 느리니 주의하라
- (Effective Java Item 64) Java ‐ 객체는 인터페이스를 사용해 참조하라
- (Effective Java Item 65) Java ‐ 리플렉션보다는 인터페이스를 사용하라
- (Effective Java Item 66) Java ‐ 네이티브 메서드는 신중히 사용하라
- (Effective Java Item 67) Java ‐ 최적화는 신중히 하라
- (Effective Java Item 68) Java ‐ 일반적으로 통용되는 명명 규칙을 따르라
- (Effective Java Item 69) Java ‐ 예외는 진짜 예외 상황에만 사용하라
- (Effective Java Item 70) Java ‐ 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라
- (Effective Java Item 71) Java ‐ 필요 없는 검사 예외 사용은 피하라
- (Effective Java Item 72) Java ‐ 표준 예외를 사용하라
- (Effective Java Item 73) Java ‐ 추상화 수준에 맞는 예외를 던지라
- (Effective Java Item 74) Java ‐ 메서드가 던지는 모든 예외를 문서화하라
- (Effective Java Item 75) Java ‐ 예외의 상세 메시지에 실패 관련 정보를 담으라
- (Effective Java Item 76) Java ‐ 가능한 한 실패 원자적으로 만들라
- (Effective Java Item 77) Java ‐ 예외를 무시하지 말라
- (Effective Java Item 78) Java - 공유 중인 가변 데이터는 동기화해 사용하라
- (Effective Java Item 79) Java - 과도한 동기화는 피하라
- (Effective Java Item 80) Java - 쓰레드보다는 실행자, 태스크, 스트림을 애용하라
- (Effective Java Item 81) Java - wait와 notify는 동시성 유틸리티를 애용하라
- (Effective Java Item 82) Java - 쓰레드 안전성 수준을 문서화하라
- (Effective Java Item 83) Java - 지연 초기화는 신중히 사용하라
- (Effective Java Item 84) Java - 프로그램의 동작을 쓰레드 스케줄러에 기대지 말라
- (Effective Java Item 85) Java - 자바 직렬화의 대안을 찾으라
- (Effective Java Item 86) Java - Serializable을 구현할지는 신중히 결정하라
- (Effective Java Item 87) Java - 커스텀 직렬화 형태를 고려해보라
- (Effective Java Item 88) Java - readObject 메서드는 방어적으로 작성하라
- (Effective Java Item 89) Java - 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라
- [🔖(Effective Java Item 90) Java - 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라]
- (Effective Kotlin Item 1) Kotlin - 가변성을 제한하라
- (Effective Kotlin Item 2) Kotlin - 임계 영역을 제거하라
- (Effective Kotlin Item 3) Kotlin - 가능한 한 빨리 플랫폼 타입을 제거하라
- (Effective Kotlin Item 4) Kotlin - 변수의 스코프를 최소화하라
- (Effective Kotlin Item 5) Kotlin - 인수와 상태에 대한 기대치를 명시하라
- (Effective Kotlin Item 6) Kotlin - 사용자 정의 오류보다 표준 오류를 선호하라
- (Effective Kotlin Item 7) Kotlin - 결과가 없을 가능성이 있는 경우 널 가능 또는 Result 반환 타입을 선호하라
- (Effective Kotlin Item 8) Kotlin - use를 사용하여 리소스를 닫아라
- (Effective Kotlin Item 9) Kotlin - 단위 테스트를 작성하라
- (Effective Kotlin Item 10) Kotlin - 가독성을 목표로 설계하라
- (Effective Kotlin Item 11) Kotlin - 연산자의 의미는 함수의 이름과 일치해야 한다
- (Effective Kotlin Item 12) Kotlin - 가독성을 높이려면 연산자를 사용하라
- (Effective Kotlin Item 13) Kotlin - 타입 명시를 고려하라
- (Effective Kotlin Item 14) Kotlin - 리시버를 명시적으로 참조하라
- (Effective Kotlin Item 15) Kotlin - 프로퍼티는 동작이 아닌 상태를 나타내야 한다
- (Effective Kotlin Item 16) Kotlin - Unit?을 반환이나 연산에 사용하지 말라
- (Effective Kotlin Item 17) Kotlin - 이름 있는 인수 사용을 고려하라
- (Effective Kotlin Item 18) Kotlin - 코딩 컨벤션을 준수하라
- (Effective Kotlin Item 19) Kotlin - knowledge를 반복하지 말라
- (Effective Kotlin Item 20) Kotlin - 일반적인 알고리즘을 반복하지 말라
- (Effective Kotlin Item 21) Kotlin - 일반적인 알고리즘을 구현할 때 제네릭을 사용하라
- (Effective Kotlin Item 22) Kotlin - 타입 매개변수의 섀도잉을 피하라
- (Effective Kotlin Item 23) Kotlin - 제네릭 타입에 변성 한정자 사용을 고려하라
- (Effective Kotlin Item 24) Kotlin - 공통 모듈을 추출해서 여러 플랫폼에서 재사용하라
- (Effective Kotlin Item 25) Kotlin - 각각의 함수는 하나의 추상화 수준으로 작성하라
- (Effective Kotlin Item 26) Kotlin - 변경으로부터 코드를 보호하려면 추상화를 사용하라
- (Effective Kotlin Item 27) Kotlin - API 안정성을 명시하라
- (Effective Kotlin Item 28) Kotlin - 외부 API를 래핑하는 것을 고려하라
- (Effective Kotlin Item 29) Kotlin - 가시성을 최소화하라
- (Effective Kotlin Item 30) Kotlin - 문서로 규약을 정의하라
- (Effective Kotlin Item 31) Kotlin - 추상화 규약을 준수하라
- (Effective Kotlin Item 32) Kotlin - 보조 생성자 대신 팩토리 함수를 고려하라
- (Effective Kotlin Item 33) Kotlin - 이름 있는 선택적 인수를 갖는 기본 생성자 사용을 고려하라
- (Effective Kotlin Item 34) Kotlin - 복잡한 객체 생성을 위해 DSL 정의를 고려하라
- (Effective Kotlin Item 35) Kotlin - 의존성 주입을 고려하라
- (Effective Kotlin Item 36) Kotlin - 상속보다 합성을 선호하라
- (Effective Kotlin Item 37) Kotlin - 데이터 묶음을 표현할 때 data 한정자를 사용하라
- (Effective Kotlin Item 38) Kotlin - 연산과 행동을 전달하려면 함수 타입이나 함수형 인터페이스를 사용하라
- (Effective Kotlin Item 39) Kotlin - 제한된 계층구조를 표현하기 위해 sealed 클래스와 sealed 인터페이스를 사용하라
- [(Effective Kotlin Item 40) Kotlin - 태그 클래스 대신 클래스 계층구조를 선호하라]
- [(Effective Kotlin Item 41) Kotlin - 열거형 클래스를 사용해서 값 목록을 나타내라]
- [(Effective Kotlin Item 42) Kotlin - equals의 규약을 준수하라]
- [(Effective Kotlin Item 43) Kotlin - hashCode의 규약을 준수하라]
- [(Effective Kotlin Item 44) Kotlin - compareTo의 규약을 준수하라]
- [(Effective Kotlin Item 45) Kotlin - API의 필수적이지 않은 부분을 확장으로 추출하는 것을 고려하라]
- [(Effective Kotlin Item 46) Kotlin - 멤버 확장 함수를 피하라]
- (Effective Kotlin Item 3) Kotlin - variable
- (Effective Kotlin Item 4) Kotlin - primitive types, literals, and operations
- (Effective Kotlin Item 5) Kotlin - control Flow: if, when, try, and while
- (Effective Kotlin Item 6) Kotlin - function
- (Effective Kotlin Item 7) Kotlin - for
- (Effective Kotlin Item 8) Kotlin - Null Safety and Nullable Types
- (Effective Kotlin Item 9) Kotlin - Class
- (Effective Kotlin Item 10) Kotlin - Extend
- (Effective Kotlin Item 11) Kotlin - Data Class
- (Effective Kotlin Item 12) Kotlin - Object
- (Effective Kotlin Item 13) Kotlin ‐ Exception
- (Effective Kotlin Item 14) Kotlin - Enum Classes
- (Effective Kotlin Item 15) Kotlin - Sealed Classes and Interfaces
- (Effective Kotlin Item 16) Kotlin - Annotation Classes
- (Effective Kotlin Item 17) Kotlin - Extensions
- (Effective Kotlin Item 18) Kotlin - Collections
- (Effective Kotlin Item 19) Kotlin - Operator Overloading
- (Effective Kotlin Item 20) Kotlin - The Beauty of the Type System
- (Effective Kotlin Item 21) Kotlin - Generic
- Reactive Programming - Reactive Streams
- Reactive Programming - Blocking I/O & Non-Blocking I/O
- Reactive Programming - Reactor Outline
- Reactive Programming - Marble Diagram
- Reactive Programming - Cold Sequence & Hot Sequence
- [Reactive Programming - Backpressure]
- [Reactive Programming - Sinks]
- [Reactive Programming - Scheduler]
- [Reactive Programming - Context]
- [Reactive Programming - Debugging]
- [Reactive Programming - Testing]
- [Reactive Programming - Operators]
- [Reactive Programming - Spring Webflux]
- [Reactive Programming - Annotation Based Controller]
- [Reactive Programming - Functional Endpoint]
- [Reactive Programming - Spring Data R2DBC]
- [Reactive Programming - Exception Handling]
- [Reactive Programming - WebClient]
- [Reactive Programming - Reactive Streaming Data Processing]
- 가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 사용자 수에 따른 규모 확장성
- 가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 개략적인 규모 추정
- 가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 처리율 제한 장치의 설계
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 안정 해시 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 키-값 저장소 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 분산 시스템을 위한 유일 ID 생성기 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - URL 단축기 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 웹 크롤러 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 알림 시스템 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 뉴스 피드 시스템 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 채팅 시스템 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 검색어 자동완성 시스템 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 유튜브 설계]
- [가상 면접 사례로 배우는 대규모 시스템 설계 기초 1 - 구글 드라이브 설계]
- (Clean Code 2) Clean Code - 의미 있는 이름
- (Clean Code 3) Clean Code - 함수
- (Clean Code 4) Clean Code - 주석
- (Clean Code 5) Clean Code - 형식 맞추기
- (Clean Code 6) Clean Code - 객체와 자료구조
- (Clean Code 7) Clean Code - 오류 처리
- (Clean Code 8) Clean Code - 경계
- (Clean Code 9) Clean Code - 단위 테스트
- (Clean Code 10) Clean Code - 클래스
📖 리팩토링 2판⭐
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 - 느려진 서비스, 어디부터 봐야 할까
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 - 성능을 좌우하는 DB 설계와 쿼리
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ 외부 연동이 문제일 때 살펴봐야 할 것들
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ 비동기 연동, 언제 어떻게 써야 할까
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ 동시성, 데이터가 꼬이기 전에 잡아야 한다
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ IO 병목, 어떻게 해결하지
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ 실무에서 꼭 필요한 보안 지식
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ 모르면 답답해지는 네트워크 기초
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ 자주 쓰는 서버 구조와 설계 패턴
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ 처음 해보는 성능 테스트를 위한 기본 정리
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ NoSQL 이해하기
- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 ‐ DB로 분산 잠금 구현하기
- 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴 - 객체 지향
- 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴 - 다형성과 추상 타입
- 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴 - 재사용: 상속보단 조립
- 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴 - 설계 원칙: SOLID
- 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴 - DI(Dependency Injection)와 서비스 로케이터
- 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴 - 주요 디자인 패턴
- [Real MySQL 8.0 - 인덱스]
- [Real MySQL 8.0 - 실행 계획]
- [Real MySQL 8.0 - 아키텍처]
- [Real MySQL 8.0 - 트랜잭션과 잠금]
- 객체지향의 사실과 오해(역할, 책임, 협력 관점에서 본 객체지향) - 협력하는 객체들의 공동체
- 객체지향의 사실과 오해(역할, 책임, 협력 관점에서 본 객체지향) - 이상한 나라의 객체
- [객체지향의 사실과 오해(역할, 책임, 협력 관점에서 본 객체지향) - 타입과 추상화]
- [객체지향의 사실과 오해(역할, 책임, 협력 관점에서 본 객체지향) - 역할, 책임, 협력]
- [객체지향의 사실과 오해(역할, 책임, 협력 관점에서 본 객체지향) - 책임과 메시지]
- [객체지향의 사실과 오해(역할, 책임, 협력 관점에서 본 객체지향) - 객체 지도]