00:00:00이번 스탠드업 에피소드는 케이시가 인트로를 맡기 때문에 특별할 거예요.
00:00:05케이시, 오늘은 무슨 얘기를 할 건가요?
00:00:07안녕하세요 여러분, 스탠드업에 오신 걸 환영합니다.
00:00:09최근 뭔가에 따르면 스포티파이에서 45, 6번째로 좋은 기술 팟캐스트라고 하더군요.
00:00:12사실이에요.
00:00:13아무튼, 죄송합니다.
00:00:14오늘 스탠드업에서는 제가 다루고 싶은 주제가 있어요.
00:00:1610월에 발생한 AWS 장애에 대해 이야기할 건데요, 사실 더 큰 주제를 다루고 싶어서 이걸 꺼낸 거예요.
00:00:20바로 실제로 뭔가를 이해하는 것과 이해한다고 말하는 것의 차이에 대해서요..
00:00:29특히 프로그래밍 경력 초기에 있는 사람들에게 자주 일어나는 일 중 하나인데요,
00:00:32예를 들어 주니어 프로그래머거나 막 입문한 경우 말이죠.
00:00:34저도 분명히 그랬는데, 뭔가를 안다는 인상을 주고 싶잖아요, 그렇죠?
00:00:37무슨 일이 벌어지는지 모른다는 걸 들키고 싶지 않은 거죠.
00:00:40그래서 외부적인 압박이 많이 있어요.
00:00:41실제로 있든 없든, 뭔가를 이해했다고 말해야 할 것 같거나 이해한 척해야 할 것 같은 느낌을 받게 되죠.
00:00:46사실은 좀 애매하거나 완전히 이해하지 못했는데도 말이에요..
00:00:49그리고 본인 잘못이 아니더라도,
00:00:51예를 들어 설명이 제대로 안 됐거나 중요한 정보가 빠져 있었더라도,
00:00:57여전히 그걸 알고 있었던 것처럼 행동해야 한다는 압박을 느끼게 되죠,
00:01:03그렇죠?
00:01:03그게 더 똑똑해 보이게 하거나, 최소한 주니어처럼 보이지 않게 해주니까요.
00:01:09그래서 제가 나이를 먹고 프로그래밍 경험을 더 쌓으면서 발견한 것 중 하나는,
00:01:16요즘엔 거의 과하다 싶을 정도로 설명을 요청한다는 거예요.
00:01:20멍청해 보이는 것에 대해 전혀 신경 쓰지 않아요..
00:01:26"잠깐만요, 다시 설명해 주세요.
00:01:33그 부분은 이해 못 했어요.
00:01:38그게 무슨 뜻이에요?" 또는 "그 용어는 무슨 의미예요?" 같은 식으로 물어봐요?
00:01:54이제는 그런 걸 별로 신경 쓰지 않거든요.?
00:02:03그렇게 걱정하지 않아요.
00:02:04그리고 실제로 알고 싶어요.
00:02:06왜냐하면 뭔가를 안다고 생각했거나 아는 척했다가 나중에 큰 낭패를 본 경험이 너무 많거든요..
00:02:12그래서 진짜 알고 싶어요.
00:02:13버그에 대한 설명이 있거나 성능 저하의 원인을 안다고 생각할 때, 항상 머릿속 한편으로는 이렇게 생각해요.
00:02:16'내가 진짜 근본 원인까지 파고들지 않았다면, 다른 뭔가일 수도 있어.
00:02:18진짜 원인이 아직 숨어 있을 수도 있는데 내가 끝까지 파보지 않아서 모르는 거일 수도 있지.
00:02:20그냥 편하니까 넘어가는 거 아닐까.'.
00:02:22진짜로 알고 싶어요.
00:02:23버그에 대한 설명이 있거나 성능 저하의 원인을 안다고 생각할 때도,
00:02:29항상 머릿속 한편에서는 '정말 이게 근본 원인까지 파고든 건지,
00:02:35아니면 진짜 원인이 아직 어딘가에 숨어 있는 건 아닐까.
00:02:39끝까지 살펴보지 않아서 모르는 건 아닐까.
00:02:43그냥 편하니까 넘어가려는 건 아닐까'라고 생각해요..
00:02:48제가 DynamoDB 장애에 대해 이야기하고 싶었던 이유는 최근에 주목할 만한 대규모 장애들이 연달아 발생했기 때문입니다.
00:02:57구글을 먹통으로 만든 큰 장애가 있었는데, 알고 보니 필드가 비어있는 경우를 처리하지 않은 게 원인이었죠.
00:03:04그러니까 프로그래밍 방식이,
00:03:06JSON을 불러오는데 JSON에 아무것도 없으면 널 포인터를 역참조하거나 뭐 그런 식이었던 거죠.
00:03:13말 그대로 그런 거였어요.
00:03:15그리고 CrowdStrike 장애도 있었는데, 블루스크린으로 전 세계를 먹통으로 만들었죠.
00:03:21그들은 정말 훌륭한 설명을 제공했는데,
00:03:24특정 배열 크기 조정 방식을 사용하는데 규칙이 너무 많아서 배열이 오버플로우됐다는 거였어요.
00:03:31이런 것들은 RCA, 즉 근본 원인 분석이라고 부르는 걸 제공했을 때 꽤 괜찮았습니다.
00:03:37왜 시스템이 다운됐는지 설명했을 때요.
00:03:39제가 그걸 읽었을 때 머릿속에 미해결 질문이 많이 남지 않았어요.
00:03:44문제가 된 코드 라인을 정확히 알지는 못했을 수도 있어요.
00:03:48실제 코드 조각을 공개하지 않았을 수도 있으니까요.
00:03:52하지만 충분한 정보를 줘서 저는 '아,
00:03:54누군가 이 코드를 어떻게 작성했는지 이해하겠고,
00:03:58그들이 저지른 멍청한 짓도 이해하겠다'는 생각이 들었습니다.
00:04:02그러니까 저런 짓은 하지 말라는 거죠.
00:04:05이해합니다.
00:04:05그리고 전 완전히 납득했어요..
00:04:10DynamoDB 장애의 경우는, 이 팟캐스트에서 다뤄졌잖아요?
00:04:15우리가 그 얘기했을 때, 기타 센터에 있던 그 사람이요.
00:04:20펍에서 누가 얘기하는 걸 우연히 들었다고 했던 거요..
00:04:24놀랍습니다.
00:04:25여기 찾기 어려운 프로그래머를 봅니다.
00:04:27대부분의 시간을 혼자, 종종 어둠 속에서 작업하는 단순한 생명체입니다.
00:04:31하지만 이게 뭔가요?
00:04:32인터넷에서 누군가 틀린 말을 하고 있네요.
00:04:35우리의 코더가 행동에 돌입합니다.
00:04:37분당 120단어의 최고 속도에 도달하다가 라이트 모드 웹사이트가 번쩍입니다..
00:04:42이 코드 애호가들의 천적이 우리 친구를 기절시킵니다.
00:04:45추격은 중단됐습니다.
00:04:46다음 기회에 잡아야겠네요.
00:04:47컴퓨터 앞에 있지 않을 때, 그들은 몇 시간이고 조잡한 기호들을 그리며 시간을 보낼 수 있습니다.
00:04:52그들이 화이트보드라고 부르는 것이죠.
00:04:54연구자들은 수천 개의 방언을 발견했으며, 단일 사무실에서만 십여 개 이상이 사용되는 경우도 있습니다.
00:04:59하지만 아직 어떤 언어학자도 그 목적이 무엇인지 해독하지 못했습니다..
00:05:03허영심 많은 생명체들입니다.
00:05:05그들의 신체는 수천 년에 걸쳐 진화하여 온라인에서 자신을 보면서 특이한 자세로 앉을 수 있게 되었습니다.
00:05:11이것은 종종 몇 시간 동안 지속되며 코드 리뷰를 기다리고 있다는 핑계를 댑니다.
00:05:17하지만 왜 그렇게 활동이 없는지 추궁당하면...
00:05:20그리고 마침내, 거의 아무것도 이루지 못한 긴 하루가 끝나고, 우리의 키보드 전사는 잠잘 준비를 합니다.
00:05:26빠르게 읽고는 불을 끕니다..
00:05:29잘 자, 작은 코더야.
00:05:30그래서 제가 밤에 어떻게 그렇게 잘 자냐고요?
00:05:33Sentry가 버그들을 박살내는 걸 도와주거든요.
00:05:36그리고 저는 겨울에 죽는 사우스다코타의 작고 귀여운 벌레들 말하는 게 아닙니다.
00:05:41크고 사나운 정글 벌레들을 말하는 겁니다.
00:05:44그리고 저는 그 어떤 것도 무섭지 않아요.
00:05:47그냥, 하지만 저는 Sentry의 Seer로 그 버그들을 박살낼 수 있습니다.
00:05:52그래서 저는 그것에 대해 좀 더 의욕이 생겨서 가서 보기로 했죠.
00:05:57그들이 얼마나 많은 정보를 게시했는지요.
00:05:59그리고 이미 어느 정도 읽었는데, 나중에 그들이 RCA를 게시한 요약본이 있었고 매우 모호했어요.
00:06:06RCA는 실제로 많은 것을 설명하지 않았습니다.
00:06:09그러다가 그들이 12월 re:Invent에서 전체 프레젠테이션을 게시한 걸 알아챘어요.
00:06:15아니면 re:Invent가 12월이었는지는 모르겠지만,
00:06:19비디오는 12월에 올라왔는데 이 장애를 다룬 re:Invent 프레젠테이션이었습니다..
00:06:26그래서 그걸 다 봤습니다.
00:06:28전체 RCA를 다 읽고 전체 프레젠테이션을 다 본 후에도, 여전히 이런 생각이 들더라고요.
00:06:35여기서 실제 버그에 대한 설명이 보이지 않는다고요.
00:06:39실제 버그가 뭐였는지 알아내려고 노력했는데 전혀 설명되지 않았어요..
00:06:45그래서 제가 하고 싶었던 건 그냥 그것에 대해 이야기하고,
00:06:48왜 그들이 버그가 무엇인지 제대로 설명하지 않았다고 생각하는지 짚어보면서,
00:06:52사람들이 그냥 '아,
00:06:53알겠어.
00:06:53버그가 뭔지 알았어'라고 넘어가서는 안 된다는 예시로 삼는 거였어요.
00:06:57사람들이 제게 답글을 달면서 '아,
00:06:59제가 버그가 뭔지 설명해드릴게요'라고 하고는 똑같은 얘기만 반복하더라고요.
00:07:02전 '그게 버그가 아니에요'라고 하는데 말이죠.
00:07:05그래서 모두가 '나는 이해했어'라고 말하도록 유도되는 거예요.
00:07:08읽었으니까요.
00:07:09하지만 아니에요.
00:07:10실제 버그가 뭐였는지 말해주지 못한다면, 우린 아직 끝난 게 아닌 거죠..
00:07:14좀 더 완전한 설명이 있어야 한다는 거죠.
00:07:16그래서 제가 말하는 게 다 합리적으로 들리나요?
00:07:19네.
00:07:19우선, 말씀드리고 싶은 건, 저는 케이시가 말하는 걸 정확히 알았어요..
00:07:23처음부터요, 맞죠.
00:07:25바로요.
00:07:25당신은 '알겠어요, 당신이 말하는 거 정확히 알아요.
00:07:30제 쪽에서 질문 없어요.
00:07:32막히는 거 없어요.
00:07:34다들 감사합니다.
00:07:35전 좋아요'라고 하는 것 같았어요..
00:07:39내일 봐요.
00:07:39아무 문제없어요.
00:07:40그냥 말하고 싶은 건,
00:07:42저는 Spotify에서 들을 때 팟캐스트에서 케이시가 말하는 걸 듣는 게 정말 좋아요.
00:07:47그리고 지금 당장도요.
00:07:49한 시간 동안 당신 얘기 들을 수 있을 것 같아요.
00:07:52Spotify 언급도 정말 좋네요.
00:07:54제가 막 말하려던 참이었어요.
00:07:56특히 Spotify에서 들으면 음질이 엄청나다고요.
00:07:59보너스 추가분도 받잖아요, 맞죠?
00:08:01실제 에피소드 전후의 모든 잡담을 다 들을 수 있어요.
00:08:04우리가 Spotify에 더 길고 긴 버전을 올리기 시작했거든요.
00:08:08더 많은 추가분이 들어간 버전이요.
00:08:10네.
00:08:11본론에서 벗어난 얘기는 덜하지만, Spotify에는 좀 더 잡담이 많아요.
00:08:15왜냐하면 라이브 청중들은 잡담을 듣거든요..
00:08:19여기 들어와서요.
00:08:20트래시와 그의 포켓몬 중독에 대해서도 듣게 되죠.
00:08:23당신은 아마 모를 거예요.
00:08:24왜냐하면 YouTube에서 이걸 듣고 있으니까요, 그렇죠?
00:08:27재미있는 얘기들을 다 듣지 못하는 거예요.
00:08:29YouTube 영상의 처음 10분으로는 꽤 팔기 어려운 내용이죠.
00:08:32YouTube 영상으로는 정말 힘든 판매죠.
00:08:34'나는 내가 이해도 못하는 걸 네 명이 얘기하는 걸 볼 거야.
00:08:37그리고 그게 다이나모 DB라고 불리는 거래'가 되는 거니까요.
00:08:40맞아요..
00:08:41팟캐스트를 시작하는 김에 아담을 소개해야 할 것 같은데요. 아, 그러네요. 아주 좋은 지적이에요.
00:08:45전혀 안 했네요. 안녕하세요. 오늘 팟캐스트에 나오신 이유를 좀 말씀해주세요.
00:08:50왜냐하면 제가 TJ네 집에 있거든요.
00:08:53첫 번째 이유,
00:08:541번 이유는 TJ가 자기 집에 방문하는 모든 사람에게 팟캐스트에 나올 것을 요구하기 때문이죠.
00:09:02몇 번은 좀 어색했죠.
00:09:03네.
00:09:04맞아요.
00:09:04당신은 정말 누구세요??
00:09:07AWS 히어로라는 것 외에요. 저는 그것도 아니에요. AWS 히어로가 아니었어요. 알겠어요.
00:09:13슈퍼히어로 그룹에서 쫓겨났다고요. 그게 어떻게 작동하는 거예요? 그냥 갱신이 안 되는 건가요?
00:09:18저는 한 번만 히어로였고 그들이 결정한 거죠.
00:09:20'아, 당신은...' 돈 내는 건가요.
00:09:22히어로가 되려면 돈을 내야 하나요?.
00:09:24아니요, 아니에요.
00:09:25그냥 저는 더 이상 그것에 대해 신경 쓰지 않았어요.
00:09:28전혀 얘기 안 했거든요.
00:09:29그래서 그들이 '어쩌면 그는 더 이상 히어로가 아닐지도 몰라.
00:09:32이제 그는 빌런이야'라고 한 거죠.
00:09:34케이시는 마치 살인 미스터리의 일부처럼 보이네요.
00:09:36거기 서 있는 게.
00:09:37오 이런.
00:09:37우리가 곧 뭘 보게 될 거냐면, 어, 뭐더라?
00:09:40닉 힐.
00:09:40보드에다 전부 그림 그리는 그 사람이요.
00:09:42그리고 나타나잖아요.
00:09:43케이시 무라토리.
00:09:44당신이 생각하는 사람이 그 사람이죠.
00:09:46무라토리.
00:09:46무라토리인가요, 아니면 무라토리인가요?
00:09:48오 세상에.
00:09:49곧 시각자료 쓰실 거죠?
00:09:50그래서 제가 이게 최고의 팟캐스트라고 하는 거예요..
00:09:54말 그대로 이게 참여하기에 최고의 팟캐스트예요.
00:09:57어, 우리 가족은 무라토리라고 발음해요.
00:10:00마치 거기에 Y가 있는 것처럼, 무라토리라고요.
00:10:03하지만 맞는 발음이에요.
00:10:05별로 말이 안 되는 게, 이탈리아어거든요.
00:10:08이탈리아 이름이에요.
00:10:09그리고 이탈리아어로는 무라토리나 무라토리일 거예요..
00:10:13말이 안 되죠.
00:10:14그래서 왜 무라...
00:10:16가 된 건지 전혀 모르겠어요.
00:10:18이탈리아계 미국인 같은, 이민자들 사이에서 일어난 일인 것 같아요.
00:10:23모르겠어요.
00:10:24좋아요.
00:10:24그래서 기본적으로 그들이 말한 건 이거예요..
00:10:28그들은 API 엔드포인트라고 부르는 것들을 가지고 있는데, 그걸 그렇게 부르죠.
00:10:34그리고 이것들은 도메인 주소입니다.
00:10:37DNS에서 찾아볼 때, DynamoDB 요청을 어디로 보내야 할지 알기 위해 찾게 될 이름이죠.
00:10:44그리고 이것들은 아마 이렇게 생겼을 겁니다..
00:10:47그리고 Adam이 아마 확인해줄 수 있을 거예요. 왜냐하면 그는 영웅이거나, 영웅이었으니까요.
00:10:53이것들은 마치, 아 뒤에 있네요.
00:10:55네.
00:10:56우리가 몇 초 뒤처져 있어요.
00:10:58리버에서 비디오가 사라졌거든요.
00:11:00아, 됐네요.
00:11:01그래서 이것들은 dynamodb.use-east-1.api.aws 같은 형태로 생겼습니다.
00:11:07그리고 IPv6를 사용하는지 IPv4를 사용하는지에 따라 달라지는 것 같아요.
00:11:12상황에 따라 다른 이름을 가지거나, 특정한 것을 사용하는지에 따라서요.
00:11:16정부 기관은 다른 것을 사용한다고 언급했던 것 같고요.
00:11:20그래서 이 이름들은 기본적으로 애플리케이션에 하드코딩하는 이름들입니다.
00:11:24DynamoDB로 뭔가를 해야 할 때, 이걸 요청하는 식이죠.
00:11:28이게 말이 되나요.
00:11:30그리고 맞게 들리나요.
00:11:31Adam, 왜냐하면 저는 AWS 관련 것들을 사용하지 않거든요.
00:11:35네?
00:11:36네?
00:11:36네.
00:11:37맞아요..
00:11:38그래서, 당신은 이런 것을 요청하게 되고 완벽하게 전송하게 됩니다.
00:11:42제 말은, 그가 무슨 말을 하는지 알겠어요.
00:11:45네.
00:11:46그러면 그게 어딘가로 리디렉션될 거예요.
00:11:49왜냐하면 분명히 전 우주의 모든 DynamoDB 트래픽을 처리할 단일 머신 같은 건 없을 테니까요.
00:11:56여기서 볼 수 있듯이 지역별로 세분화한다고 해도, 어느 지역을 선택해야 하는 것 같아요.
00:12:02추측하건대, 메인 주소로 보내는 게 아니라 지역 주소로 보내는 거죠.
00:12:07아니면 알아서 처리해줄 메인 주소가 있을 수도 있고요.
00:12:11잘 모르겠어요..
00:12:13어쨌든,
00:12:13어느 시점에서 이것과 통신하게 되는데,
00:12:16이것은 기본적으로 로드 밸런싱 체계 같은 것을 가리켜야 합니다.
00:12:21그래서 이것은 기본적으로 그들이 DNS 트리라고 부르는 것을 가리켜야 하죠..
00:12:27비록 그들이 트리의 특성에 대해 전혀 설명하지는 않았지만요.
00:12:31오히려 그냥 가중치 배열 같은 것처럼 들렸어요.
00:12:34여기 여러 머신들이 있고, 로드 밸런싱을 위해 우리가 설정한 가중치에 따라 그 머신들을 선택하는 거죠.
00:12:41그래서 머신이 뒤처지면 가중치를 낮게 설정하고, 머신이 비어 있는 것 같으면 가중치를 높게 설정하는 식이죠.
00:12:48그래서 그들은 그걸 트리라고 불렀어요.
00:12:50그래서 트리라고 가정하는 건데, 트리 부분이 뭔지는 설명하지 않았어요.
00:12:55하지만 이 이름은 가리켜야 합니다.
00:12:57잠깐만 끼어들어도 될까요??
00:13:00그런데, 실제로 누군가가 그 트리로 L6 승진을 받았다고 하더라고요.
00:13:03그래서 다음번에는 그 트리가 뭔지 알아보셔야 할 것 같아요.
00:13:06왜냐하면 그게 누군가에게는 정말 중요했던 거니까요.
00:13:09좋아요.
00:13:09패킷도 있었고 엔지니어들도 있었죠.
00:13:11동의해요.
00:13:11트리는 아마 중요할 거예요.
00:13:13단지 버그에는 중요하지 않았을 뿐이죠.
00:13:15그리고 그것조차도, 그래서 제 말은 그들이 트리를 설명할 필요가 없었다는 거예요..
00:13:19그래서 그들이 트리가 뭔지 건너뛴 건 괜찮다고 봐요. 하지만 저도 간단한 질문이 하나 있어요.
00:13:25네.
00:13:26그게 근본 원인 분석(root cause analysis)이라서 트리라고 부르는 건가요, 아니면 아닌가요??
00:13:29더 이상 농담은 안 돼요.
00:13:31너무 주제에서 벗어났어요.
00:13:33죄송해요.
00:13:33죄송해요.
00:13:34어쨌든, 이것은 그걸 가리켜야 합니다..
00:13:37그리고 이런 DNS 항목들의 로드 밸런싱 방식이 있는데,
00:13:41발표에서 이것을 설명한 방식은 plan145.dynamodb.ddb.aws 같은 걸 사용한다는 거예요.
00:13:49이게 그 트리의 루트인데, 근본 원인 분석이 아니라 이 트리 구조에서 루트라는 말이에요.
00:13:55여기에는 로드 밸런싱을 가능하게 하는 여러 레코드들의 최상위 레코드가 포함되어 있죠.
00:14:01그리고 Route 53이 이런 로드 밸런싱 기능을 가지고 있을 거라고 추측해요.
00:14:07발표 내용을 읽으면서 유추한 건데,
00:14:09그들이 직접적으로 말하진 않았지만,
00:14:12Route 53이 자체 DNS 시스템이고 이걸 통해 모든 걸 처리하는데,
00:14:17여기에 로드 밸런싱이 어떻게 작동해야 하는지 설정해두면 그게 가능해지는 것 같아요.
00:14:23그러면 일종의 무작위 방식과 가중치 같은 걸 기반으로 올바른 머신을 선택하는 거죠.
00:14:29그런데 그들이 말한 건,
00:14:31실제로 존재하는 이 이름이나 이런 식의 트리 같은 게 있는데,
00:14:35이 이름은 발표용으로만 사용한 거라는 거예요.
00:14:38실제로는 plan145 같은 사람이 읽을 수 있는 이름을 사용하지 않았대요.
00:14:44실제로는 뭔가를 해시한 값이었다고 해요.
00:14:46그러니까 실제로는 0aFE129a 같은 게 들어가 있었을 거예요.
00:14:51그래서 실제로 가서 보면 사람이 읽을 수 있는 이름은 보이지 않았을 거예요.
00:14:56적어도 그 당시에는요.
00:14:58plan145 같은 건 안 보이고 그냥 해시값만 보였을 거예요.
00:15:03그래서 아이디어는 이런 거죠.
00:15:05사용자가 이걸 사용하려고 하면 이 이름을 쿼리하고,
00:15:08Route 53이 여기로 연결해주는데,
00:15:11이게 일종의 로드 밸런싱 트리고 Route 53이 이걸 사용해서 당신이 가야 할 곳으로 보내주는 거예요.
00:15:18결국엔 실제로 트래픽을 보낼 수 있는 머신을 알려주는 거죠.
00:15:23근데 또 그들은 그런 부분을 설명하지 않아서 그게 어떻게 작동하는지는 전혀 모르겠어요.
00:15:29Route 53을 만져본 적도 사용해본 적도 없어서 모르겠지만, 어쨌든 그렇게 된다고 가정하죠.
00:15:36이 버그하고는 상관없으니까요..
00:15:41AWS 전문가가 있으니까 혼란스러우면 Adam한테 물어보면 되죠.
00:15:46더 많은 인사이트를 줄 수도 있을 거예요.
00:15:49그래요, 해보세요..
00:15:50Route 53에는 트래픽을 분할하는 여러 가지 방법이 있어요.
00:15:53그래서 네, 가중치 방식도 그 중 하나고, 그들이 설명한 게 그런 것 같네요..
00:15:57어떻게든 이런 레코드들을 그렇게 설정해놨는데, 어떻게 했는지는 말 안 했어요.
00:16:01하지만 뭔가 트리 형식으로 그걸 했죠.
00:16:04제 추측으로는 트리에 가중치가 있는 것 같아요.
00:16:06최상위에 몇 개의 가중치가 있고 거기서 더 많은 가중치로 분기되는 식으로요.
00:16:11레코드가 많으니까 그게 처리하기 더 쉬웠을 거예요..
00:16:14누가 알겠어요. 어쨌든 모르겠어요. 요점은 이게 정상적으로 일어나야 하는 일이라는 거죠.
00:16:20이제,
00:16:20실제로는 해시 코드였을 텐데 여기서 plan145라고 부르는 이유는,
00:16:26상상하시겠지만 로드 밸런싱이 계속 지속되어야 하기 때문이에요.
00:16:31DynamoDB 머신들이 항상 뭔가를 하고 있으니까요.
00:16:35과부하가 더 걸리기도 하고, 머신이 다운되거나 크래시되거나 누가 알겠어요, 그렇죠??
00:16:43오프라인으로 전환될 수도 있고, 새로운 용량이 추가될 수도 있습니다.
00:16:48그래서 이런 것들은 항상, 정말 항상 업데이트되어야 합니다.
00:16:53그래서 여러분이 연결하는 이 메인 API 엔드포인트는 그것이 가리키는 트리를 지속적으로 조정해야 합니다.
00:17:01그래서 그들이 하는 방식은 또 다른 트리, 즉 이동할 트리를 만드는 겁니다.
00:17:08예를 들어, 플랜 146 같은 걸 만드는 거죠.
00:17:11그리고 여기에 전체 트리를 만듭니다.
00:17:14그런 다음 준비가 되면,
00:17:16이 트리가 완성되면,
00:17:18이 레코드를 가져와서 저것을 가리키는 대신 이것을 가리키도록 하는 겁니다.
00:17:24즉, 새로운 것을 만들고, 그냥 그 이름을 바꿔서 이것으로 옮기는 거죠.
00:17:30그런데 어떤 이유로, 이 이유는 실제로 설명되지 않았는데요..
00:17:36그들이 그 프로세스를 설정한 방식은 두 개의 조각으로 나누는 것입니다.
00:17:41기본적으로 새로운 트리가 어떻게 생겨야 하는지 파악하는 플래너(planner)라는 것이 있습니다.
00:17:47그래서 플래너라고 불리는 어떤 머신이 있다고 상상할 수 있습니다.
00:17:52그게 실제 머신인지 아니면 다른 것들을 실행하는 어떤 머신에서 실행되는 프로세스일 뿐인지는 모르겠습니다.
00:17:59하지만 플래너라고 불리는 무언가가 있습니다.
00:18:01그리고 제가 파악한 바로는, 단 하나만 있습니다.
00:18:05즉, 우리가 전환할 새로운 플랜이 어떻게 생겨야 하는지 파악하는 플래너가 하나 있다는 뜻입니다..
00:18:13그리고 이것은 계속 작동합니다.
00:18:15그래서 플랜 145를 생성하고,
00:18:17그 다음 플랜 146을 생성하고,
00:18:20그 다음 147,
00:18:21148,
00:18:229,
00:18:2210,
00:18:23뭐 그런 식으로 계속되는 거죠?
00:18:25그리고 영원히 플랜을 계속 내놓습니다.
00:18:28그게 그것의 일이니까요.
00:18:30그런데 실제로는 그것들을 생성하지 않는 것 같습니다.
00:18:34그것의 일은 Route 53에 실제로 만드는 게 아닙니다.
00:18:38누군가가 Route 53에 넣는다면 그것들이 어떻게 될지 파악하는 것이 일입니다.
00:18:44그런 다음 세 개의 인액터(enactor)가 있습니다..
00:18:50이 인액터들은 플래너로부터 플랜을 받아서 Route 53에 넣습니다.
00:19:06이해가 되나요?
00:19:07자, 제가 발음을 이해한 바로는 플래너 하나, 인액터 세 개입니다.
00:19:11왜 이렇게 되어 있는지에 대한 설명은 없었습니다.
00:19:15그들은 인액터가 세 개인 이유는 장애 허용(fault tolerant)을 위해서라고 했습니다.
00:19:20즉, 그 중 하나가 다운되거나 하는 경우를 대비해서요.
00:19:24하지만 그렇다면 왜 플래너도 세 개가 필요하지 않은지는 설명하지 않았습니다.
00:19:29왜냐하면 플래너가 다운되면 인액터들이 실행할 것이 없거든요.
00:19:32그래서 별로 말이 안 됐습니다.
00:19:34그래서 왜 이 구조가 이렇게 생겼는지에 대한 설명이 발표에 없었습니다.
00:19:39이것이 이렇게 생긴 것이 버그와 크게 관련이 있는 것은 아니지만,
00:19:43나중에 보겠지만 어느 정도는 관련이 있습니다.
00:19:46그래서 저는 그들이 이것을 정당화하지 않았다는 사실에 약간 이상하다고 느꼈지만, 괜찮습니다.
00:19:51아무튼 이해가 되길 바랍니다.
00:19:53우리는 플래너가 하나 있습니다.
00:19:55인액터가 세 개 있습니다.
00:19:57인액터들은 모두 이 플랜을 실행하려고 합니다.
00:19:59자,
00:20:00여기서 일어나는 일은,
00:20:01다시 말하지만,
00:20:02그들이 발표에서 말한 유일한 것은 "추론하기 더 쉽게 만든다"는 것이었습니다.
00:20:07이것이 유일한 정보였습니다.
00:20:09그들은 추론하기 더 쉽게 만든다고 말했습니다.
00:20:12추론하기 더 쉽게 만들기 때문에, 이 인액터들은 직렬화(serialization)를 사용합니다.
00:20:18그래서 그들이 그냥 레코드를 만들려고 하고,
00:20:20레코드가 이미 있으면 그냥 만들지 않는 것이 아니라,
00:20:24다시 말해서,
00:20:24세 사람이 실행되고 있습니다..
00:20:29우리 모두 이 최상위 레코드, plan146.ddb.aws를 만들고 싶어 합니다, 맞죠?
00:20:36우리 모두 그걸 하려고 노력하고 있어요.
00:20:39우리 중 한 명이 먼저 해요.
00:20:41다음 사람이 하려고 하면 이미 거기에 있거나 뭐 그런 거죠?
00:20:44우리 모두 같은 레코드를 만들려고 하는 거예요.
00:20:48그래서 이론적으로는 세 사람이 계획의 어떤 부분을 처리하려고 하든 무작위로 마구 두드려도 이론적으로는 다 잘 작동해야 하는 거죠?
00:20:56그리고 발표자가 직접적으로 말하지는 않았지만, 제가 방금 말한 것에 동의할 것 같다는 느낌을 받았어요.
00:21:03즉, 그들이 그냥 임의로 실행하게 해도 괜찮았을 거라는 거죠.
00:21:07하지만 그는 추론하기 쉽게 만들기 위해 직렬화를 사용한다고 말했어요.
00:21:11그 의미는 이 실행자들이 그렇게 마구 두드리는 대신,
00:21:15업데이트하려는 엔드포인트에 대한 락을 획득하려고 시도한다는 거예요.
00:21:19다시 말해서,
00:21:20이 사람이 이것들 중 하나를 업데이트하려고 한다면,
00:21:23그리고 제가 받은 느낌은 이것을 업데이트하려고 한다면이었는데,
00:21:27이것을 업데이트하려고 한다면일 수도 있고,
00:21:30아니면 둘 다일 수도 있었어요.
00:21:32제 기억이 맞다면 락킹이 정확히 어디에서 발생하는지 100% 명확하게 말하지는 않았어요.
00:21:38하지만 락킹은 그들이 "좋아, DNS 레코드인 락을 만들 거야"라고 하면서 발생해요.
00:21:44그리고 Route 53이 원자적이라는 개념을 가지고 있다는 사실을 이용해서,
00:21:49즉 두 가지를 할 수 있는데 둘 다 성공하지 않으면 둘 중 어느 것도 하지 않는다는 거죠.
00:21:55그들은 기본적으로 Route 53을 통해 락을 거는 락킹 시스템을 만들었어요.
00:22:00그래서 Route 53의 DNS 레코드가 실제로 락 레코드인 거죠, 이해가 되나요??
00:22:08빠른 질문 해도 될까요?
00:22:10네.
00:22:11직렬화를 통해 이걸 한다고 하셨는데요?
00:22:14무슨 뜻인지 잘 이해가 안 가요.
00:22:16직렬화는 한 메모리에서 다른 메모리 표현으로 변환하는 거라고 생각했거든요.
00:22:22죄송해요, 다른 직렬화예요.
00:22:24네, 그것도 직렬화예요.
00:22:26이 경우에는 말 그대로 시간적 직렬화를 의미하는데,
00:22:30이 실행자들이 임의로 동작하는 게 아니라 어떤 순서로 행동을 조직화할 수 있는 방법을 원했다는 거예요.
00:22:38그리고 그들이 그렇게 한 방법이 락킹이었어요.
00:22:42그래서 일어나는 일은,
00:22:43이 사람이 하려는 일을 그냥 하는 대신,
00:22:46예를 들어 "좋아,
00:22:48이거 끝냈으니까 이 녀석을 계획 146에 연결할 거야"라고 하는 대신,
00:22:53이것에 대한 락을 획득하려고 시도하는 거죠?
00:22:57그리고 락을 얻지 못하면 변경하지 않아요.
00:23:00그래서 이 실행자들 중 한 명만 주어진 시간에 이것을 업데이트하는 과정에 있을 수 있어요.
00:23:07이해되나요?
00:23:08음.
00:23:09다시 말하지만, 그들이 정확히 왜 그렇게 하려고 했는지는 설명되지 않았어요.
00:23:15그냥 추론하기 쉽게 만든다고 말하고 거기서 끝났어요.
00:23:19그래서 왜 그들이 이게 개선이라고 생각했는지 모르겠어요.
00:23:23그리고 재미있게도, 이게 결국 버그를 발견하게 만들었어요.
00:23:28그래서 개선이 아니었죠.
00:23:29어쩌면 오히려 나빴을 거예요.
00:23:32그래서 Casey, 그들이 좋은 이유가 없다는 거예요?
00:23:36실행자들을 거의 한 번에 하나씩 실행하게 만들겠다고 하는데, 왜 실행자가 세 개나 있나요?
00:23:43이해가 안 가요.
00:23:44왜 하나만 두지 않나요?
00:23:46그냥 말하지 않았어요.
00:23:48우리는 이유를 몰라요.
00:23:50그리고 정확히 설명하지도 않았어요.
00:23:52세 개의 동시 실행자가 있는데 대한 설명을 정말 듣지 못했어요.
00:23:57그들이 다운될 수 있을 거라고 예상하는데, 그래서 세 개가 있는 거죠..
00:24:07맞아요. 하지만 락을 걸잖아요. 그럼 이 녀석이 락을 걸고 다운되면 어떻게 되나요?
00:24:13그러니까, 그것에 대한 설명도 들은 적이 없어요.
00:24:17그래서 이게 저한테는 정말 혼란스러웠죠.
00:24:19여기서 우리가 논의하는 내용의 일부로 불평하는 건 아니에요.
00:24:23왜냐하면 저한테 중요한 사안은 아니거든요.
00:24:26하지만 발표 자체로서는 정말 궁금한 게 많았어요.
00:24:29솔직히 왜 이런 걸 했는지 전혀 이해가 안 되더라고요.
00:24:33맞죠.
00:24:33그리고 아마 그건 다시 말하지만, 제가 AWS 서비스를 안 쓰기 때문일 수도 있어요.
00:24:39Route 53 같은 걸 정기적으로 사용하는 사람이라면 이런 것들 중 일부가 당연하게 느껴질 수도 있겠죠.
00:24:46아, 락에 타임아웃을 설정할 수 있기 때문이구나, 뭐 그런 식으로요.
00:24:50모르겠어요.
00:24:51그렇죠.
00:24:51어쨌든, 그래서 그들은 그렇게 하고 있었고요.
00:24:54결과적으로 어떤 일이 벌어지냐면,
00:24:57이 버그를 발견하게 된 계기가 된 일인데요,
00:24:59이 실행자들이 락을 얻지 못하면 그냥 백오프를 하는 거예요.
00:25:03맞죠?
00:25:04기본적으로 그냥 괜찮아, 좀 기다렸다가 다시 시도할게, 이런 식이죠.
00:25:08그래서 실행자, 이 실행자가 락을 얻으려고 하는데 다른 누군가가 이미 락을 갖고 있어요.
00:25:14그래서 잠깐 기다렸다가 락을 다시 얻으려고 시도하죠.
00:25:17그런 일이 벌어지는 거예요.
00:25:19맞죠.
00:25:20그리고 그들이 말하길, 병리학적 케이스라고 표현했는데요, 실행자 중 하나가 어떤 플랜을 실행했어요.
00:25:26그 플랜이 꽤 오래된 거였다고 해봅시다.
00:25:29그들이 예시로 110을 사용했던 것 같아요.
00:25:32그래서 플랜 110을 실행했죠.
00:25:34그리고 API가 제 110을 가리키도록 설정해야 한다고 생각하는 거예요.
00:25:38dynamodb.use.one인가 뭔가 그런 걸 업데이트하기 위해 락을 얻으려고 시도하는데,
00:25:44다른 누군가가 플랜 111 같은 걸 실행하고 있어서 실패하는 거죠.
00:25:49아니면 플랜 109일 수도 있고, 이전 플랜일 수도 있고요.
00:25:53그래서 다른 실행자들이 그걸 하고 있어요.
00:25:55이 실행자는 할 수가 없죠.
00:25:57백오프하는 거예요.
00:25:58맞죠..
00:26:02그리고 기억하세요, 여기 이 실행자는 110에 있어요. 시도하고 있고, 정말로 실행하고 싶어 하죠.
00:26:07다시 시도해요.
00:26:08다른 누군가가 락을 갖고 있네요.
00:26:10또 시도해요, 여전히 잠겨있어요.
00:26:12이 사람은 110에 붙어서 필사적으로 실행하려고 하는데 할 수가 없어요.
00:26:16명백히 이게 너무 많이 반복됐고,
00:26:18그 사이에 다른 실행자들과 플래너는 계속 새 플랜을 만들어내고 있는 거예요.
00:26:22맞죠..
00:26:23다른 실행자들은 145나 146 정도까지 올라가서 110보다 훨씬 앞선 플랜들을 실행하고 있어요.
00:26:30맞죠.
00:26:30그리고 이 친구는 여전히 멈춰있죠.
00:26:33운이 없게도 락을 한 번도 못 얻어서요.
00:26:36맞죠.
00:26:36마침내,
00:26:37플랜 145가 이미 다른 실행자에 의해 실행되고 가리켜지고 그런 일들이 다 일어난 후에야,
00:26:43플랜 110,
00:26:44이 실행자가 여전히 시도하다가 마침내 락을 얻게 돼요.
00:26:48그러니까, 그렇죠.
00:26:49그래서 그가 말하는 거예요, 좋아, 이제 우리는 110을 가리키고 있어.
00:26:54그렇죠.
00:26:55맞죠..
00:26:58그래서 이제 엄청 오래된 낡은 플랜을 가리키고 있는 건데, 사실 이게 문제가 되지는 않아야 해요. 맞죠.
00:27:03왜냐하면 결국 다음번에 어떤 실행자가 뭔가를 갖게 되면, 그건 훨씬 나중 플랜일 테니까요.
00:27:07그냥 플랜 146이나 147이나 148 뭐 그런 걸 실행하겠죠.
00:27:11그리고 이걸 다시 가리키면 우리는 다시 새 플랜으로 돌아가요.
00:27:14그래서 모두가 몇 분 동안 나쁜 로드 밸런싱을 겪겠지만, 그 다음엔 괜찮아질 거예요.
00:27:18맞죠.
00:27:19실제로 적어도 몇 분 동안은 나쁜 로드 밸런싱을 겪긴 했어요..
00:27:22맞죠. 네. 사실이에요. 근데 그것보다 훨씬 더 심각했어요. 그게 일어났어야 했던 일이죠. 맞죠.
00:27:30그러니까 그들도 이렇게 작동할 거라고 예상했다는 거죠.
00:27:34알겠어요.
00:27:35문제는 이것들이, 그들은 또한 Route 53이 이 모든 레코드들로 막히는 걸 원하지 않았어요.
00:27:42왜냐하면 그냥 놔두면, 결국 석 달 후에는 Route 53에 약 80억 개의 레코드를 쌓아놓게 되니까요.
00:27:50몇 분마다 이 큰 가중치 트리 같은 걸 넣는 거잖아요.
00:27:54그들은 생각했죠, 좋아, 어느 시점에서는 이 플랜들을 정리해야 해..
00:28:00그래서 enactor들은 특정 시간보다 오래된 플랜도 찾습니다.
00:28:04그리고 특정 시간보다 오래되면 삭제하죠.
00:28:07그래서 일어난 일은, 플랜 110을 가리키게 된 겁니다.
00:28:11이 enactor가 마침내 락을 획득합니다.
00:28:14110을 가리키죠.
00:28:15다른 enactor는 "오, 와우, 110이라니, 엄청 오래됐네.
00:28:20이거 제거해야겠다"라고 생각하고 삭제합니다.
00:28:23그러니까 이제 DynamoDB us-east-1.api.aws가 해결될 수 없는 레코드를 가리키게 된 겁니다.
00:28:30맞죠.
00:28:31실제로는 플랜 110처럼 보이지 않고 OAFE129A 같은 해시값,
00:28:36점,
00:28:36그리고 DDB.aws 이런 식으로 보일 겁니다.
00:28:39하지만 그 이름을 가리키고 있는데, 그 이름을 조회하면 아무것도 나오지 않습니다..
00:28:46그래서 그 시점에 일어나는 일은,
00:28:48데이터를 보낼 엔드포인트를 가져오려는 모든 사람들이 기본적으로 해결할 수 없는 이름을 받게 되는 겁니다.
00:28:54맞죠.
00:28:55그리고 Route 53에서 그런 일이 발생하면 정확히 무슨 일이 일어나는지는 잘 모르겠지만,
00:29:00기본적으로 사용할 수 없거나 IP 대신 횡설수설하는 값을 받게 될 겁니다.
00:29:04누가 알겠어요.
00:29:05하지만 어떤 값이든, 실제로 사용하려고 시도하면 응답을 받을 수 없을 겁니다.
00:29:09맞죠..
00:29:10흥미롭네요.
00:29:11이게 AWS가 Rust를 충분히 사용하지 않아서 그런 건가요?
00:29:15명백하게 use-after-free 버그잖아요.
00:29:18그래서 Rust를 사용했으면 해결됐을 거라고 생각하시나요?
00:29:21Route 53을 완전히 Rust로 다시 작성했다면, 분명히 이런 문제들은 없었을 거라고요.
00:29:27아니요,
00:29:28구체적으로 말하면,
00:29:29프레젠테이션에서 언급했던 걸로 기억하는데,
00:29:31Rust에 대한 얘기는 아니었지만 구체적으로 무슨 일이 일어나는지 설명했었습니다.
00:29:37이것 또는 저것을 조회하면,
00:29:38어느 쪽을 말하는 건지 정확히 기억은 안 나지만,
00:29:41레코드를 찾을 수 없다는 응답을 받게 된다고 했던 것 같습니다.
00:29:45그게 최종 결과예요.
00:29:47이것을 조회하든 저것을 조회하든, 확실하지는 않지만, 그냥 레코드를 찾을 수 없다는 응답을 받게 됩니다.
00:29:53그게 그 API를 호출하려고 할 때 받게 되는 응답이었죠.
00:29:57그래서 DynamoDB를 사용하기 위해 어떤 라이브러리를 사용하든, 그냥 "야, 레코드 못 찾았어.
00:30:03미안"이라고 할 겁니다.
00:30:05맞죠.
00:30:05그래서 인터넷에 있는 누구에게나 물어보면, 다들 "응, 버그를 설명했어.
00:30:10그게 버그야.
00:30:10race condition이 있었다는 거지"라고 합니다.
00:30:14모두가, race condition이라고 말하는 순간 모두의 뇌가 멈춰버립니다.
00:30:19"오, 알겠어, race condition이었구나.
00:30:22끝"이라고 하죠.
00:30:23볼 것 없다는 식으로요.
00:30:25맞죠?
00:30:25그래서 다들 "race condition이야.
00:30:28설명했잖아"라고 하는데, 아니에요, 설명 안 했어요.
00:30:31왜냐하면 여기서 무슨 일이 일어날지 생각해보면,
00:30:34바로 직후에 모두가 이걸 받게 되고,
00:30:37새로운 enactor가 그냥 새로운 걸 enact할 겁니다.
00:30:40맞죠?
00:30:41그래서 진짜 버그는, 왜 그게 일어나지 않았냐는 겁니다.
00:30:44제가 보고 싶었던 진짜 RCA는 왜 다음 actor가 와서 고치지 않았냐는 거예요.
00:30:50다른 것도 얘기해볼까요?
00:30:51이것도 버그 아닌가요?
00:30:52즉시 삭제되어야 할 정도로 오래된 레코드를 왜 쓰는 거죠?
00:30:56음, 그건 이 녀석이 꽤 오래 전에 썼기 때문이었어요.
00:30:59그리고 그건...
00:31:00음, 만약 왜 더 나은 코드로 actor를 작성하지 않았냐고 묻는 거라면, 네, 그것도 괜찮은 질문이네요..
00:31:11좋아요, 맞네요.
00:31:12즉시 삭제되어야 할 것으로 업데이트하는 건, 그게 바로 문제인 것 같은데요.
00:31:17훨씬 이전에 뭔가 잘못한 거잖아요.
00:31:19네,
00:31:20이것의 이론적 구조를 실제로 고치지는 못하더라도,
00:31:23이 녀석이 락 대기에서 백오프를 마친 후에 간단한 체크를 하나 하는 게 좋을 것 같아요.
00:31:29삭제 코드를 실행한다면 자기가 삭제할 만한 값으로 설정하려고 하는 건 아닌지 확인하는 것이 아마 좋은 안전 조치일 겁니다.
00:31:37하지만 네, 100% 동의합니다.
00:31:39좋아요, 하지만 enactor가 그 레코드를 얻으려고 정말, 정말 열심히 일했어요.
00:31:45오랫동안 기다렸죠.
00:31:46오, 포켓몬 카드를 가질 거예요..
00:31:49누가 기다렸든. 그러니 그냥 레코드를 쓰게 놔두세요. 좋아요. 그래서, 그래서 그것에 대해 듣고 싶네요.
00:31:56안타깝게도, 발표 자료를 보면, RCA를 봐도, 그 내용이 어디에도 없습니다.
00:32:03발표 자료에는 적어도 12초짜리 아주 작은 부분이 하나 있는데,
00:32:10거기서 버그가 대략 어디에 있을지 언급하긴 합니다.
00:32:15그래서 그게 뭔지 설명해드리겠습니다.
00:32:19명백히 이런 일이 함께 발생하는데,
00:32:22DynamoDB us-east-1을 사용할 때,
00:32:27그걸 플랜에 연결하면서 동시에 다른 작업도 수행합니다.
00:32:32그 작업은 롤백을 설정하는 겁니다..
00:32:40DD인 것 같은데요. DDB.rollback.AWS였나요? 정확히 기억이 안 나네요.
00:32:49롤백 레코드가 있습니다.
00:32:50그 레코드를 이전 플랜이 무엇이었든 그것으로 설정합니다.
00:32:55만약 여기서 145를 가리키고 있었는데,
00:32:57이제 110을 가리키려고 한다면,
00:33:00이 옛날 작업자가,
00:33:01저는 110으로 이동하고 있어요,
00:33:04라고 하면서 설정을 시도하는 거죠.
00:33:06현재 이 이름이 무엇이었든 가져와서, 그 이름을 이동시킵니다.
00:33:11플랜 145였을 텐데, 그걸 이동시켜서 롤백 주소가 이전 플랜을 가리키도록 합니다..
00:33:18맞습니다. 그리고 이건 그냥 디버깅용입니다. 또는, 기본적으로 운영자의 편의를 위한 거죠, 그렇죠?
00:33:24이전 플랜으로 롤백하고 싶거나 뭐 그런 경우를 위한 거죠.
00:33:28또는 이전 플랜이 뭐였는지 알고 싶으면 여기서 볼 수 있는 거고요, 맞죠?
00:33:32그게 그들이 장애에 대해 말한 방식의 첫 번째 부분입니다.
00:33:36여기서 한 가지 지적하고 싶은 게 있는데, 이것도 저한테는 전혀 이해가 안 갔어요.
00:33:41왜냐하면 제 생각엔,
00:33:42좋아요,
00:33:43이것들이 1분마다 업데이트된다고 말씀하시는 건데,
00:33:46그런 걸 하나 가지고 있는 게 무슨 소용이에요?
00:33:48로그인할 때쯤이면 이미 롤백하려던 것에서 새로운 것으로 업데이트됐을 텐데,
00:33:53그게 실제로는 원하지 않는 플랜이잖아요.
00:33:55모든 게 다운됐으니까요, 맞죠?
00:33:57그러니까, 맞죠?
00:33:58이건 원하지 않는 거예요.
00:34:00그냥 이름들을 리스트로 가지고 있어야 해요.
00:34:02그래야 12시 30분에 뭐였지?
00:34:04저거였어, 이렇게 할 수 있잖아요, 맞죠?
00:34:07그래서 이건 저한테 전혀 말이 안 됐어요.
00:34:09왜 이게 좋을 수 있는지 정말 전혀 모르겠어요, 맞죠?
00:34:12실제로 원하는 일을 할 것 같지 않았거든요.
00:34:15원하는 건 특정 시점을 표시해서,
00:34:17오후 1시로 돌아가야 해,
00:34:19그 이후로 모든 게 엉망이 됐으니까,
00:34:21이렇게 할 수 있는 거잖아요,
00:34:22맞죠??
00:34:26어쨌든, 그래서 저한테는 말이 안 됐어요.
00:34:29하지만 다시 말하지만, 버그와 정확히 관련된 건 아니니까.
00:34:32그래서 왜 그런지 묻지 않았어요.
00:34:34그냥, 좋아요, 그게 해야 하는 일이군요.
00:34:36그리고 한 버전만 롤백할 수 있다는 거죠, 그렇게 말씀하시는 거죠.
00:34:40네, 다른 트리들은 존재하는데도 말이죠.
00:34:42그러니까 이름만 알면 쉽게 할 수 있는 건데.
00:34:44그래서 이건 그냥 거의 확실히 신경 쓰지 않을 것에 사람이 읽을 수 있는 이름을 붙이는 거예요.
00:34:50맞습니다.
00:34:50하지만 그들은 정말 그렇게 많은 걸 저장할 수 없어요..
00:34:54Casey,
00:34:54제 생각엔 그들이 정말로,
00:34:56모르겠어요,
00:34:57Adam,
00:34:57이런 식으로,
00:34:58거기엔 확장성이 많지 않아요,
00:35:00맞죠?
00:35:00많은 라인들이니까요.
00:35:02제가 했다면, 그냥 이걸 타임스탬프로 만들었을 거예요.
00:35:05그게 원하는 거라면요, 맞죠?
00:35:07저라면, 플래너가 언제, 또는 이 사람이 이걸 언제 가리켰는지를 말했을 거예요.
00:35:12락을 얻었을 때, 이 이름을 타임스탬프로 바꾸고, 이걸 하나의 원자적 작업으로 업데이트하는 거죠.
00:35:18그러면 오후 1시로 롤백하고 싶으면,
00:35:20타임스탬프를 가진 것 중에서,
00:35:22가장 이른 타임스탬프를 찾으면 되는 거예요,
00:35:25그 시간 이후가 아닌 거요..
00:35:28그리고 그게 그 시간에 실행되고 있던 거예요.
00:35:30제가 했을 방법이 그거예요.
00:35:31맞습니다.
00:35:31하지만 모르겠어요.
00:35:32그래서 왜 이렇게 했는지 전혀 모르겠어요.
00:35:34그들이 한 대로 했네요.
00:35:34저는, 아시겠지만, 완벽하게 말이 될 수도 있어요.
00:35:36다시 말하지만, 저는 그들의 시스템에 대해 아무것도 몰라요.
00:35:39이 모든 것들이, 완벽하게 말이 돼요..
00:35:41그래서 제가 정말로, 제가 말하는 건 이해가 안 간다는 거예요. 나쁜 아이디어가 아닐 수도 있어요, 맞죠?
00:35:45시스템의 나머지 부분을 이해한다면 좋은 아이디어일 수도 있어요.
00:35:49어쨌든,
00:35:50그래서 그들이 말하는 건,
00:35:51이게 우리가 얻는 전부인데,
00:35:53이 작업은,
00:35:54롤백을 이전 플랜을 가리키도록 설정하는 거,
00:35:56즉 이 경우에는 실제로는 어떤 경우에는 더 새로운 거였을 수도 있어요,
00:36:01맞죠?
00:36:01그래서 실제로는 이전에 가리키던 플랜이 아니에요.
00:36:04더 오래된 것일 수도 있고, 더 새로운 것일 수도 있죠.
00:36:08그 활동을 하는 거예요..
00:36:11만약 그 플랜이 더 이상 존재하지 않는다면,
00:36:14즉 이렇게 삭제된 것처럼 말이죠,
00:36:16그러면 enactor가 영구적으로 멈춥니다.
00:36:19그래서 매번, 일단 dynamodb.usc가 그것인 상태가 되면, 맞죠.
00:36:25우리가 여기서 말한 일련의 단계들을 전부 수행합니다?
00:36:28이 플랜이 삭제되는 거죠..
00:36:31그래서 이제 이건 유효하지 않은, 해석 불가능한 이름을 가리키고 있게 됩니다.
00:36:34plan dash 110, 실제로는 어떤 16진수 코드인데, 우리는 그걸 더 이상 해석할 수 없습니다.
00:36:39뭐였든 간에, 더 이상 해석할 수 없어요..
00:36:41그 상태가 참이 되면,
00:36:43다음에 enactor가 와서 새로운 플랜을 가리키게 하려고 시도할 때,
00:36:48그게 어떤 새 플랜이든 간에,
00:36:50실제로 여기까지 와서 롤백을 설정하려고 할 때 영구적으로 크래시가 납니다.
00:36:56따라서 세 개의 enactor 모두 이제 멈추게 됩니다.
00:37:00왜냐하면 결국 세 개 모두 새로운 플랜을 실행하려고 시도할 것이고,
00:37:05먼저 롤백을 이전 플랜이 뭐였든 그걸 가리키도록 설정하려고 하다가,
00:37:10거기 플랜이 없다는 걸 발견하게 됩니다.
00:37:14그리고 그게 명백히 그냥 하드 크래시인 거죠.
00:37:17오, 그거 미친 거 아니에요.
00:37:19저는 세 개의 enactor가 중복성을 제공하기 위한 거라고 생각했는데.
00:37:25다시 말하지만, 이게 제가 온라인에서 답글 다는 사람들한테 짜증나는 이유입니다.
00:37:31그들은 레이스 컨디션이었다고 하는데, 레이스 컨디션이 아니었어요.
00:37:36이것에 레이스 컨디션이 필요한 게 아닙니다.
00:37:39레이스 컨디션은 단지 이 이름이 해석 불가능하게 된 이유일 뿐이에요.
00:37:45하지만 이걸 잘못 작성한 코드가 없었다면, 그냥 작동했을 겁니다..
00:37:52전혀 몰랐을 겁니다.
00:37:53DynamoDB가 1분 정도 순간적으로 다운되는 정도였을 텐데,
00:37:57가끔 DynamoDB가 1분 정도 다운되는 일이 있을 거라고 추측합니다.
00:38:02그건 글로벌 뉴스가 아니죠..
00:38:04글로벌 뉴스가 된 건 영구적으로 다운시킨 것이고, 그게 여기서 일어난 일입니다.
00:38:09그리고 실제 사람이 와서 이걸 파악하고,
00:38:11리셋하고,
00:38:11이 enactor들을 다시 작동시킬 때까지는 그냥 사라진 겁니다.
00:38:15영구적으로 다운된 거죠.
00:38:16그러니까 잠재적으로 몇 시간이요.
00:38:18그리고 이 경우에는 연쇄 장애를 일으킬 만큼 충분히 길었던 것 같습니다.
00:38:22그런 일은 절대 없었을 겁니다.
00:38:24그냥 순간적인 다운이었을 거예요.
00:38:25일부 사람들이 순간적으로 해석 불가능한 이름이나 레코드 없음을 받았다면, 그냥 다시 시도했을 겁니다.
00:38:31보통 DNS의 경우, 그건 마치 휴대폰이 터널을 지나간 것 같은 거예요.
00:38:35그게 전부였을 겁니다..
00:38:37그래서 저는 여기 코드가 어떻게 생겼는지 알고 싶어요.
00:38:41이게 유효한 이름이 아니었다면,
00:38:43시작할 때조차 그렇지 않았을 텐데,
00:38:45즉 이 시스템을 시작하고 운영자가 미리 설정하지 않았다면,
00:38:49아무것도 가리키지 않았을 겁니다.
00:38:52그게 시작할 것이라고 생각할 기본 케이스입니다.
00:38:55그러니까 이걸 하려고 한다면, 그 케이스를 처리할 거라고 생각할 텐데요.
00:39:00왜냐하면 롤백 주소는 그냥 아무것도 가리키지 않을 수 있으니까요.
00:39:05그냥 이게 뭐든 가져가세요.
00:39:06아무것도 아니면, 롤백 주소를 아무것도 아닌 것으로 설정하세요..
00:39:12끝.
00:39:12그러니까 그들이 이 코드를 작성한 방식에 뭔가 정말 이상한 게 있습니다.
00:39:17그리고 그게 RCA에 있었어야 할 내용입니다.
00:39:20제게는 그게 전체 버그예요.
00:39:21이건 그냥 우리가 이걸 아무것도 가리키지 않게 만든 과정의 배경일 뿐입니다.
00:39:26누군가가 실수로 이 레코드를 삭제했다면 같은 버그가 발생했을 겁니다.
00:39:30어떤 운영자가 그냥, 앗, 젠장, 아무것도 아닌 것으로 설정했다고 하면요..
00:39:35발표에 따르면 이 똑같은 버그가 발생했을 겁니다.
00:39:38그러니까 근본 원인은 레이스 컨디션이 아닙니다.
00:39:41레이스 컨디션은 부차적인 겁니다.
00:39:43이해되세요?
00:39:44간단한 질문인데요.
00:39:45저는 진지하게 이걸 생각해보고 있어서요.
00:39:47그러니까 그건 롤백을 설정하는 것이 아마도 메모리가 잔뜩 있는 어떤 struct 같은 게 전달되었다고 가정하고,
00:39:54어떤 종류의 접근을 시도하는 거겠죠.
00:39:56폭발하는 거죠.
00:39:57아니면 이게 같은 스타일의 버그라고 생각하세요?
00:40:00Cloudflare를 다운시킨 그 한 줄처럼, 그냥 거기 있다고 가정하고 unwrap하는 거요..
00:40:07Rust로 되어 있습니다. 메모리 안전한 Rust죠. Unwrap하고, 폭발하는 겁니다.
00:40:13정말 모르겠어요.
00:40:14제 머릿속으로는,
00:40:15사람들이 자주 하는 행동 중에 제가 항상 '왜 저렇게 하지?'라고 생각하는 게 뭘까 생각했는데,
00:40:22그건 그냥 그들이 프로그래밍을 배운 방식이기 때문이죠?
00:40:26그래서 에러 상황에 예외를 던지는 걸 좋아하는 언어 중 하나로 작성했다면,
00:40:31이게 딱 그런 사례가 될 거라고 생각했어요.
00:40:34예를 들어, 이 항목이 가리키는 DNS 레코드를 가져오려고 했는데요..
00:40:40정상적인 프로그래밍 환경이라면, 아무도 거기서 예외를 던지지 않아요.
00:40:45아무것도 받지 못하면 그냥 아무것도 반환하지 않죠.
00:40:48그러면 사람이 ddb.robot.js를 설정할 때 그냥 아무것도 없는 걸로 설정하는데,
00:40:54그게 올바른 동작이에요.
00:40:55말 그대로 '아무것도 없음'이라는 값이 이 플로우를 통해 올바르게 흘러가는 거죠.
00:41:00그런데 핵심 기반 서비스이니까,
00:41:02장애 허용적으로 작성하려고 한다고 가정하면,
00:41:05예외를 던지는 것 같은 건 절대 하지 않을 거예요.
00:41:08그래서 제 머릿속으론,
00:41:10여기서 이 레코드를 요청하면 어떤 라이브러리 호출 같은 걸 쓰는데 레코드가 없을 때 예외를 던지는 거죠.
00:41:16그래서 예외가 던져지고 액터가 종료된 거예요.
00:41:19그게 제 추측이에요.
00:41:21완전히 틀릴 수도 있어요.
00:41:22그냥 막 추측한 거니까요.
00:41:24하지만 그래서 RCA를 보고 싶은 거예요.
00:41:26뭐였을까요.
00:41:27Trash가 얘기한 것일 수도 있어요.
00:41:30Prime이 얘기한 것일 수도 있고요?
00:41:32제가 방금 말한 것일 수도 있죠.
00:41:34뭐든 될 수 있어요.
00:41:35그리고 알고 싶어요.
00:41:37왜냐하면 거기에 진짜 교훈이 있을 테니까요.
00:41:39이 경쟁 상태를 피하는 건 완전히 중요하지 않아요.
00:41:43이 경쟁 상태는 거기 있었을 수 있고,
00:41:45일 년에 한 번 5초 정도 이상한 장애를 피하려고 결국 고치는 게 중요했지만,
00:41:50사실 우리가 가장 배우고 싶은 건 아니에요.
00:41:53우리가 가장 배우고 싶은 건 '이런 걸 작성하지 마라'인데, 이게 뭔지조차 모르잖아요.
00:41:58그럼 어떻게 작성하지 않죠.
00:42:00그래서 이게 나쁜 RCA였다고 생각하는 거예요.
00:42:03이해되나요?
00:42:04네.
00:42:04네?
00:42:05좋아요.
00:42:05AWS 대부분이 뭘로 작성됐죠, Adam?.
00:42:11Java였어요.
00:42:12방금 채팅에서 누가 Scala라고 했어요.
00:42:16AWS에서 7년 일했다는데 대부분 Scala로 작성됐다고 하더라고요.
00:42:21음, 그건 기술적으로 Java에 단계만 더한 거죠.
00:42:25그리고 그 말이 그들을 끝없이 화나게 할 거예요.
00:42:29그래서 저는 여기까지예요..
00:42:34이건 제가 설명을 본 것 같지 않다고 느낀 경우였어요.
00:42:37그리고 사실 듣는 게 중요하다고 생각해요.
00:42:39왜냐하면 이 여름 이 문제의 밑바닥엔 나쁜 프로그래밍 관행이 있었거든요.
00:42:43그게 뭔지 알고 싶어요.
00:42:44특히 저 같은 사람들한테 도움이 되니까요.
00:42:47지금은 아키텍처 교육을 많이 하진 않지만, 언젠가는 하고 싶거든요.
00:42:50나쁜 아키텍처가 정말 많다고 생각하니까요.
00:42:53그래서 이런 것들에 주의를 기울이려고 노력해요.
00:42:55사람들이 어떤 종류의 아키텍처 실수를 하고 있을까?
00:42:58그리고 이것도 그 중 하나였을 거라고 확신해요.
00:43:01맞죠.
00:43:01그래서 알고 싶어요.
00:43:02알고 싶다고요..
00:43:04네.
00:43:05제 생각에 최소한 기대하는 건,
00:43:07왜 전체가 터졌는지 보여주는 간단하고 재현 가능한 예시 하나 정도는 있어야 한다는 거예요.
00:43:13작은 코드 스니펫 같은 거요.
00:43:15그리고 이건 아까 당신이 언급한 건데, 우리가 이런 종류의 문제에 접근하는 방식이잖아요.
00:43:20누군가의 코드를 리뷰하다가 이상해 보이는 걸 발견하면,
00:43:24저는 항상 제 샌드박스를 만들어서 제 이론을 검증하려고 최선을 다해요.
00:43:28그리고 실제로 코드를 보여주면서 이게 왜 아마 잘못됐는지, 간단하고 재현 가능한 단계를 제시하는 거죠.
00:43:35그런 걸 기대하는 거예요.
00:43:36그리고 그렇게 해야 제가 진정으로 이해할 수 있어요.
00:43:40많은 사람들이, 당신 말처럼, 뭔가 이상해 보이는 걸 발견하지만 왜 이상한지 모르잖아요.
00:43:46하지만 거기서 멈출 수 없어요.
00:43:48실제로 구축해보고 이해해야 하는 거죠.
00:43:50그게 제가 기대하는 거예요.
00:43:52그리고 아까 말했듯이,
00:43:53크라우드스트라이크랑 구글 장애 사례가 더 나았던 게,
00:43:56그냥 여기서 널 포인터 역참조였다거나,
00:43:5920개만 있을 거라고 생각했는데 설정 파일에 21개를 넣어서 배열 범위를 벗어났다고 말해줬잖아요.
00:44:05그러면 어떤 종류의 코드가 그런 문제를 일으키는지 정확히 알 수 있는 거죠.
00:44:10게다가,
00:44:11더 나아가서,
00:44:11아까 했던 얘기와 관련해서,
00:44:13제가 아는 한,
00:44:14Rust로 프로그래밍하는 모든 사람들은 가끔 이런 걸 봤을 때 "Rust로 작성했으면 이런 일 안 일어났을 텐데"라고 말하려고만 하는 것 같아요.
00:44:23근데 그런 얘기조차 할 수 있는 정보를 안 준 거예요..
00:44:29솔직히 그 사람들은 어쨌든 그런 말 했을 가능성이 높지만, 정보는 안 줬죠.
00:44:34그래서 RCA에서 지켜야 할 규칙 중 하나는,
00:44:37Rust 신봉자들이 원한다면 Rust로 작성했으면 방지할 수 있었을 거라고 올바르게 말할 수 있을 만큼 충분한 정보를 제공해야 한다는 거예요..
00:44:46그런데 이번 건, 그런 정보가 없어요. Rust로 방지할 수 있었을지 모르는 거죠.
00:44:51전혀 모르죠.
00:44:52아마 방지 못했을 수도 있지만 모르는 거예요.
00:44:55뭐, 케이시, 꽤 확률이 높긴 해요.
00:44:58왜냐하면 아마 출시조차 안 했을 테니까요.
00:45:01그러니까 방지한 거죠..
00:45:03맞아요. 액터가 하나도 없었을 거예요. 세트 액터를 설계하고 있었을 테니까요.
00:45:09CloudFlare도 이런 거 정말 잘해요.
00:45:12들어가서 많은 코드 라인을 보여주고 이게 정확히 무슨 일이 일어난 건지 설명하죠.
00:45:18문제가 위쪽에 있더라도, 이전의 모든 조건들 때문에 이 라인에서 폭발한 거라고요.
00:45:23제가 unwrap으로 Rust를 놀린 건데, 사실 진짜 문제는 아니었지만요.
00:45:28어쨌든 이런 모든 일들이 일어나는 거잖아요.
00:45:31그래서 CloudFlare는 정말 잘해요.
00:45:34AWS가 이번 건에서 이렇게 형편없이 한 게 놀라워요.
00:45:38그리고 또 다른 건, 이제 저를 불필요하게 의심스럽게 만드는 거죠, 그렇죠??
00:45:44이걸 읽으면서 생각했어요.
00:45:45뭔가 숨기는 거 아니야?
00:45:46버그가 뭔지 정말로 파악하지 못한 거 아니야?
00:45:48경쟁 상태(race condition)에 대해 온갖 얘기를 늘어놨지만,
00:45:52당신이 직접 설명한 내용만 봐도 경쟁 상태는 사실 중요하지 않았다는 걸 알 수 있어요.
00:45:56그건 그냥 레코드가 아무것도 아닌 값으로 설정되게 만든 계기일 뿐이지, 그게 뭐 그리 중요해요?
00:46:01그런 건 RCA에 '왜 이 버그가 다른 때가 아니라 지금 발생했는지'를 설명하는 부분으로 넣기에는 좋을지 몰라도,
00:46:06그게 버그 자체는 아니잖아요.
00:46:08그래서 이상하게 느껴져요.
00:46:09RCA에서 정작 버그에 대해서는 얘기하지 않으면 의심스러워지는 거예요.
00:46:12그럴 필요도 없는데 말이죠.
00:46:13실제로 찾아냈다면 그냥 말해주면 되고, 그러면 찾았다는 걸 알 수 있으니까요.
00:46:17그래서 이것도 일종의 신뢰 향상 효과가 있다고 봐요.
00:46:20외부에서 지켜보는 사람들, 이 DynamoDB라는 게 믿을 만한지 알고 싶어 하는 사람들에게 말이죠.
00:46:25버그를 실제로 찾아낸 것처럼 보이면 조금 더 신뢰가 생기지만,
00:46:28버그가 뭔지 전혀 모르는 것처럼 보이거나 버그를 이해하지 못한 것 같으면 오히려 더 걱정되는 거죠.
00:46:32그래서 이것도 RCA에서 이렇게 써야 하는 또 다른 이유라고 생각해요..
00:46:37고객들에게 신뢰를 주는 거죠. 어쩌면 그래서 Adam을 AWS 히어로에서 해고한 걸지도 몰라요.
00:46:43어쩌면 다 연결되어 있을지도. 그럴 수도 있지. 그가 이런 더러운 비밀을 폭로하는 걸 원하지 않았던 거야.
00:46:48그래.
00:46:48너무 많이 알아버렸어.
00:46:50너무 많이 알았던 거야.
00:46:51기타 샵(guitar shop) 얘기를 3분 정도로 간단히 요약해줄 수 있어?
00:46:56그게 뭘 드러냈는지 말이야.
00:46:57기억을 더듬어보려고 하는데,
00:46:59단일 장애점(single point of failure)인 어떤 사람이 관련되어 있었고 이번 장애 때도 자리에 없었다는 것 같은데.
00:47:06그래서 두 가지를 어떻게 조합해야 할지 모르겠어.
00:47:09물론 우리는 전혀 알 수 없죠.
00:47:11둘 중 어느 쪽이 진실을 말하고 있는지도 모르는 거예요.
00:47:14RCA가 너무 엉망이어서 맞는 내용인지 아닌지도 모르겠지만,
00:47:18어쨌든 비밀번호는 wishbone 12였던 것 같아요..
00:47:22바로 그거야. 항상 날 죽이려고 하네. 내 기억으로는 그래.
00:47:26그래,
00:47:27그 얘기는 설정을 복사하도록 설계된 뭔가가 있었는데,
00:47:31그게 통제 불능 상태가 되어서 멈출 수가 없었다는 거였어요.
00:47:35그냥 완전히 잘못된 방식으로 설정을 복사하고 있었고, 고치거나 수리해야 하는 상황이었던 거죠.
00:47:42우리가 더 이상의 정보를 갖고 있지 않은 이유는 그게 우연히 엿듣게 된 대화였기 때문이에요.
00:47:50그럼 이게 이번 내용과 일치하나요?
00:47:52음, 조금은 그래요.
00:47:54그 enactor들이 설정 복사를 실행할 만한 것처럼 들리긴 하니까요.
00:47:59하지만 다른 한편으로는, 이건 머신을 위한 설정이 아니에요.
00:48:04DNS 엔트리는 DNS 엔트리일 뿐이죠.
00:48:07진짜 설정은 아니에요.
00:48:08그래서 두 이야기가 그렇게 잘 들어맞지는 않는다고 봐요..
00:48:14그래서 이 RCA가 좀 더 믿을 만했으면 좋겠다고 바랐던 또 다른 이유가 있어요.
00:48:19그 이야기가 거짓이라는 걸 확실히 알고 싶었거든요.
00:48:21하지만 이 RCA가 너무 형편없어서 여전히 잘 모르겠어요.
00:48:25만약에, 만약에 그 사람이 설정을 복사하려고 만든 도구가 말 그대로 그 enactor라면 어떨까요?
00:48:30그냥 그걸 프로덕션화한 거고, 그 사람이...
00:48:33그리고 7년 동안 바꾸지 않은 거예요.
00:48:35그게 제가 점들을 연결해본 방식이에요.
00:48:37그 사람이 이렇게 말하는 거죠.
00:48:39'여러분,
00:48:40저는 그걸 제 로컬 환경에서 테스트하려고 만든 건데,
00:48:43여러분은 그냥 enactor 세 개를 만들어서 프로덕션에 나란히 배치하기로 결정했네요.
00:48:48도대체 어떻게 이런 일이...' 모르겠어요, 어떻게 이렇게 된 거죠?.
00:48:53대안적인 질문이 있어요.
00:48:54그래요.
00:48:54아니면 롤백이 문제였을까요?
00:48:56왜냐하면 그게 "자, 여기 이전 버전이 있어요"라고 복사하는 작업을 했거든요.
00:49:00맞죠.
00:49:01그래서 이전 버전을 복사하는데,
00:49:02그러다가 null 문제가 발생하고,
00:49:04스크립트가 전혀 예상하지 못했거나 제어를 벗어나서 계속해서 반복적으로 덮어쓰기 시작하는 거죠.
00:49:10그래서 아무것도 할 수 없게 되는 거예요.
00:49:12모르겠어요.
00:49:12제가 아는 건,
00:49:13제가 파악한 바로는 그들의 설명만을 바탕으로 했을 때,
00:49:16그들이 제공한 정보만으로는 여전히 경쟁 조건이 관련이 있다고 생각하지 않아요.
00:49:21왜냐하면 다시 말하지만,
00:49:22Route 53 엔드포인트에 대한 우연한 업데이트만으로도 세 개의 액터 모두 즉시 다운되었을 거거든요.
00:49:28그들의 설명에 따르면,
00:49:29액터들을 멈추는 데 필요한 건 엔드포인트가 해석 불가능한 이름을 가리키기만 하면 되는 거예요.
00:49:34그게 전부라고요.
00:49:35그래서 만약 그게 정말이라면, 문자 그대로 운영자의 오타만으로도 이 모든 게 다운될 수 있었던 거죠.
00:49:40경쟁 조건 같은 건 필요 없었어요.
00:49:42맞죠.
00:49:43그래서 다시 말하지만,
00:49:44RCA는 실제 버그가 무엇이었는지에 대해 저를 납득시키는 데 제대로 된 역할을 하지 못했어요.
00:49:49왜냐하면 RCA 전체에서 버그라고 말했던 이 경쟁 조건과 관련 없이도 똑같은 상황을 유발할 수 있는 방법들이 너무 많이 떠오르거든요.
00:49:57하지만 저는 그게 버그라고 생각하지 않아요.
00:49:59아무튼 Casey, 이 놀라운 발표를 해주셔서 감사합니다.
00:50:02저는 사실 진심으로 그린우드...
00:50:04질투에 찬 분노를 느끼고 있어요.
00:50:06당신이 사용한 그 필기 도구가 뭔지 궁금해서요.
00:50:08당신이 사용하는 걸 어떻게 설정하는지 알아내야겠어요.
00:50:11정말 환상적이네요..
00:50:15시청해주신 모든 분들께 감사드립니다.
00:50:16저는, 음, 라이브로 보신 분들은 사전 잡담과 아마도 사후 잡담도 조금 즐기셨기를 바랍니다.
00:50:21확장 버전과 메인 스토리에 포함되지 않은 재미있는 대화들을 듣고 싶으시다면,
00:50:25Spotify로 가서 전체 팟캐스트를 들어보세요.
00:50:27거기서는 우리가 그냥 떠들어대는데, 뭐 트래시가 먹는 것과 간식 같은 것들에 대해서요.
00:50:31이름은 'More Yapping,
00:50:33More Yapping Again'이고,
00:50:35Casey,
00:50:35TJ,
00:50:36그리고 Trash도 나와요..
00:50:42내 화면의 에러들, 터미널 커피, 그리고 꿈을 살아가는 중.