In defense of shallow technical knowledge
얕은 기술 지식에 대한 변론
Whenever a new piece of technology comes out (these days, mostly AI) I go to some effort to understand it. Usually I end up writing a post about it, so I can be confident that I do understand1.
새로운 기술이 나올 때마다(요즘은 주로 AI) 저는 그것을 이해하기 위해 어느 정도 노력을 기울입니다. 보통은 그것에 대해 글을 쓰게 되는데, 그래야 제가 1 을(를) 이해하고 있다는 확신을 가질 수 있기 때문입니다.
What’s the point of doing this? Obviously my explainers about diffusion models are shallow: certainly they aren’t detailed enough to do useful research on diffusion models. What’s the point, then?
이런 노력을 하는 이유가 뭘까요? 분명히 제가 확산 모델에 대해 설명하는 글은 얕습니다: 확산 모델에 대해 유용한 연구를 할 만큼 자세하지는 않습니다. 그렇다면 그 목적은 무엇일까요?
In my view, good engineering requires having reliable shallow intuitions about how things work. You don’t need a full understanding of how things work, or even a good enough understanding to work usefully in that area of the stack. But it’s still useful to try to minimize the number of technologies in your stack that are purely black boxes.
제 생각에, 좋은 엔지니어링은 사물이 어떻게 작동하는지에 대한 신뢰할 수 있는 얕은 직관을 갖는 것을 필요로 합니다. 사물이 어떻게 작동하는지 완전히 이해할 필요도 없고, 그 스택 영역에서 유용하게 일할 만큼 충분히 이해할 필요도 없습니다. 하지만 순수하게 블랙박스인 기술의 수를 최소화하려고 노력하는 것은 여전히 유용합니다.
Database indexes 데이터베이스 인덱스
Let me give an example that isn’t about AI. If you’ve done any kind of web development, you rely heavily on database indexes. For some engineers, these are black boxes. All they know is what they do: specifically, that if you set up the right kind of index, you can turn very slow queries into very fast ones. Sometimes they’ve learned some more rules of thumb, such that you should avoid having too many unused indexes.
AI와 관련 없는 예를 들어보겠습니다. 웹 개발을 해본 적이 있다면 데이터베이스 인덱스에 크게 의존하게 됩니다. 일부 엔지니어에게 인덱스는 블랙박스와 같습니다. 그들이 아는 것은 인덱스가 하는 일뿐입니다. 구체적으로, 올바른 종류의 인덱스를 설정하면 매우 느린 쿼리를 매우 빠르게 바꿀 수 있다는 점입니다. 때로는 사용하지 않는 인덱스가 너무 많으면 피해야 한다는 경험적 규칙도 배웠을 수 있습니다.
Instead of learning rules of thumb, you should instead learn at a very high level what an index is: essentially a large dictionary that maps some combination of column values to the location on-disk where the full record is stored. This is not good enough to let you implement a database index. But it’s very useful when you’re using a database index. From that definition, you can conclude:
경험적 규칙을 배우기보다는 인덱스가 무엇인지 아주 높은 수준에서 이해하는 것이 좋습니다. 본질적으로 인덱스는 일부 열 값 조합을 전체 레코드가 저장된 디스크상의 위치에 매핑하는 큰 사전과 같습니다. 이것만으로 데이터베이스 인덱스를 구현할 수는 없지만, 인덱스를 사용할 때 매우 유용합니다. 이 정의에서 다음과 같은 결론을 내릴 수 있습니다.
- That without an index, the database is forced to iterate over every single record in the table to satisfy your query (unless your query explicitly sets a
LIMITon records returned)
인덱스가 없으면 데이터베이스는 쿼리를 만족시키기 위해 테이블의 모든 레코드를 반복해서 검사해야 한다는 점입니다(쿼리가 반환되는 레코드에 대해 명시적으로LIMIT을 설정하지 않는 한). - That an index is only useful if it matches the actual query your application is making. If you index on “name plus email” and then start querying on “name plus address”, your index won’t be used and you’re back to the full table scan described in (1)
인덱스는 애플리케이션이 실제로 수행하는 쿼리와 일치할 때만 유용합니다. 예를 들어 “이름과 이메일”로 인덱스를 생성했는데 “이름과 주소”로 쿼리를 시작하면, 인덱스가 사용되지 않고 (1)에서 설명한 전체 테이블 스캔으로 돌아가게 됩니다. - That indexes massively speed up reads, but must slow down database writes and updates, because each change must also be made again in the index “dictionary”
인덱스는 읽기 속도를 대폭 향상시키지만, 각 변경 사항을 인덱스 “사전”에도 다시 반영해야 하므로 데이터베이스 쓰기 및 업데이트 속도를 늦출 수밖에 없습니다.
I don’t think it’s necessarily useful to go deeper than this, unless you’re actively maintaining a database. You could learn about the data structures that represent the index, about how they’re stored on-disk and in-memory, about all the tricks that go into updating them efficiently, and so on. All that stuff is very interesting. But it will very rarely inform the database migration or query you’re writing.
데이터베이스를 적극적으로 관리하지 않는 한, 이보다 더 깊이 들어가는 것은 반드시 유용하지 않다고 생각합니다. 인덱스를 나타내는 데이터 구조, 디스크와 메모리에 저장되는 방식, 효율적으로 업데이트하기 위한 여러 기법 등에 대해 배울 수 있습니다. 이 모든 것은 매우 흥미롭지만, 데이터베이스 마이그레이션이나 작성 중인 쿼리에 영향을 미치는 경우는 매우 드뭅니다.
Large language models 대형 언어 모델
At GitHub, I work with large language models every day. I’ve worked on the Copilot side of things, and now I work on GitHub Models, where we’re actually exposing language model inference directly via our API. It has been very useful to understand what language models actually are, and I’ve spent a lot of time doing that (coding LLM inference from scratch in Javascript and Ruby, for instance).
GitHub에서 저는 매일 대형 언어 모델을 다루고 있습니다. 저는 Copilot 쪽에서 일했었고, 지금은 GitHub Models에서 일하고 있는데, 여기서는 실제로 API를 통해 언어 모델 추론을 직접 노출하고 있습니다. 언어 모델이 실제로 무엇인지 이해하는 것이 매우 유용했으며, 이를 위해 많은 시간을 투자했습니다(예를 들어, Javascript와 Ruby로 LLM 추론을 처음부터 코딩하는 작업 등).
As one example of how it’s been useful, some time ago I implemented a “json output” mode for the Models playground. It slightly surprised me to learn that although almost every model in the catalog technically supported json output, the smaller ones did not support it well. Specifically, when json mode was enabled, the smaller models would sometimes get stuck and endlessly output \n after a few characters of valid json.
유용했던 한 가지 예로, 얼마 전 Models 플레이그라운드에 “json 출력” 모드를 구현한 적이 있습니다. 카탈로그에 있는 거의 모든 모델이 기술적으로 json 출력을 지원함에도 불구하고, 작은 모델들은 이를 잘 지원하지 못한다는 사실에 다소 놀랐습니다. 구체적으로, json 모드가 활성화되면 작은 모델들이 가끔 멈추고 유효한 json 몇 글자 뒤에 \n 을 끝없이 출력하는 현상이 있었습니다.
However, that behavior is actually predictable. Language models do not directly output words (or tokens). Instead, they output the entire set of probabilities over all possible tokens every time, and a simple function (called a sampler) selects a token from that set - for instance, by picking the token with the highest probability. When a model supports json output, what that typically means is that the sampler can be told to only select tokens that continue a valid json string.
그러나 그 행동은 실제로 예측 가능합니다. 언어 모델은 단어(또는 토큰)를 직접 출력하지 않습니다. 대신, 매번 가능한 모든 토큰에 대한 전체 확률 집합을 출력하고, 간단한 함수(샘플러라고 함)가 그 집합에서 토큰을 선택합니다 - 예를 들어, 가장 높은 확률을 가진 토큰을 선택하는 식입니다. 모델이 json 출력을 지원할 때, 일반적으로 이는 샘플러가 유효한 json 문자열을 계속 이어갈 수 있는 토큰만 선택하도록 지시할 수 있다는 의미입니다.
For instance, when picking the first token in the model response, the sampler will only pick from \n, { or [. This works great for large models or models trained on a lot of json. After a few tokens, they “get the idea” that they’re outputting json and do most of the work themselves. But small models don’t really understand json, so they might think \n is more likely than a token like [. Once they’ve outputted a couple of \n characters, that makes them even more likely to output more. So you end up in a loop where the model prefers to keep spitting out new lines than to try and continue the json string.
예를 들어, 모델 응답에서 첫 번째 토큰을 선택할 때, 샘플러는 \n , { 또는 [ 중에서만 선택합니다. 이는 대형 모델이나 많은 json으로 학습된 모델에 매우 효과적입니다. 몇 개의 토큰 후에는 모델이 자신이 json을 출력하고 있다는 “아이디어를 얻어” 대부분의 작업을 스스로 수행합니다. 그러나 작은 모델은 json을 제대로 이해하지 못해 \n 이 [ 같은 토큰보다 더 가능성이 높다고 생각할 수 있습니다. 몇 개의 \n 문자를 출력하면, 더 많은 \n를 출력할 가능성이 더욱 커집니다. 그래서 모델이 json 문자열을 계속 이어가려 하기보다는 새 줄을 계속 출력하는 루프에 빠지게 됩니다.
It was useful to understand the problem at this level of detail, because it let me conclude:
이 문제를 이 정도 수준의 세부사항으로 이해하는 것이 유용했는데, 그 덕분에 나는 다음과 같은 결론을 내릴 수 있었습니다:
- Some small models will just never be able to reliably output json unprompted - this isn’t a bug in the setup, but a feature of the actual technology
일부 소형 모델은 프롬프트 없이 신뢰할 수 있게 json을 출력할 수 없습니다 - 이것은 설정의 버그가 아니라 실제 기술의 특징입니다 - Even so, you could probably get those small models to do it by prompting them with some sample json, so it’s in the context
그럼에도 불구하고, 샘플 json을 프롬프트로 제공하여 문맥에 포함시키면 소형 모델도 아마 json 출력을 할 수 있을 것입니다 - Just because a sampler supports a strategy doesn’t mean it plays nicely with the actual model
샘플러가 어떤 전략을 지원한다고 해서 실제 모델과 잘 작동한다는 의미는 아닙니다
We ended up supporting json mode for most models via the API, but not giving a UI option for it except for models that were smart enough to output json effectively. That way we don’t confuse people who aren’t familiar with the points above and just want to try the LLMs out, while still letting developers have control over what they’re building with the models.
우리는 대부분의 모델에 대해 API를 통해 json 모드를 지원하게 되었지만, json을 효과적으로 출력할 만큼 똑똑한 모델에만 UI 옵션을 제공했습니다. 이렇게 하면 위에서 언급한 점들을 잘 모르는 사용자들이 혼란스러워하지 않고 LLMs를 쉽게 사용해볼 수 있으면서도, 개발자들이 모델을 활용해 무엇을 만들지 제어할 수 있도록 했습니다.
Where do you draw the line?
경계는 어디에 두나요?
If a basic understanding of how technologies work is helpful when you’re writing software on top of them, would a full understanding be even more useful? Maybe! But I think there’s a limit to how deep you can go on everything. I would rather have a basic understanding of database indexes, sharding, HTTP, pre-forking web servers, Ruby on Rails (and the twelve other things that go into normal web dev work) than to have a full understanding of only one of those things.
기술이 어떻게 작동하는지 기본적으로 이해하는 것이 그 위에 소프트웨어를 작성할 때 도움이 된다면, 완전한 이해는 더 유용할까요? 아마도요! 하지만 모든 것에 대해 너무 깊이 파고들 수 있는 한계가 있다고 생각합니다. 데이터베이스 인덱스, 샤딩, HTTP, 프리포킹 웹 서버, Ruby on Rails(그리고 일반적인 웹 개발 작업에 포함되는 열두 가지 다른 것들)에 대해 기본적인 이해를 갖는 것이 그 중 하나만 완전히 이해하는 것보다 낫다고 생각합니다.
This question probably resolves to the familiar “go broad or go deep” discussion: should a software engineer try to have broad knowledge about many things, or to have deep knowledge about one specialty? I think it’s fine to go either route. Personally, I’ve tried to go broad in my own career, and I’d give the same advice to people who ask. I think it makes you more versatile and puts you in a better spot to react to new trends (such as AI). But if you really like databases or networking or whatever, you can certainly spend a career diving deep into that.
이 질문은 아마도 익숙한 “넓게 가야 할까, 깊게 가야 할까” 논쟁으로 귀결될 것입니다: 소프트웨어 엔지니어가 여러 분야에 대해 폭넓은 지식을 갖추어야 할까요, 아니면 한 분야에 대해 깊은 지식을 가져야 할까요? 저는 어느 쪽이든 괜찮다고 생각합니다. 개인적으로 저는 제 경력에서 폭넓게 가려고 노력해왔고, 질문하는 사람들에게도 같은 조언을 합니다. 그렇게 하면 더 다재다능해지고 AI와 같은 새로운 트렌드에 더 잘 대응할 수 있는 위치에 있게 됩니다. 하지만 데이터베이스나 네트워킹 등 특정 분야를 정말 좋아한다면, 그 분야에 깊이 파고들어 경력을 쌓는 것도 분명 가능합니다.
Tips for building intuitions
직관을 키우기 위한 팁
When I’m trying to figure out how something works, I aim to be able to explain it to a smart junior engineer. I think this is a pretty good imaginary person to target: technical enough that you’re not starting from scratch, but not so technical that you can handwave complicated areas with jargon. For instance, if you’re trying to understand diffusion models, you shouldn’t say “oh, then the model denoises and the quality gets better”. You should put enough effort in to understand what denoising is and why doing it would improve the quality of the output.
무언가가 어떻게 작동하는지 이해하려고 할 때, 저는 똑똑한 주니어 엔지니어에게 설명할 수 있을 정도를 목표로 합니다. 이 가상의 인물은 꽤 좋은 대상이라고 생각합니다. 완전히 처음부터 시작하는 것은 아니지만, 전문 용어로 복잡한 부분을 대충 넘길 수 있을 정도로 너무 기술적이지도 않은 사람입니다. 예를 들어, 확산 모델을 이해하려고 할 때 “아, 그러면 모델이 노이즈를 제거하고 품질이 좋아진다”라고 말해서는 안 됩니다. 노이즈 제거가 무엇인지, 그리고 왜 그것이 출력 품질을 향상시키는지 이해하려고 충분히 노력해야 합니다.
Paradoxically, I think going too deep into the mathematics can be harmful, not helpful. In computer science papers, a complex mathematical expression often covers a simple intuition. SwiGLU is just “allow the neural net to gate parts of the network on or off”. Rotary position embedding is just “pack relative-position information into a token embedding by rotating it into the complex plane”. The mathematical details are less useful than understanding why binary states are useful, or what information about relative position is for.
역설적이게도, 수학에 너무 깊이 파고드는 것은 도움이 되기보다는 해로울 수 있다고 생각합니다. 컴퓨터 과학 논문에서 복잡한 수학적 표현은 종종 단순한 직관을 감추고 있습니다. SwiGLU는 단지 “신경망이 네트워크의 일부를 켜거나 끌 수 있도록 허용하는 것”입니다. Rotary position embedding은 단지 “토큰 임베딩을 복소 평면으로 회전시켜 상대 위치 정보를 담는 것”입니다. 이진 상태가 왜 유용한지, 또는 상대 위치에 대한 정보가 무엇을 위한 것인지 이해하는 것이 수학적 세부사항보다 더 유용합니다.
One way to tell that you’ve done it right is if you can automatically think through a bunch of specific consequences, like the ones I listed in the two example sections. The whole point of this process is to be able to have useful intuitions about these technologies (e.g. “oh, text diffusion would be a good fit for the AI box in Google search results because it has to be very fast and has a mostly fixed size). If you’re not having any useful intuitions, that probably reflects a flaw in your understanding.
잘했다는 것을 알 수 있는 한 가지 방법은 내가 두 개의 예시 섹션에서 나열한 것과 같은 구체적인 결과들을 자동으로 생각해낼 수 있는지 여부입니다. 이 과정의 핵심은 이러한 기술들에 대해 유용한 직관을 가질 수 있는 것입니다(예: “아, 텍스트 확산은 구글 검색 결과의 AI 박스에 적합한데, 매우 빠르게 작동해야 하고 크기가 대부분 고정되어 있기 때문이야”). 만약 유용한 직관이 전혀 없다면, 그것은 아마도 당신의 이해에 결함이 있음을 반영하는 것입니다.
I don’t read through a lot of secondary sources, unless they’re unusually good. I try to read at least one original paper (e.g. the classic attention paper for transformers), and I chat a lot with language models. For most of the things I’m learning, the language model already knows all the details, so I don’t have to actually supply the paper in-context - for instance, the “Attention is all you need” paper is well-known enough that all current language models can answer questions about it from scratch.
나는 특별히 뛰어나지 않은 한 2차 자료를 많이 읽지 않습니다. 최소한 하나의 원본 논문(예: 트랜스포머의 고전적인 어텐션 논문)은 읽으려고 노력하며, 언어 모델과 많이 대화합니다. 내가 배우는 대부분의 것들에 대해 언어 모델은 이미 모든 세부 사항을 알고 있기 때문에, 실제로 논문을 문맥에 제공할 필요가 없습니다. 예를 들어, “Attention is all you need” 논문은 너무나 잘 알려져 있어서 현재 모든 언어 모델이 처음부터 그에 관한 질문에 답할 수 있습니다.
I find language models to be also very useful for checking my results. When I write one of my explainer posts, I always copy-paste it into a model chat (usually o3) and ask for a careful fact-check. This is great for flushing out subtle misunderstandings. For this to work well, you have to actually write down some claims. I like to write down a bunch of the “consequences” I mentioned above. Doing that makes it easy for the language model to do fact-checking. For instance, when I was learning about diffusion models, I thought that they’d be faster than autoregressive models with a full context window, but I was wrong about that. Figuring out why I was wrong helped me fix a misunderstanding I had about how caching worked with the key-value attention matrix in transformers.
저는 언어 모델이 제 결과를 검토하는 데에도 매우 유용하다고 생각합니다. 설명 글을 쓸 때마다 보통 o3 모델 채팅에 복사해서 붙여넣고 꼼꼼한 사실 확인을 요청합니다. 이는 미묘한 오해를 밝혀내는 데 아주 좋습니다. 이를 잘 활용하려면 실제로 몇 가지 주장을 글로 적어야 합니다. 저는 위에서 언급한 여러 “결과”들을 적는 것을 좋아합니다. 그렇게 하면 언어 모델이 사실 확인을 쉽게 할 수 있습니다. 예를 들어, 확산 모델에 대해 배울 때 저는 전체 컨텍스트 창을 가진 자기회귀 모델보다 확산 모델이 더 빠를 거라고 생각했지만, 그 생각이 틀렸다는 것을 알게 되었습니다. 왜 틀렸는지 파악하는 과정에서 트랜스포머의 키-값 어텐션 매트릭스에서 캐싱이 어떻게 작동하는지에 대한 오해를 바로잡을 수 있었습니다.
Summary 요약
- Building a shallow understanding about how technologies you use work is very helpful, because it lets you have useful insights (about performance, quality, when the technology is a good fit, and so on)
당신이 사용하는 기술이 어떻게 작동하는지에 대해 얕은 이해를 갖는 것은 매우 유용합니다. 이는 성능, 품질, 기술이 적합한 시기 등에 대한 유용한 통찰을 제공하기 때문입니다. - You could instead go deep on one thing if you want, but my personal advice is to go broad
원한다면 한 가지에 대해 깊이 파고들 수도 있지만, 개인적인 조언은 폭넓게 배우는 것입니다. - The kind of understanding I mean is the kind you could explain to someone who is a little technical but not an expert - no mathematics, no jargon
제가 말하는 이해는 약간 기술적인 사람에게 설명할 수 있는 수준의 이해입니다. 수학이나 전문 용어는 필요 없습니다. - Writing down your understanding is very useful because it forces you to articulate things
이해한 내용을 글로 적는 것은 매우 유용한데, 이는 당신이 생각을 명확히 표현하도록 강제하기 때문입니다 - It also allows you to fact-check with a language model, which I’ve found very useful
또한 언어 모델을 사용해 사실 확인을 할 수 있는데, 저는 이것이 매우 유용하다는 것을 알게 되었습니다.
edit: This article was posted on Hacker News with lots of comments.
수정: 이 글은 Hacker News에 게시되었으며 많은 댓글이 달렸습니다.
-
Partly because the act of writing is useful for clarifying my thoughts, and partly because producing a written artifact means I can trivially ask o3 “hey, what did I miss?“.
↩
부분적으로는 글쓰기가 제 생각을 명확히 하는 데 도움이 되기 때문이고, 부분적으로는 작성한 글을 통해 간단히 o3에게 “내가 놓친 게 뭐지?”라고 물어볼 수 있기 때문입니다.
If you liked this post, consider subscribing to email updates about my new posts.
이 글이 마음에 드셨다면, 제 새 글에 대한 이메일 업데이트 구독을 고려해 보세요.
May 25, 2025 │ Tags: good engineers
2025년 5월 25일 │ 태그: 좋은 엔지니어