Ch.1 어떻게 공부할 것인가¶
앞에서 "왜 CS를 알아야 하는가"와 "이해가 왜 우선인가"를 이야기했다. 이제 "그럼 어떻게 공부하는가"를 이야기하겠다.
이 강의의 학습 단계¶
이 강의는 매 챕터마다 세 단계를 밟는다.
| 수준 | 특징 | 이 강의에서 |
|---|---|---|
| 암기 | 정의를 안다 | 키워드 목록으로 정리한다 |
| 이해 | "왜"를 안다 | CS Drill Down으로 파고든다 |
| 경험 | 직접 보고 측정한다 | k6, strace 등으로 증명한다 |
이 표에 등장한 도구 한 줄 소개
k6: 부하 테스트 도구. 초당 N개 요청을 날려 p50/p99 응답 시간·초당 처리량(req/s)을 측정한다. Ch.2부터 사용strace: 프로세스가 커널에 요청하는 System Call을 추적하는 도구. Ch.2에서 "print()가 왜 느린가"를 증명할 때 사용- 지금은 도구 이름만 기억하면 된다. 설치·사용법은 Ch.2에서 함께
이 강의는 "경험" 레벨을 목표로 한다. 키워드를 외우는 게 아니라, 직접 부수고 관찰하고 측정하면서 체감하는 거다.
(Ch.1은 예외적으로 코드 없이 진행한다. Ch.2부터 매 챕터 코드를 돌리고, 측정하고, 분석한다.)
Computational Thinking¶
공부를 시작하기 전에 다져놓으면 좋은 게 딱 하나 있다.
Computational Thinking (컴퓨팅 사고)
문제를 CS 개념으로 분해(Decomposition)하고, 핵심을 추상화(Abstraction)하여 체계적으로 해결하는 사고방식이다.
Jeannette Wing이 2006년 Communications of the ACM에 기고한 "Computational Thinking" 논문에서 대중화된 개념이다.
단순히 코딩을 잘하는 것이 아니라, 문제를 분해하고 추상화하는 능력을 의미한다.
출처: Wing, J. M. (2006). Computational thinking. Communications of the ACM, 49(3), 33-35.
Computational Thinking. 컴퓨터와 유사한 사고 방식을 적용하여 문제를 분석하고 해결하는 접근 방법이다. CS의 근본적인 사고 방식이며, 효율적으로 문제를 해결하고 자동화하는 데 필수적인 역량이다.
간단히 말하면, 어떤 현상을 보고 "이걸 컴퓨터로 어떻게 구현하지?"라는 생각을 하는 것이다. 거기서 꽤나 복잡한 능력이 요구되지만, 결국 이걸 코드로 구현하려면 어떻게 해야 하는지 머릿속으로 구상하고 결론을 내리는 과정이다.
Computational Thinking의 4단계¶
Wing의 CT 개념을 이후 교육학 연구(Google for Education, Brennan & Resnick(2012) 등)에서 구체화한 모델이 있다. 보통 네 단계로 구분한다:
- 분해(Decomposition): 복잡한 문제나 현상을 더 작고 관리 가능한 부분으로 나눈다
- 패턴 인식(Pattern Recognition): 분해된 정보 중에서 예측 가능한 패턴을 찾는다
- 추상화(Abstraction): 문제 해결을 위해 중요한 정보만 추출하고 불필요한 사항을 제거한다
- 알고리즘 디자인(Algorithm Design): 문제를 해결하기 위해 구체적인 단계별 절차를 설계한다
흡사 "수열(Sequence)" 문제를 풀이하는 것과 비슷하다. 패턴을 인식하고, 규칙을 도출하여, 적용과 검증을 한다. 수열도 엄밀히 말해 함수로 결론이 도출되지 않는가? 별 차이 없다.
실무에서의 CT¶
"서버가 느리다"는 하나의 현상이다. 이 현상을 CS 키워드로 분해할 수 있으면 원인을 찾을 수 있다.
"서버가 느리다"
|
+-- CPU Bound인가? (CPU 사용률이 100%에 가까운가?)
|
+-- I/O Bound인가? (DB 쿼리, 파일 읽기, 네트워크 호출이 병목인가?)
| |
| +-- Connection Pool이 고갈된 건 아닌가?
| |
| +-- 인덱스가 안 걸린 쿼리가 있는 건 아닌가?
| |
| +-- N+1 쿼리가 발생하고 있는 건 아닌가?
|
+-- 메모리 문제인가? (OOM, GC 오버헤드)
|
+-- 네트워크 문제인가? (Latency, Bandwidth)
이 트리를 그릴 수 있으려면, 각 가지에 해당하는 키워드를 알아야 한다. CPU Bound가 뭔지 모르면 첫 번째 질문조차 던질 수 없다.
CT는 결국 "적절한 키워드로 문제를 분해하는 능력"이다. 그리고 이 강의는 그 키워드를 하나씩 쌓아가는 과정이다.
Science라고는 하지만 어쨌든 Engineering이다. Science면 자연과학대에 있어야지 왜 공대에 있겠는가. CS는 단순히 이론적인 학문이 아닌, 실제 문제를 해결하기 위한 도구이자 학문이다. 이걸 잊으면 안 된다.
연관어 학습법¶
이 강의의 핵심 학습 방법론이다.
(학문적으로는 Concept Mapping이나 Schema Theory와 유사한 접근이지만, 이 강의에서는 CS 키워드 그래프에 특화된 독자적인 방법론으로 사용한다.)
CS의 키워드는 서로 연결되어 있다. 어떤 키워드에서 출발하든 결국 관련 키워드로 이어진다. 이 연결 고리를 따라가면서 학습 범위를 넓혀나가는 것이 연관어 학습법이다.
구체적으로 어떻게 하는 건지 예시를 보자.
File Descriptor에서 시작하는 연관어¶
Ch.2에서는 print() 하나에서 출발한다.
print()를 치면 뭐가 일어나지?
-> 내부적으로 sys.stdout.write()를 호출한다
-> stdout이 뭐지? File Descriptor 1번이다
-> File Descriptor가 뭐지? OS가 파일/자원에 붙이는 번호다
-> write()는 뭐지? System Call이다
-> System Call이 뭐지? 사용자 프로그램이 커널에 요청하는 인터페이스다
-> User Mode에서 Kernel Mode로 전환된다
-> 이 전환(Mode Switch)에 CPU Cycle이 많이 든다
하나의 함수(print())에서 출발해서 stdout, File Descriptor, System Call, Kernel, Mode Switch, CPU Cycle까지 도달했다. 이게 Ch.2 한 챕터의 키워드 그래프다.
그런데 여기서 끝이 아니다. File Descriptor 하나만 더 파고들어 보자.
File Descriptor
-> OS가 열린 파일/자원에 붙이는 번호다
-> 파일을 열면 커널이 File Table에 등록한다
-> 읽기/쓰기를 할 때 Page Cache를 거친다
-> Page Cache가 뭐지? 디스크 데이터를 메모리에 캐싱하는 거다
-> 캐시가 꽉 차면? Page Fault가 발생한다
-> 메모리가 부족하면? Memory Swap이 일어난다
FD 하나를 파고들었을 뿐인데 File Caching, Page Fault, Memory Swap까지 자연스럽게 연결됐다. 이게 연관어 학습법이다. 하나를 깊이 파면 주변 개념이 줄줄이 따라온다.
(아래 그래프에 나오는 키워드들은 전부 이후 챕터에서 하나씩 설명한다. 지금은 "이런 식으로 연결된다"는 구조만 보면 된다.)
graph LR
print["print()"] --> stdout
stdout --> fd["File Descriptor"]
stdout --> buffer["Buffer"]
buffer -->|flush| write["write() System Call"]
fd --> write
fd --> ft["File Table"]
ft --> pc["Page Cache"]
pc --> pf["Page Fault"]
pf --> swap["Memory Swap"]
write --> MS["Mode Switch"]
MS --> kernel["Kernel"]
MS --> UM["User Mode"]
MS --> KM["Kernel Mode"]
MS --> cycle["CPU Cycle"]
write --> IO["I/O"]
(print()는 Bytecode 레벨에서도 분석할 수 있다. Bytecode가 어떻게 System Call로 이어지는지는 Ch.2에서 다룬다.)
이 그래프가 챕터를 거듭할수록 점점 커진다. Ch.3에서는 I/O에서 CPU Bound/I/O Bound가 뻗어나가고, Ch.4에서는 Kernel에서 Process/Thread/Memory가 뻗어나간다. Ch.24가 끝나면 수백 개의 키워드가 하나의 거대한 그래프로 연결된다.
AI 도구를 활용하자¶
요즘은 좋은 도구가 있다. AI에게 키워드를 하나 던지고 "이것과 관련된 CS 개념은 뭐가 있어?"라고 물어볼 수 있다. 물론 AI의 답변을 맹신하면 안 된다. 반드시 원본 출처(공식 문서, 교과서, 논문)를 확인해야 한다.
관련된 것에 대해 키워드를 하나씩 파고들고 공부해보자. 언젠간 모든 개념이 연결되고, 그러다 보면 자연스럽게 특정 개념에 대해 넓은 이해와 적용을 할 수 있다.
그리고 언젠가는 이런 깨달음이 올 거다: "CS 뭐... 다 그 밥에 그 나물이구나." (사실 그 밥에 그 나물은 아니지만, 그런 자신감을 가지라는 얘기다.)
프로그래밍 언어를 5~6개 쯤 공부하다 보면 대충 문법만 보고 두들겨도 프로그램을 짤 수 있다. "여기는 이 기능이 없나?" 하면서 찾아보면서 말이다. CS도 그렇다. 5~6과목 정도를 공부하다 보면 생각나는 대로 뱉다가 말이 되는 것 같은 경우가 있다. 하지만 꼭 진실 공급원(공식 문서, 교과서)을 확인하라.
외우는 게 아니다. 연결하는 거다.
Drill-Down 학습법¶
그러면 CS 공부를 어디서부터 시작하는가?
BE 개발자가 알아야 할 CS 과목을 정리해보면 이렇다.
| 과목 | 주요 키워드 예시 |
|---|---|
| 소프트웨어 공학 | OOP, AOP, DDD, Agile, DI, IoC, 관심사 분리 |
| 운영체제 | Process, Thread, Mutex, Semaphore, Context Switching |
| 데이터베이스 | Query, DBMS, Index, Isolation Level, Transaction |
| 분산 시스템 | Docker, Container, VM, Orchestration |
| 자료구조와 알고리즘 | 시간 복잡도, 공간 복잡도, 자료구조 선택 기준 |
| 컴퓨터 네트워크 | TCP/IP, 3-way handshake, Connection Pool |
| 프로그래밍 언어론 | Lambda, Stream, Type System |
| 컴퓨터 보안 | XSS, CORS, CSRF, TLS |
많아 보인다. 이걸 교과서 8권 사서 처음부터 끝까지 정독해야 하는 걸까? 아니다.
이 강의가 취하는 방식은 Drill-Down이다. 실무에서 벌어지는 장애 상황, 성능 문제, 디버깅 막힘에서 출발해서 CS로 파고드는 거다. 교과서의 1장부터 읽는 게 아니라, "print()가 왜 느리지?"라는 의문에서 출발해서 System Call, Kernel, Mode Switch를 알게 되는 식이다.
이게 왜 효과적인가? 동기가 있기 때문이다. "왜 느린 건데?"라는 의문이 있으니까 답을 찾고 싶고, 답을 찾는 과정에서 자연스럽게 CS 키워드를 접하게 된다. 의문 없이 교과서를 펼치면 "이걸 왜 알아야 하지?"에서 멈추기 쉽다.
구체적으로 어떻게 하는 건가? 오늘 FastAPI 쓰다가 connection pool exhausted 에러를 만났다고 치자. 에러 메시지를 통째로 검색하는 것에서 그치지 않는다. 에러를 구성하는 키워드를 하나씩 더 파본다:
connection pool exhausted
-> connection pool이 뭐지? DB 연결을 미리 만들어두는 거다
-> 왜 미리 만들어두지? 연결을 만드는 비용이 크기 때문이다
-> 연결 비용이 왜 큰 거지? TCP 3-way handshake + 인증 과정이 필요하다
-> exhausted가 왜 발생했지? 커넥션을 쓰고 반납을 안 했나?
-> 반납 안 하면 어떻게 되지? pool이 고갈되고 새 요청이 대기한다
AI에게 물어볼 때도 마찬가지다. "connection pool exhausted 해결해줘"가 아니라 "connection pool exhaustion의 일반적인 원인을 CS 관점에서 알려줘"라고 물어본다. 그러면 커넥션 누수, pool sizing, timeout 설정 같은 키워드가 나오고, 각각을 또 파고들 수 있다.
이 강의가 끝나면 위 과목들의 핵심 키워드를 자연스럽게 접하게 된다. 교과서를 펼치기 전에 키워드를 먼저 아는 거다. 그 뒤에 교과서를 읽으면 "아, 이게 그때 그거구나"라는 연결이 바로 된다.
실무를 위한 과목 우선순위를 굳이 매기자면(작성자 경험 기반): DB → 분산 시스템 → 자료구조와 알고리즘 → 운영체제 → 소프트웨어 공학 → 네트워크 → 보안 → 프로그래밍 언어론 정도가 되겠다. DB가 1순위인 이유는 단순하다. 백엔드 성능 문제의 대부분은 DB에서 온다. 인덱스 하나 안 걸어서, 쿼리 하나 잘못 짜서 서비스 전체가 느려지는 경우가 그만큼 흔하다. 물론 사람마다, 업무마다 다르다.
이 강의에서 각 챕터가 진행되는 방식¶
모든 챕터(Ch.2부터)는 같은 패턴으로 진행된다:
- 실무에서 벌어질 법한 사례를 하나 보여준다
- "어떤 결과가 나올 것 같은가?" 질문을 던진다
- 실제로 측정해서 결과를 보여준다 (k6, strace, explain 등)
- 코드를 분석한다
- "왜 이렇게 일어났나"를 CS 개념으로 파고든다 (Drill Down)
- 같은 원리가 적용되는 다른 사례를 소개한다
- 키워드를 정리한다
이 과정에서 연관어 그래프가 매 챕터 점점 커진다.