Home

읽기 설정

프로그래밍을 정말 잘하게 되는 방법입니다. 제가 코딩 공부했던 시간을 바꿀 수 있다면00:00

시작한 언어나 선택한 튜토리얼이 아닐 거예요.00:04

여섯 가지 원칙일 겁니다. 저는 그걸 모두 바보 같은 방식으로 배웠어요. 즉,00:12

느리고 주로 실무에서요. 이 원칙들은 프레임워크가 아니며, 모두 이번 주부터 시작할 수 있는 것들입니다. 바로 알아볼까요?00:16

첫 번째 원칙은, 사용하는 계층 아래의 계층을 배우세요.00:22

2년 동안 저는 더 나아지는 것이 새로운 프레임워크를 배우는 거라고 생각했어요. 리액트, 뷰, 스벨트,00:25

매달 출시되는 다음 것들을 여섯 개나 시작해서 아무것도 끝내지 못했죠.00:30

도구는 사라지지만, 문제는 사라지지 않아요. 모든 도구는 질문에 대한 답입니다.00:35

그 질문이 존재하기 전에 만들어졌죠. 질문과 답을 배우세요. 그러면 어디든 적용할 수 있습니다. 그래서,00:39

질문은 데이터베이스가 전원이 중간에 끊겼을 때 데이터를 잃지 않도록 어떻게 할까요?00:44

답은 Write Ahead Log입니다. 실제 데이터를 만지기 전에 하려는 작업을00:48

로그 파일에 추가하고 디스크로 플러시합니다. 로그를 먼저, 데이터를 나중에 항상 기록해야 합니다. 만약 기계가 고장나면00:53

로그는 살아남고, 재시작하면 데이터베이스는 이를 재생하고 진행 중이었던 작업을 복구합니다. PostgreSQL도 그렇게 합니다.01:00

MySQL의 InnoDB와 SQLite도 Write Ahead Log 모드를 켜면 그렇게 합니다. 그런 다음 한 계층을 벗겨내세요.01:07

당신의 파일 시스템은 자체적인 트릭 버전을 실행하는데, 이것이 ext4에서 저널링이라고 하는 이유입니다.01:13

같은 문제지만 스택의 다른 계층에서는 여전히 유효합니다.01:17

10년 또는 100년 후에나 가능할 것이고, 당신의 프레임워크 지식보다 훨씬 더 오래 지속될 것입니다.01:22

그러니, 당신이 사용하는 계층 바로 아래 계층에 한 시간만 투자하세요. 전체 계층은 아니고요.01:26

두 번째 원칙은 튜토리얼 지옥에서 벗어나세요. 작동하는 것에서 배우는 것이 아니라, 제대로 작동하지 않는 것에서 배워야 합니다. 즉,01:30

다른 사람의 코드가 작동하는 것을 보는 데 쓰는 모든 시간은 아무것도 아닌 시간입니다.01:36

튜토리얼은 역량에 대한 착각을 불러일으킵니다. 다른 사람이 시스템 아키텍처를 선택하고 설계했으며,01:40

예외 상황들을 처리하고 코어 오류 때문에 두 시간 동안 막혀서, 편집해서 보이지 않게 했겠죠.01:47

자르고 편집된 모든 깔끔한 장면은 누군가가 혼란스러워했던 것을 숨기고 있어요.01:51

그 혼란이 실제 학습 과정이었고, 당신은 거기에 없었어요.01:56

그래서 아무도 풀어내지 못한 무언가를 만들어 보세요.02:00

당신을 위한 것. Raw 소켓 기반의 HTTP 서버, 익스프레스나 플라스크, 진 없이, 크래시 복구 기능이 있는 키-값 저장소02:02

복구 기능이 있는, 마치 원시적인 형태의 Redis나 장난감 인터프리터 같은 것.02:09

HTTP 서버는 제가 직접 만들었어요. 시간을02:12

토요일 하루 종일 요청이 잘리면서 들어오는 문제를 디버깅했어요. 제 파서가 완전히 망가졌다고 생각했죠. 실수는 이것이었어요.02:14

소켓에서 한 번 읽으면 하나의 완전한 요청이 반환된다고 생각했어요.02:21

TCP는 그렇게 작동하지 않아요. 메시지 경계가 없는 바이트 스트림이죠.02:24

TCP는 바이트들이 순서대로 도착한다는 것을 보장해요,02:28

하지만 한 요청이 끝나는 곳과 다음 요청이 시작되는 곳은 여러분의 문제이고, 그래서 HTTP에 콘텐츠 길이 헤더가 있는 이유예요.02:31

콘텐츠 길이 헤더라고 하는 거예요. 문서 전체 시간에 걸쳐 있었던 한 문장 때문에 하루를 썼어요,02:37

그리고 정말 가치가 있었지만, 그 문장을 암기했기 때문이 아니에요.02:42

이제 제가 다루는 모든 프로토콜에 대해 항상 같은 질문을 하기 때문이에요.02:46

한 메시지는 어디에서 끝나는 걸까요? WebSocket도 답해야 했고, gRPC도 답해야 했고, 사용했던 모든 메시지 큐도 답을 해야 했어요.02:50

이제 문제를 즉시 알아차리고, 그 문제에 패배한 하루를 보냈기 때문에 알아차려요.02:57

세 번째 원칙은 코드 고고학자가 되는 거예요. 여러분의 GitHub 저장소는 이미 대부분 질문에 대한 답을 가지고 있어요.03:02

여러분보다 먼저 누군가 겪었던 모든 버그가 기록되어 있고, 많은 사람들이 어떻게 검색해야 하는지 모르고 있어요.03:10

두 개의 Git 명령어가 다른 모든 것을 알고 있는 것보다 훨씬 가치 있어요.03:15

Git blame은 누가 마지막으로 한 줄을 수정했고 어떤 커밋에서 수정했는지 알려줘요. 그러니까 이해가 안 되는 코드를 삭제하기 전에 그 커밋 메시지를 읽어보세요.03:18

거의 항상 그 줄이 추가된 이유, 즉 버그를 수정하기 위해 어떤 문제가 있었는지 기록돼 있어요. 그리고 Git bisect는 무엇인가를 망친 커밋을 찾기 위해 이진 검색으로 히스토리를 탐색해요.03:25

깨진 커밋과 정상적으로 작동하는 커밋을 표시해요. 그러면 Git은 중간 지점을 체크아웃해요.03:31

테스트해봐요. 그러면 범위를 다시 절반으로 줄여요. 추측하는 오후 대신 약 10번의 확인으로 천 개의 커밋을 해결할 수 있어요.03:36

그리고 대략 40%의 경우, blame은 그 줄을 쓴 바보가 바로 8개월 전 당신이었다는 것을 보여줘요.03:43

원칙 네 번째, 과학자처럼 디버깅하세요. 요청할 때마다 재현할 수 있는 버그는 이미 90% 해결된 거예요.03:49

그 시점 이전의 모든 것은 추측이고, 추측은 정말 끔찍하게 확장돼요.03:54

현재 프로세스는 한 줄을 변경하고 새로 고쳐도 여전히 깨져있으면 console.log를 추가하고 또 4개를 더 추가해서 이제 11개가 출력돼요.03:58

여기, 여기 2, 여기 대문자로 쓰고 느낌표 4개까지 붙여서 구분할 수 없어요.04:05

그건 디버깅이 아니라 저녁자리예요. 세 단계로 이루어지며, 소프트웨어에서 가장 어려운 지시사항으로 시작합니다. 코드를 만지지 마세요.04:10

가설을 세워보세요. 데이터가 잘못된 게 아니라 무엇이 실패하는지 구체적으로 말해야 해요.04:17

하지만 쓰기가 커밋되기 전에 캐시를 무효화해서 동시 읽기가 이전 값으로 다시 채워져요.04:21

가설은 틀릴 수도 있는 것이고, 그게 바로 유용한 이유예요.04:29

다음으로 격리하세요. 실패하는 가장 작은 경우를 얻을 때까지 버그가 아닌 모든 것을 제거해야 해요.04:33

대부분의 버그는 이 단계에서 식별되고, 그 이후가 아니에요.04:38

실패하는 테스트를 작성하세요. 안정적으로 재현되면 수정은 보통 간단하고, 테스트는 영원히 보관해야 해요.04:42

그리고 실제 디버거를 배우세요. PDB, Delve, Chrome DevTools, 사용하는 언어에 맞는 걸 사용하세요.04:48

조건부 중단점은 사용자 ID가 null일 때만 일시 정지하고, 백 개 이상의 print 문을 대체하며 모든 변수를 보여줘요.04:54

그건 MRI와 막대기로 사람을 찌르는 것과의 차이점이에요.05:01

오늘의 스폰서인 HackMe를 소개합니다. 공격자가 되어 보안을 가르쳐주는 서비스예요.05:05

처음 본 적 없는 공격에 대비할 수는 없죠. 그래서 실제 취약한 기계를 얻어서 해킹하게 돼요.05:12

로그인 폼을 통해 데이터베이스를 추출하고, 비밀번호 해시를 크래킹해서, 낮은 권한의 셸을 루트로 확장하는 거죠.05:18

그런 다음 자신의 코드로 돌아가서 실제로 작동하는 공격에 대한 검증을 작성해야 합니다. 체크리스트의 항목이 아니에요.05:24

설치할 필요가 없어요. 공격 박스는 브라우저 탭에 있는 구성된 Linux 머신이라서 몇 분 안에 첫 번째 연습을 시작할 수 있어요.05:32

방은 안내되어 있어서, 빈 터미널만 바라보고 있지는 않아요. 그리고 그들의 어시스턴트 Echo가 막히는 부분을 해결해 줘요.05:39

초보부터 심각한 침투 테스트까지 다양한 경로가 있어요. 인터넷에 연결되는 코드를 작성한다면 몇 개의 방에서 코딩하는 방식이 바뀔 거예요.05:45

시작은 무료이고, 설명에 링크가 있습니다. 제 코드를 사용하시면 연간 구독료를 25% 할인받을 수 있어요.05:51

프리미엄 멤버십을 25% 할인받을 수 있어요. TriHackMe 덕분에 영상 후원받았습니다. 원칙 다섯 번째, 모든 것이05:56

깨질 거예요. 모든 네트워크 호출은 결과를 확인할 수 없는 동전 던지기입니다.06:01

실패할 거라는 가정 하에 코드를 작성하세요. 아마추어 코드는 하나의 질문에 답해요. 모든 것이 잘 될 때 무슨 일이 생기는가?06:05

운영 환경에서는 다른 모든 질문을 합니다. 만약 데이터베이스가 트랜잭션 중에 죽는다면 어떡하죠?06:12

API가 실패하지 않고 응답하지 않는다면요? 그냥 45초 동안 멈춰있을 수 있어요.06:17

두 가지 습관이 대부분의 경우를 해결해줍니다. 첫 번째는 이드empot턴시입니다.06:22

같은 작업을 두 번 하면 한 번 하는 것과 같은 결과가 나와요.06:26

일반적인 구현 방식은 이드empot턴시 키이고, 스트라이프 API에서 사용하는 패턴이에요.06:30

클라이언트는 고유한 키를 헤더로 보내고, 결과를 저장하고, 그 키가 다시 나타나면,06:34

저장된 결과를 반환하고 아무것도 다시 실행하지 않아요. 요청은 성공할 수 있지만 응답이 손실될 수 있기 때문이에요.06:40

작업은 완료되었지만, 확인 응답은 전송 중에 죽었고, 클라이언트는 다시 시도했어요. 제가 그 버그를 배포했었어요.06:47

이드empot턴시 키가 없는 결제 엔드포인트, 모바일 클라이언트는 타임아웃 시 재시도를 설정했어요.06:53

타임아웃 시 재시도를 합니다. 한 고객이 두 번 청구되었고, 주문도 하나 있었어요.06:57

두 번째는 지수 백오프를 사용해서07:01

처음에는 1초 후에 재시도하고, 그다음 2초, 4초, 8초 후에 재시도하며 각 지연에 임의 오프셋을 더하세요.07:03

지터가 없다면 동시에 실패한 모든 클라이언트는 같은 시점에 재시도해요.07:09

그리고 명시적인07:13

모든 네트워크 호출에 타임아웃을 설정하세요. Python의 requests, Go의 기본 http.client, Axios는 모두07:14

지시하지 않으면 타임아웃되지 않아요. 이게 바로 하나의 느린 의존성이 전체 스레드 풀을 잡아먹는 방식이에요.07:22

완벽하게 동기화되어 재시도하는 천 개의 클라이언트는 장애에서 복구되지 않아요.07:26

그것들이 바로 장애예요. 본질적으로 서비스 거부 공격을 구축해서 자기 자신에게 겨냥한 것과 같아요.07:30

여섯 번째 원칙은 측정하고 추측하지 마세요. 마지막 원칙이 여기 있어요.07:35

성능에 대한 직감은 믿을 수 없으며, 거의 30초 만에 스스로 증명할 수 있어요.07:39

왜 배열이 연결 리스트보다 루프를 돌리는 데 더 빠른가요?07:45

포인터를 말했다면 반은 맞아요. 포인터를 쫓는 것이 메커니즘이지만, 왜 포인터를 쫓는 것이 느린지 설명하지는 못해요.07:48

정답은 캐시이고, 그걸 아는 것은 성능을 예측하는 것과 프로파일러에게 염소를 바치는 것의 차이예요.07:54

CPU는 한 번에 한 바이트를 가져오지 않아요. 캐시 라인, 한 번에 64바이트씩 가져와요.08:00

그래서 배열의 요소 0을 건드리면 다음 15개의 정수를 무료로 L1에 가져와요.08:05

연결 리스트는 그런 것을 전혀 얻지 못해요. 노드는 힙에 흩어져 있고, 현재 노드의 주소를 찾기 위해 읽을 때까지 다음 노드를 가져올 수도 없어요.08:09

L1은 약 나노초이고, 주 메모리는 약 100이에요. 빅오에서는 둘 다 O of N이라고 했어요,08:16

그리고 빅오는 실제로 중요한 부분을 숨기고 있었어요. 프레임워크를 탓하는 것은 쉽고, 누구도 스탠드업에서 반박할 수 없어요.08:21

대신 프로파일링하세요. Python에는 PySpy, Go에는 PProf, JavaScript에는 DevTools가 있어요.08:27

플레임 그래프는 시간이 어디로 갔는지 보여줘요. 더 넓은 막대는 해당 함수에서 더 많은 시간을 의미해요.08:32

가장 넓은 부분을 찾고 왜 그런지 물어보세요. 그리고 CPU뿐만 아니라 할당량도 프로파일링해야 해요.08:37

가비지 컬렉션이 되는 언어에서는 느려 보이는 함수는 종종 컬렉션을 트리거하는 것일 뿐이에요.08:42

거의 예상했던 곳이 아니에요. 잊고 있던 루프에서 4,000번 호출되는 도우미 함수이거나, N+1 쿼리일 수 있어요.08:47

그런 다음 이전과 이후를 벤치마크하세요. 더 빨라졌다는 것을 보여주는 숫자를 생성할 수 없다면 아무것도 최적화하지 않은 거예요.08:54

코드를 더 못생겨 보이게 만들고, 효과적으로 자신에게 자장가를 불러줬어요.09:00

마무리하자면, 여섯 가지 모두를 할 필요는 없어요. 아무도 그렇게 하지 않아요. 네 번째부터 시작해서 디버거를 제대로 배우세요.09:03

오후면 충분하고, 같은 주에 효과를 느낄 수 있을 거예요. 설명란의 TryHackMe도 자유롭게 확인해 보세요. 시작은 무료고요,09:09

저 코드를 사용하면 연간 플랜을 25% 할인받을 수 있어요.09:15

항상 시청해 주셔서 정말 감사하고, 즐거운 코딩하세요.09:18

AI Summary

프로그래밍 실력을 향상시키기 위해서는 단순히 튜토리얼을 따라 하는 것보다 더 깊이 있는 학습이 필요합니다. 기술의 작동 원리를 이해하고, 실패 상황에서 문제 해결 능력을 키우며, 다른 개발자들의 코드를 분석하는 '코드 고고학'을 통해 지식을 습득해야 합니다. 또한, 과학적인 디버깅 방법론과 안정적인 코드 작성을 위한 전략(멱등성, 지수 백오프)을 적용하고, 측정 기반으로 성능을 최적화하는 것이 중요합니다.

Key Highlights

  • •기술의 작동 원리(계층적 사고)를 이해해야 합니다.
  • •실패 상황에서 문제 해결 과정을 통해 학습해야 합니다.
  • •기존 코드를 분석하여 다른 개발자들의 경험을 활용해야 합니다 (코드 고고학).
  • •과학적인 방법론으로 디버깅하고, 재현 가능한 버그에 대한 가설 검증이 필요합니다.
  • •네트워크 호출 실패 대비를 위한 멱등성 및 지수 백오프 기법 적용이 중요합니다.

Related Videos