Command Palette

Search for a command to run...

이 글의 핵심은 LLM을 내부 검색기가 아니라 다음 token을 반복 생성하는 시스템으로 이해하는 것입니다.

처음에는 LLM을 거대한 검색기처럼 생각했습니다. 질문을 던지면, 모델 안 어딘가에 있는 지식 저장소에서 관련 문서를 꺼내 읽고 답하는 줄 알았습니다. 그래서 예전에 도서관과 교수님의 뇌라는 비유로 정리했습니다.

그 비유는 아직 유효합니다. 외부 문서는 도서관이고, 모델 파라미터는 교수님의 뇌입니다. RAG는 교수님에게 도서관을 붙이는 기술입니다. 다만 이 비유만으로는 실제 실행 비용을 설명하기 어려워졌습니다.

5월에 prefill, decode, KV cache, MoE, batch, sequence length를 이어서 공부하면서 학습 질문이 바뀌었습니다. 이제 확인해야 할 대상은 "LLM이 지식을 어디에 저장하는가"만이 아니었습니다.

질문은 더 구체적인 실행 흐름으로 이동했습니다.

입력 문장은 모델 안에서 어떤 순서로 계산되고, 왜 긴 context와 high reasoning은 비싸지는가?

이 글은 그 질문의 시작점입니다.

이번 재작성에서 앞 3편은 하나의 짧은 학습 경로로 잡습니다.

1편: LLM은 무엇을 하는 시스템인가
2편: token은 어디서 비용이 되는가
3편: Transformer block 안에서는 무엇이 계산되는가

그래서 이 글은 모든 세부사항을 한 번에 설명하려는 글이 아닙니다. 먼저 전체 지도를 만듭니다. LLM이 검색기가 아니라 token 생성 시스템이라는 감각을 잡고, 다음 글들에서 tokenizer와 Transformer block으로 더 좁게 내려갑니다.

LLM은 답을 꺼내 읽는 검색기가 아닙니다. 입력 문장을 token으로 쪼개고, 그 token을 숫자 벡터로 바꾸고, Transformer block을 여러 층 통과시킨 뒤, 다음 token 하나를 고릅니다. 그리고 그 token을 다시 붙여 다음 token을 고릅니다.

이 반복이 우리가 보는 답변입니다.

추론 비용이 내부 구조 학습을 필요하게 만들었습니다

AI Frontier EP 96에서 노정석 대표는 이제 training 이야기보다 inference 이야기가 훨씬 중요해졌다고 짚었습니다. Claude Code나 Codex로 실제 작업을 하면 긴 context를 넣고, reasoning token을 많이 쓰고, 코드와 대화가 계속 바뀌는 workload를 매일 만듭니다.

예전에는 "모델이 얼마나 큰가"가 더 크게 보였습니다. 몇 B parameter인지, 몇 T parameter인지, 어떤 모델이 더 똑똑한지에 시선이 갔습니다. 그런데 실제로 매일 돈과 속도를 만드는 것은 추론입니다.

천 줄짜리 코드를 붙여 넣고 "이거 봐줘"라고 하면, 모델은 바로 답을 쓰는 것이 아닙니다. 먼저 그 긴 입력을 읽어야 합니다. 이 단계가 prefill입니다. 그다음 답변 token을 하나씩 생성합니다. 이 단계가 decode입니다.

이 둘은 비용 특성이 다릅니다.

긴 입력을 읽는 비용 = prefill, prompt length, KV cache 생성
긴 답변을 쓰는 비용 = decode step, output token, KV cache 재사용
긴 대화를 유지하는 비용 = sequence length, cache memory, scheduling

그래서 "왜 input token과 output token 가격이 다를까", "왜 cache 가격이 따로 있을까", "왜 context length가 커지면 티어가 바뀔까" 같은 질문이 생깁니다.

이 질문은 단순한 가격표 해석이 아닙니다. LLM이 실제로 어떻게 계산되는지 모르면 답할 수 없습니다.

EP 94에서 나온 tokenizer 변화 체감도 같은 문제였습니다. vocabulary가 줄어든 것 같고, 같은 작업에 토큰이 더 많이 쓰이는 느낌이 있었습니다. 그때는 "토큰 단가가 오른 건가"로 느껴졌지만, 실제로는 tokenizer, embedding table, LM head, sequence length, KV cache 부담이 한 줄로 연결되어 있었습니다.

그래서 이 시리즈를 다시 씁니다.

기존 글은 LLM을 도서관과 교수님의 뇌로 구분했습니다. 새 글은 그 비유를 출발점으로 삼되, 실제 계산 경로와 추론 인프라까지 내려갑니다.

검색하는 것이 아니라 다음 토큰을 만듭니다

가장 먼저 버려야 했던 오해는 이것이었습니다.

질문
-> 내부 Vector DB 검색
-> 관련 문서 읽기
-> 답변

실제 LLM 기본 동작은 이쪽에 가깝습니다.

질문
-> token IDs
-> embedding vectors
-> Transformer blocks
-> next-token logits
-> 다음 token 선택
-> 다시 입력 뒤에 붙임

물론 RAG를 붙인 시스템은 외부 문서를 검색합니다. 회사 문서, 논문, 매뉴얼, 위키를 Vector DB나 graph index에 넣고, 질문이 들어오면 관련 근거를 찾아 LLM context에 넣을 수 있습니다. 그때 검색하는 것은 LLM 내부가 아니라 외부 retrieval 계층입니다.

이 차이는 뒤에서 RAG/Vector DB/Graph RAG로 다시 자세히 다룹니다. 지금은 하나만 잡으면 됩니다. 검색 시스템은 근거를 가져오고, LLM은 그 근거가 들어온 context를 읽고 다음 token을 생성합니다.

모델 자체가 기본적으로 하는 일은 "문서 검색"이 아니라 "다음 token 예측"입니다.

그래서 기존 01편의 도서관 비유를 다시 쓰면 이렇게 됩니다.

파라미터 = 교수님의 뇌
RAG/Vector DB = 책이 꽂힌 도서관
LLM 추론 = 교수님이 지금 질문을 읽고 다음 단어를 이어 쓰는 과정

중요한 차이가 있습니다. 교수님의 뇌 안에는 원본 문서가 그대로 들어 있지 않습니다. 수많은 학습 데이터에서 얻은 패턴이 parameter라는 숫자들에 분산되어 있습니다. 그래서 출처를 정확히 꺼내는 능력과 그럴듯하게 이어 쓰는 능력은 다릅니다.

이 차이가 hallucination과 RAG의 필요성을 만듭니다.

첫 번째 변환은 토큰입니다

LLM은 글자를 그대로 계산하지 않습니다. 먼저 문장을 token으로 쪼갭니다.

예를 들어 사용자가 이렇게 입력했다고 하자.

LLM에서 sequence length가 뭐예요?

토크나이저는 이 문장을 모델 vocabulary에 있는 조각들로 나눕니다. 어떤 조각은 단어일 수 있고, 어떤 조각은 subword일 수 있고, 어떤 조각은 기호일 수 있습니다.

토큰마다 ID가 있습니다.

"LLM" -> 12345
"sequence" -> 6789
" length" -> 2345
...

이 ID 자체에는 문맥이 없습니다. 그냥 사전 번호입니다. 그래서 다음 단계가 필요합니다.

여기서 token은 사용자에게 바로 비용으로 보입니다. 같은 문장을 더 잘게 쪼개면 sequence length가 길어집니다. sequence length가 길어지면 더 많은 token을 prefill해야 하고, attention이 참고해야 할 위치도 늘어나고, KV cache도 커집니다.

그래서 tokenizer는 단순한 전처리 도구가 아닙니다. 사용자 입장에서는 비용의 입구이고, 모델 입장에서는 embedding table과 LM head의 모양을 결정하는 경계입니다.

EP 94에서 Opus 4.7 tokenizer 변화가 화제가 된 이유도 여기에 있습니다. 그 논의는 공식 스펙 확정이라기보다 사용자 체감과 외부 분석에 가까웠습니다. 하지만 질문 자체는 중요했습니다.

vocabulary가 줄면?
-> embedding table과 LM head의 row 수는 줄 수 있다
-> 같은 텍스트가 더 많은 token으로 쪼개질 수 있다
-> sequence length와 decode 반복, KV cache 부담은 늘 수 있다

비용이 사라지는 것이 아닙니다. 한 축에서 다른 축으로 이동합니다.

Embedding은 token ID를 계산 가능한 벡터로 바꿉니다

token ID는 모델이 계산하기 쉬운 형태가 아닙니다. 모델은 숫자를 다루지만, token ID 숫자 하나를 그대로 크고 작음으로 해석하지 않습니다.

12345번 token이 12346번 token보다 의미상 하나 더 큰 것이 아닙니다.

그래서 embedding table이 필요합니다. embedding은 token ID를 벡터로 바꿉니다.

token ID
-> embedding table lookup
-> [0.12, -0.08, 0.44, ...]

이 벡터가 모델 내부 계산의 출발점입니다.

여기에 위치 정보도 더해집니다. 같은 token이라도 문장 앞에 있는지 뒤에 있는지에 따라 역할이 달라지기 때문입니다. 예전 Transformer 설명에서는 positional encoding을 입력 embedding에 더한다고 말하는 경우가 많고, 요즘 decoder-only LLM에서는 RoPE 같은 방식으로 attention 계산 안에서 위치 정보를 다루는 경우도 많습니다.

입문 단계에서는 이렇게 잡으면 됩니다.

token ID는 사전 번호다.
embedding은 그 번호를 모델 내부 좌표로 바꾸는 입력층이다.
위치 정보는 token 순서를 모델이 알 수 있게 해준다.

Transformer block은 token 벡터를 계속 갱신합니다

embedding을 거친 token 벡터들은 Transformer block stack으로 들어갑니다.

여기서 "stack"이라는 말이 중요합니다. 모델에는 Transformer block이 여러 층 쌓여 있습니다. 그 layer 수는 모델마다 정해져 있습니다. 요청이 들어올 때마다 layer 수가 바뀌는 것이 아닙니다.

한 block 안에는 대략 두 큰 계산이 있습니다.

self-attention
-> MLP / FFN

self-attention은 token들 사이의 관계를 섞습니다.

예를 들어 "그것"이라는 token이 앞 문장의 "KV cache"를 가리키는지, "batch"를 가리키는지, "sequence length"를 가리키는지 문맥을 봐야 합니다. attention은 각 token이 다른 token들을 얼마나 참고할지 계산합니다.

MLP/FFN은 token 간 정보를 새로 섞는다기보다, attention을 통해 문맥이 반영된 각 token 벡터를 더 깊게 변환합니다. 비유하면 attention은 "어떤 주변 정보를 가져올지"를 정하고, MLP는 "가져온 정보를 지금 token 표현 안에서 어떻게 가공할지"를 담당합니다.

이 과정은 한 번만 일어나지 않습니다.

embedding
-> block 1
-> block 2
-> block 3
-> ...
-> final hidden state

layer가 깊다는 것은 token 벡터가 여러 번 가공된다는 뜻입니다. 하지만 이것을 곧바로 "생각을 더 깊게 한다"로 부르면 위험합니다. layer 수는 모델 구조의 고정된 깊입니다. 제품 설정의 highxhigh 같은 reasoning effort와 같은 말이 아닙니다.

LM head는 다음 token 후보를 점수로 바꿉니다

마지막 Transformer block을 지나면 각 token 위치마다 hidden state가 생깁니다.

이제 모델은 마지막 위치의 hidden state를 보고 다음에 올 token을 골라야 합니다. 여기서 LM head가 나옵니다.

LM head는 마지막 hidden state를 vocabulary 전체에 대한 점수로 바꿉니다.

hidden state
-> LM head
-> logits for every token in vocabulary
-> sampling / decoding strategy
-> selected next token

이때 나오는 것은 완성된 문장이 아닙니다. 다음 token 하나입니다.

그래서 자동회귀 생성, autoregressive generation이 필요합니다.

Autoregressive는 방금 만든 token을 다시 붙이는 방식입니다

LLM 답변은 한 번에 완성되지 않습니다.

모델은 다음 token을 하나 고릅니다. 그 token을 지금까지의 문맥 뒤에 붙입니다. 그리고 다시 다음 token을 고릅니다.

입력: "LLM은"
출력 token 1: " 다음"

새 문맥: "LLM은 다음"
출력 token 2: " token"

새 문맥: "LLM은 다음 token"
출력 token 3: "을"

이 반복이 decode입니다.

처음에는 이 반복을 "깊게 생각하는 과정"으로 착각했습니다. token을 하나 만들고 다시 넣고, 또 만들고 다시 넣으니, 많이 반복할수록 더 깊이 생각하는 것처럼 보였습니다.

그런데 이 반복은 기본 생성 방식입니다. 긴 답변을 쓰려면 많이 반복해야 합니다. 짧은 답변이면 적게 반복합니다. 출력 길이와 추론 깊이는 같은 축이 아닙니다.

reasoning effort는 별도의 개념입니다. 더 많은 중간 추론 token을 쓰거나, 더 많은 후보 검토와 검증을 하도록 예산을 주는 설정에 가깝습니다. Transformer layer 수가 늘어나는 것이 아닙니다.

Prefill은 입력을 한 번에 읽는 단계입니다

이제 추론 인프라에서 중요한 구분이 나옵니다.

prefill
decode

prefill은 입력 prompt 전체를 모델에 통과시키는 단계입니다. 사용자가 긴 코드, 긴 문서, 긴 대화 기록을 넣으면 그 전체가 prefill workload가 됩니다.

이 단계에서 모델은 prompt token들을 한 번에 처리하고, 각 layer마다 attention에 필요한 Key/Value를 만듭니다. 이것이 KV cache의 시작점입니다.

정확히는 prefill이 첫 token을 "문장으로 생성"하는 단계라기보다, prompt 전체를 forward pass로 처리해서 다음 상태를 만듭니다.

  • 각 layer의 KV cache를 만들고
  • 마지막 위치에서 첫 출력 token 후보 logits를 만든다

고 보는 편이 맞습니다.

그래서 입력이 길면 Time To First Token이 느려질 수 있습니다. 답변이 아직 나오기도 전에, 모델이 입력 전체를 읽고 KV cache를 만들어야 하기 때문입니다.

EP 96에서 나온 천 줄 코드 예시는 이 감각을 잡기에 좋습니다. Claude Code에서 긴 파일이나 긴 repository context를 넣으면, 사용자는 "모델이 읽고 있다"고 느낍니다. 내부적으로는 prompt token들이 Transformer block stack을 지나면서 각 layer의 K/V를 만들고 있습니다.

이 단계는 병렬화가 잘 되는 편입니다. 입력 token 전체를 한 번에 처리할 수 있기 때문입니다. 하지만 입력이 길수록 계산량과 메모리 사용량이 커집니다.

특히 중요한 점은 prefill이 한 번만 하고 끝나는 단순한 텍스트 읽기가 아니라는 것입니다. 모델의 모든 layer에서 token별 K/V가 만들어집니다.

prompt token 수 x layer 수 x attention head 관련 차원

이 규모로 KV cache가 생깁니다. 그래서 긴 context는 "그냥 많이 읽는 것"이 아니라 GPU memory를 실제로 잡아먹는 상태를 만듭니다.

Decode는 KV cache를 보면서 token을 하나씩 붙입니다

decode는 prefill 이후에 이어집니다.

새 token 하나가 선택되면, 모델은 그 token을 다시 Transformer block stack에 통과시킵니다. 이때 과거 token 전체를 처음부터 다시 계산하면 너무 비쌉니다. 그래서 prefill 때 만들어 둔 KV cache를 씁니다.

Query는 지금 새 token에서 만들어집니다. Key/Value는 과거 token의 것을 cache에서 가져오고, 새 token의 Key/Value만 추가합니다.

기존 KV cache
+ 새 token의 K/V
-> 다음 token 계산

이것이 KV cache가 중요한 이유입니다.

KV cache는 모델 지식이 아닙니다. parameter도 아닙니다. 요청이 들어와 처리되는 동안 GPU memory에 생기는 동적 상태입니다. 요청이 끝나면 사라집니다.

기존 비유를 이어가면 다음과 같습니다.

parameter = 교수님의 오래된 지식
activation = 지금 문제를 풀며 생긴 임시 계산
KV cache = 다음 문장을 쓰기 위해 책상 위에 남겨 둔 attention 메모

decode는 prefill보다 더 순차적입니다. 다음 token을 만들려면 이전 token이 먼저 나와야 합니다. 그래서 autoregressive generation은 latency에 민감합니다.

한 사용자가 긴 답변을 생성하고 있으면 decode step이 계속 돕니다. 여러 사용자가 동시에 답변을 생성하고 있으면 serving engine은 각 sequence의 다음 token 생성을 잘 섞어야 합니다. 여기서 continuous batching 같은 기술이 중요해집니다.

전통적인 batch는 요청을 모아서 한 번에 처리하고 끝내는 느낌입니다. LLM serving에서는 요청마다 prompt 길이도 다르고 output 길이도 다릅니다. 어떤 요청은 짧게 끝나고, 어떤 요청은 reasoning token을 길게 씁니다.

그래서 현대 serving은 실행 중인 batch 안에서 끝난 sequence를 빼고, 새 sequence를 넣고, KV cache 위치를 관리합니다. 이 과정은 단순 batch라기보다 scheduler 문제에 가깝습니다.

Batch와 sequence length는 비용 감각을 만듭니다

여기까지 이해하면 batch와 sequence length도 달라 보입니다.

sequence length는 모델이 처리하는 token 줄의 길입니다. 추론에서는 입력 prompt와 지금까지 생성된 token을 합친 현재 문맥 길이에 가깝습니다.

입력 prompt: 4,000 tokens
생성된 답변: 1,000 tokens
현재 문맥: 5,000 tokens

길어질수록 모델은 더 많은 context를 다룰 수 있습니다. 하지만 attention 비용과 KV cache memory가 커집니다.

batch는 여러 sequence를 묶어 처리하는 단위입니다. 그런데 학습과 추론에서 의미가 다릅니다.

추론 batch는 여러 사용자 요청을 묶어 GPU를 효율적으로 쓰기 위한 scheduling 단위입니다. continuous batching은 실행 중인 batch에 새 요청을 계속 넣고, 끝난 요청은 빼면서 GPU가 쉬지 않게 합니다.

학습 batch는 loss와 gradient를 계산하고 parameter를 업데이트하기 위한 데이터 묶음입니다. LLM 학습에서는 단순 sample 수보다 token 수가 중요합니다.

global batch tokens = global batch size x sequence length

그래서 batch와 sequence length는 "성능 옵션"이 아니라 비용 구조를 읽는 눈입니다.

EP 96에서는 inference 비용을 compute timememory time의 조합으로 보는 관점이 나옵니다. 표현은 다를 수 있지만 핵심은 분명합니다.

계산해야 하는 양
+ 메모리에서 불러오고 유지해야 하는 상태
-> token latency와 serving cost

LLM에서는 둘 다 중요합니다.

Transformer block 안의 matrix multiplication은 GPU compute를 씁니다. 하지만 KV cache는 GPU memory를 잡아먹고, 긴 context에서는 attention이 참조해야 할 과거 token도 늘어납니다. MoE나 multi-GPU sharding으로 가면 GPU 사이 통신도 비용이 됩니다.

그래서 "batch size를 키우면 항상 좋다"도 아니고, "context length가 길수록 무조건 좋다"도 아닙니다. 처리량, 지연시간, 메모리, 사용자 체감 속도 사이의 균형을 잡아야 합니다.

학습에서는 이 감각이 또 달라집니다.

학습 batch = gradient를 계산할 데이터 묶음
추론 batch = 동시에 serving할 sequence 묶음

학습 batch가 크면 gradient가 안정될 수 있고 GPU를 효율적으로 쓸 수 있습니다. 하지만 memory 한계가 있어 micro-batch와 gradient accumulation을 씁니다. 추론 batch는 GPU utilization과 throughput을 높이지만, 잘못 묶으면 latency가 늘어납니다.

같은 batch라는 단어가 전혀 다른 목적을 가집니다.

MoE와 GPU 이야기는 이 다음 단계입니다

여기까지는 하나의 모델이 하나의 큰 계산 그래프처럼 보입니다.

하지만 프론티어 모델 크기로 가면 단순하지 않습니다. 모든 parameter가 한 GPU에 올라가지 않습니다. layer, attention head, MLP, MoE expert, KV cache가 여러 GPU에 나뉠 수 있습니다.

MoE 모델에서는 MLP 자리에 router와 여러 expert MLP가 들어갑니다. 모든 expert를 매번 다 쓰는 것이 아니라, token별로 일부 expert를 고릅니다. 계산량은 줄일 수 있지만, expert가 다른 GPU나 다른 서버에 있으면 token dispatch/gather 통신이 생깁니다.

이때 LLM serving은 신경망 문제이면서 동시에 분산컴퓨팅 문제가 됩니다.

어떤 가중치를 어느 GPU에 둘 것인가
KV cache를 어디에 둘 것인가
prefill과 decode를 같은 장치에서 할 것인가
batch를 어떻게 섞을 것인가
latency와 throughput 중 무엇을 우선할 것인가

이 질문들이 실제 토큰 가격과 응답 속도로 돌아옵니다.

EP96에서 Blackwell NVL72, HBM, GPU 간 통신 이야기가 나온 이유도 여기에 있습니다. 모델 아키텍처는 하드웨어와 분리되어 있지 않습니다. 큰 모델을 서비스하려면 weight를 여러 GPU에 쪼개 올려야 하고, KV cache를 어디에 둘지도 정해야 합니다.

10T 같은 숫자를 들으면 처음에는 "엄청 큰 모델" 정도로 느껴집니다. 그런데 serving 관점에서는 더 구체적으로 봐야 합니다.

10T parameter
-> weight memory
-> precision에 따른 메모리 크기
-> 한 replica를 구성하는 GPU 수
-> replica를 여러 region에 복제하는 방식
-> 요청별 KV cache와 active user 수

프론티어 회사가 "수만 개의 다른 모델"을 운영한다기보다, 소수의 거대한 checkpoint를 여러 shard와 replica로 운영한다고 보는 편이 맞습니다. 한 요청은 보통 전 세계 여러 region의 weight를 동시에 섞어 쓰지 않습니다. 특정 region이나 cluster의 완성된 model replica 하나로 라우팅됩니다.

이 관점이 생기면 LLM serving은 분산 시스템으로 보입니다. compute, memory, network, scheduler, cache placement가 모두 중요해집니다.

LLM은 검색기가 아니라 token 생성 시스템입니다

정리하면 다음과 같습니다.

LLM은 내부 도서관에서 답을 찾아 꺼내는 시스템이 아닙니다. 문장을 token으로 바꾸고, token을 embedding 벡터로 바꾸고, Transformer block stack을 통과시킨 뒤, LM head로 다음 token을 고릅니다. 그리고 그 token을 다시 붙여 다음 token을 만듭니다.

이 흐름 위에 prefill, decode, KV cache가 올라갑니다. 그다음에 batch, sequence length, MoE, GPU serving, token economics가 따라옵니다.

예전에는 "교수님의 뇌와 도서관"이라는 비유로 LLM을 이해했습니다. 이제는 그 비유 위에 실제 실행 흐름을 얹어야 합니다.

그래야 tokenizer 변화가 왜 비용 체감으로 이어지는지, prefill과 decode가 왜 다른 workload인지, KV cache가 왜 메모리 병목이 되는지, batch와 sequence length가 왜 토큰 경제학의 중심인지 판단할 수 있습니다.

다음 글에서는 tokenizer와 embedding을 더 좁혀 봅니다. vocabulary, token ID, embedding table, LM head가 어떻게 이어지고, 왜 "같은 문장이 몇 token으로 쪼개지는가"가 실제 비용과 모델 구조의 경계가 되는지 정리합니다.

이어 읽기

시리즈는 순서대로, 편집 추천은 맥락대로, 비슷한 주제는 태그 기준으로 정리합니다.

시리즈 전체

LLM 공부 시리즈1/9
  1. 1.LLM 공부 01. LLM은 검색기가 아니라 다음 토큰 생성기다
  2. 2.LLM 공부 02. 토큰이 비용을 만든다
  3. 3.LLM 공부 03. Transformer 안에서 문맥이 섞이는 방식
  4. 4.LLM 공부 04. Prefill과 Decode는 LLM이 읽고 쓰는 두 단계다
  5. 5.LLM 공부 05. Batch와 Sequence Length가 속도와 비용을 정한다
  6. 6.LLM 공부 06. MoE와 GPU 클러스터는 거대 모델을 나누어 실행한다
  7. 7.LLM 공부 07. Reasoning Effort가 의미하는 추론 예산
  8. 8.LLM 공부 08. 학습 Batch와 Distillation은 모델을 어떻게 바꾸는가
  9. 9.LLM 공부 09. RAG와 Vector DB는 LLM 밖에서 근거를 찾는다

비슷한 주제의 글

태그가 겹치는 글입니다. 시리즈와 편집 추천에 이미 나온 글은 제외합니다.