
내가 3Blue1Brown 애니메이션을 만드는 방법 | Ben Sparks와 함께하는 Manim 데모
요약
3Blue1Brown 채널의 제작자가 수학 애니메이션 라이브러리인 Manim의 탄생 배경과 사용법을 소개합니다. 개인 버전과 커뮤니티 버전의 차이점을 설명하며, 로렌츠 끌개(Lorenz Attractor)를 활용한 실제 애니메이션 제작 워크플로우를 시연합니다.
핵심 포인트
- Manim은 수학적 함수를 시각화하기 위해 직접 작성한 Python 라이브러리임
- 오픈 소스 커뮤니티에 의해 관리되는 Manim Community 버전 사용 권장
- 프로그래밍 방식을 통한 맞춤형 수학 애니메이션 제작 워크플로우 공개
- 로렌츠 끌개 예제를 통한 실제 라이브러리 활용법 시연
동영상: 내가 3Blue1Brown 애니메이션을 만드는 방법 | Ben Sparks와 함께하는 Manim 데모
채널: 3Blue1Brown
재생 시간: 53분 40초
출처: 자막 (수동, 영어)
내용:
3Blue1Brown에 대해 제가 가장 자주 받는 질문은, 영상을 애니메이션화하기 위해 무엇을 사용하느냐는 것입니다. 짧은 답변을 드리자면, 저는 Manim이라는 이름의 커스텀 Python 라이브러리를 직접 작성했습니다. 따라서 모든 것이 프로그래밍 방식이며 매우 맞춤화되어 있습니다. 이 영상을 통해 제가 하고 싶었던 것은, Manim이 무엇인지 모르는 분들에게는 그것이 무엇인지 알려드리고, 이미 알고 계신 분들에게는 제가 그것을 어떻게 사용하는지, 그리고 워크플로 (workflow)가 무엇인지 보여드리기 위해 비하인드 스토리를 제공하는 것입니다. 이번 영상은 제가 몇 달 전 영국에 있을 때 Ben Sparks와 함께 앉아 대화하며 진행했습니다. 여러분 중 많은 분이 그의 수많은 멋진 Numberphile 영상들을 통해 그를 알아볼 수 있을 것입니다.
그는 Manim이 어떻게 작동하는지 알고 싶어 했고, 저 또한 다른 많은 사람이 같은 질문을 가지고 있다는 것을 알고 있었기에 대화를 녹화했습니다. 다소 거친 녹화물이지만 어떻게든 해보겠습니다. 그리고 간단한 Hello World 예제 이후, 우리는 카오스 (chaos) 이론의 기초에서 매우 중요한, 또한 시각적으로 즐거운 대상인 유명한 로렌츠 끌개 (Lorenz Attractor)를 애니메이션화합니다. 본격적으로 시작하기 전에 한 가지 언급해야 할 점은 실제로 Manim에는 두 가지 버전이 있다는 것입니다. 첫 번째 버전은 채널의 역사와 매우 밀접하게 얽혀 있는 역사를 가지고 있습니다. 제가 이 프로젝트를 시작한 방식은, 기본적으로 학부 과정을 마치던 시기에 수학적 함수를 변환 (transformations)으로서 더 잘 설명할 수 있게 해주는 코딩 프로젝트를 원했던 것이었습니다. 이를 위해 매우 투박한 Python 코드를 만들었고, 그것을 사용하여 이 채널의 첫 번째 영상을 제작했습니다. 영상을 더 많이 만들면서 도구는 개선되었고, 도구가 개선됨에 따라 저는 더 많은 영상을 만들게 되었습니다. 그리고 그 과정은 그때 이후로 계속 이어져 오고 있습니다.
제가 가장 최근에 만든 홀로그램에 관한 영상은, 제 스스로 생각하기에도 시각 효과가 꽤 자랑스러웠습니다. 2~3년 전만 해도 그런 영상을 만드는 것은 훨씬 더 극적으로 어려웠겠지만, 지난 몇 달 동안은 지난 수년간 이루어진 많은 워크플로우 (workflow) 개선 덕분에 실제로 제작하는 과정이 즐거웠습니다. 저는 항상 영상 제작을 위해 만든 모든 코드를 GitHub에 공개해 왔으며, 기반이 되는 도구인 Manim 자체도 오픈 소스 (open source)로 만들었습니다. 하지만 제 성격상 오픈 소스 프로젝트를 관리할 만한 기질이 부족하고, 영상을 제작하는 동안 그럴 만한 여력도 없었습니다. 그래서 이슈 (issue)나 풀 리퀘스트 (pull request) 같은 것들에 세심하게 신경을 쓰지 못했습니다. 하지만 이 도구가 다른 사람들에게 더 견고한 도구가 되기를 원하는 커뮤니티 사람들이 저장소 (repo)를 포크 (fork)하여, 이슈와 풀 리퀘스트에 대응하고 더 나은 테스트와 더 나은 문서화 (documentation)를 갖춘 버전을 만들었습니다. 그것이 바로 Manim 커뮤니티 버전 (Manim community version)입니다.
따라서 일반적으로는 그 버전으로 시작하는 것이 권장되지만, 그동안 저는 제 개인 버전에 많은 변경 사항이나 개발을 진행해 왔으며, 지난 몇 년 동안 더 인터랙티브 (interactive)하고 더 성능이 좋게 (performant) 만드는 등의 작업을 해왔습니다. 제가 이 이야기를 꺼내는 이유는, Ben과 함께 시연할 것이 저의 개인 버전이기 때문입니다. 하지만 이러한 차이가 존재한다는 점을 인지해야 하며, 만약 더 잘 문서화되고 테스트된 버전을 원하신다면 커뮤니티 버전을 사용하는 것이 권장된다는 점을 알아두어야 합니다. 그럼 지체 없이, 'Hello World' 예제로 들어가 보겠습니다.
모든 것은 Python으로 이루어져 있습니다. 자, 왼쪽에 있는 것은 Python, 본질적으로는 그냥 텍스트 파일입니다... 네, 이건 Sublime Text인데, 저는 Sublime을 사용합니다. 텍스트 에디터(text editor)죠. 여기서 Python 코드를 입력할 것입니다. 화면에 무언가가 나타나는 것이 어떤 모습인지 기본적인 감을 잡기 위해서 말이죠. 제가 무언가를 준비할 테니, 그 후에 어떤 일이 일어나고 있는지 이야기해 봅시다. 여기 제가 scene을 생성했습니다. 제가 함께 편집하는 모든 scene은 Python의 클래스(class) 형태를 취합니다. 그리고 construct라고 불리는 특정 메서드(method) 내부가 바로 무언가를 렌더링(render)하는 모든 코드가 위치하는 곳입니다.
원(circle)과 같은 객체(objects)들이 추가됩니다. 아시다시피, 여기에 사각형(square)도 추가할 수 있습니다. 우리도 그 사각형을 추가해 보겠습니다. 만약 이 모든 것을 실행한다면, 사각형이 나타날 것입니다. 방금 그걸 어떻게 실행하신 건가요? 혹시...
오, 네, 알겠습니다. 그러니까 이건... 마치 마법 지팡이를 휘둘렀더니 바로 일어난 것 같네요, 그렇죠? 하지만 단축키가 있었던 것 같군요. 좋습니다. 원칙적으로, 여기 이 작은 터미널(terminal)은 Python 터미널이므로, 해당 scene과 관련된 명령어를 호출할 수 있습니다. 예를 들어 square.shift(RIGHT)라고 말하면, 그 사각형이 오른쪽으로 이동할 것입니다.
그리고 제가 그것을 다시 호출하면, 더 많은 일이 일어날 것입니다. 또한 그냥 일반적인 Python처럼 1 + 2가 무엇인지 물어볼 수도 있습니다. 좋습니다, 기본적으로는 그냥 Python 입력창이군요. 네, 하지만 이것이 이 scene과 대화하고 있습니다. 따라서 제가 scene을 만드는 동안, scene 자체와 대화할 수 있는 Python 터미널이 있다면 매우 유용합니다. 그리고 별개로, 워크플로우(workflow)로서 유용할 수 있는 점은, '자, 내가 할 일들이 이만큼 있어'라고 말하는 것입니다. 예를 들어 사각형을 가져와서 상단 가장자리로 옮기고 싶을 수도 있죠. 그래서 여러분이 흔히 할 수 있는 일은, 그것을 복사해서, 이쪽으로 가져와서, 붙여넣고, 엔터를 누르는 것입니다.
그러면 그 줄을 즉시 테스트하게 됩니다. 그렇게 해서 그 줄을 테스트하죠. 하지만 저는 매번 그렇게 하고 싶지는 않습니다. 매번 실행하고 복사해서 붙여넣고 싶지는 않거든요. 그래서 대신에 단축키를 작성해 두었는데, 이것은 Sublime의 특정 기능들과 연결되어 있습니다. 제 경우에는 아마도 command R이 제가 가진 키보드 단축키일 것입니다. 그것은 텍스트를 복사하고, 복사된 텍스트를 그곳에서 실행합니다. 즉, 이 코드를 실행하고 시각적 결과물을 출력하여 즉각적으로 확인할 수 있는 단축키를 갖게 되는 것입니다. 내부적으로 조금 더 복잡한 과정이 일어나고 있기 때문에, 여기서 짧은 코멘트를 덧붙이고 싶습니다.
모든 일과 마찬가지로, 이것은 예시를 통해 설명하는 것이 가장 좋습니다. 홀로그램에 관한 가장 최근 영상의 장면(scene)을 불러와 보겠습니다. 이런 것들은 꽤 길어질 수 있습니다. 여기서 최종 결과물은 회절 격자(diffraction gratings)를 설명하는 4분 30초짜리 MP4 파일이었고, 특히 이것은 이중 슬릿(double slit)에 관한 것이었습니다. 이런 긴 장면들을 갖는 것은 매우 좋은데, 왜냐하면 많은 문맥(context)을 공유하며 코딩을 하는 동안 그 문맥을 참조할 수 있기 때문입니다. 하지만 그런 것을 위한 코드는 결국 그냥 아주, 아주, 아주 거대한 Python 코드 더미가 됩니다.
정말 엄청나게 많은 코드 말이죠. 예전에는 이 모든 것을 작은 서브루틴(subroutines)으로 나누곤 했지만, 역사적으로는 모든 지역 변수(local variables)가 공유되는 한 곳에 모아두는 것이 더 편하다는 것이 증명되었습니다. 제가 강조하고 싶은 점은, 만약 제가 장면을 작업하고 있고 그 중간 어디쯤에 있다면 — 즉, 아주 많은 코드가 이미 작성되었지만 현재 우리는 그 중간 지점에 있다면 — 제가 여기서처럼 단 하나의 작은 섹션에 대해서만 반복 작업(iterating)을 하고 있을 때, 이 섹션의 코드만 실행해서 어떤 결과가 나오는지 확인하고 싶을 수 있다는 것입니다.
상상하실 수 있듯이, 여러분은 그것을 미세하게 조정(tweak)하거나 조금씩 바꾸고 싶을 수도 있습니다. 그래서 이 경우에 어떤 일이 일어나고 있는지 살펴봅시다. 그래프들이 그려지고 있습니다. 빨간색과 파란색 파동이 조금씩 사라지는(fading out) 듯한 모습이 보이네요. 그래서 제가 이렇게 말할 수도 있을 것 같습니다. '만약 이게 그렇게 많이 사라지지 않기를 원한다면 어떨까? 그 값을 0.8로만 하고 싶다면? 여기 실행 시간(runtime)을 조금 다르게 하고 싶다면?' 저는 동일한 섹션을 다시 실행하고 싶지만, 이것이 제대로 작동하려면 코드를 붙여넣을 때 단순히 코드만 그대로 붙여넣어서는 안 됩니다.
그것은 장면(scene)이 시작될 때 가졌던 상태로 되돌아가야 합니다. 즉, 이것은 실제로 '체크포인트 붙여넣기(checkpoint paste)'라고 불리는 작은 기능을 실행하는 것인데, 기본적으로 복사된 내용이 특정 주석(comment)으로 시작하면, 이전에 해당 주석을 본 적이 있는지 확인하고 그와 연관된 장면의 상태를 캐싱(cached)해 두었다가 실행할 수 있게 해주는 방식입니다. 기본적으로 이것은 Jupyter notebook과 같은 노트북(notebook)처럼 조금 더 동작하게 만듭니다. 어떤 시청자들은 '왜 그냥 전부 Jupyter notebook에서 하지 않는가?'라고 궁금해할 수도 있겠지만, 저는 장면을 단일 텍스트 파일에 두고 스크립트 등을 통해 상호작용할 수 있는 방식을 정말 좋아합니다.
하지만 이것은 순수 텍스트 파일과 노트북 자체 사이의 일종의 하이브리드(hybridization) 형태라고 할 수 있습니다. 또한 그곳에 말 그대로 'hello world'라고 적힌 텍스트를 넣을 수도 있습니다. 이것은 hello world를 위한 좋은 계획이네요. 네, 그것을 맨 위로 올립시다. 그리고 이것 또한, 아시다시피 이 줄이 없다면 여기에 나타나지 않을 것입니다. 즉, 추가함으로써 나타나게 만드는 것이죠. 하지만 제가 생각하기에는, 객체(object)를 만들면 그것을 중앙에 배치하고, 그 후에 두 가장자리(two edges)를 설정하거나 다른 움직임을 주지 않는 한 그대로 유지되는 것 같습니다.
대부분의 객체(objects)는 기본적으로 중앙에 위치합니다. 객체를 단순히 추가하는 대신, 어떤 종류의 애니메이션을 만들 때마다 할 수 있는 다른 방법이 있는데, 바로 play라고 불리는 메서드(method)를 사용하는 것입니다. 그리고 객체를 그냥 던져 넣는 대신, 그 객체에 어떤 동작을 수행하고 싶다고 말할 수 있습니다. 예를 들어, 이번 경우에는 마치 글씨가 써지는 것처럼 보이게 하고 싶을 수도 있겠죠. 여기에는 내장된 함수(function)가 있습니다. 네, 좋네요. 그리고 몇 가지 매개변수(parameters)를 가질 수도 있습니다. 예를 들어, runtime=3과 같이 설정하여 그 동작이 조금 더 길게 일어나도록 할 수도 있습니다.
그러면 갑자기 Manim 영상을 본 적이 있는 사람이라면 누구나 그 효과를 알아챌 것입니다. 그들은 준비가 된 상태죠. 그건 정말 유용합니다. 제가 그 효과를 만들었는데, 가장자리가 나타나며 페이드 인(fade in)되는 그 특유의 효과를 사용하는 것은 다른 데가 없거든요. 꽤 예쁩니다. 그것이 Manim의 시그니처 룩(signature look)입니다. Manim의 또 다른 철학은 무엇이든 무엇으로든 변형(transform)될 수 있다는 것이었습니다. 제 말은, 예를 들어 우리가 이 텍스트를 가지고 있다고 가정해 봅시다. 제가
네, 정확합니다. 그래서 많은 것들이 변형 (transform)으로부터 파생됩니다. 보통은 'H'가 원으로 변하는 것에 특별한 교육적 (pedagogical) 이유가 있는 건 아니에요. 그냥 제가 즐거워서 하는 거죠. 보기에도 좋고요. 그리고, 음, 속도를 조금 더 느리게 만들 수도 있겠죠. 제 말은, 단순히 변형만 된 게 아니라, 마치 이징 (eased) 처리가 된 것처럼 보였다는 점이 궁금했어요. 온갖 종류의 멋진 스무딩 함수 (smoothing functions)들이 작동하고 있거든요. 아, 네. 좋습니다. 그럼 그걸 한번 가지고 놀아보죠. 변형 (transform)을 가지고 놀아봅시다. 여기 보시면 'H'는 작아지고 원은 커지고 있는 게 보일 겁니다.
사실 저는 그걸 원하지 않아요. 그래서 제가 'H'를 추출할 때, 이 텍스트에서 찾은 모든 'H'들의 그룹을 생성합니다. 만약 제가 그중 첫 번째 요소를 가져온다면, 그것의 형태를 갖게 될 겁니다. 이건 필요 이상으로 보기 흉하네요. 하지만 만약 제가 행렬 (matrix)을 사용하고 싶다면, 이 전체 텍스트가 그 안에 포함된 문자들의 그룹인 것처럼 일종의 계층 구조 (hierarchy)가 존재하게 됩니다. 그래서 제가 그냥 첫 번째 문자만 원한다면, 사실 더 간단한 방법이 있어요. 아주 단순한 방법이죠. 첫 번째 문자를 가져올 겁니다. 즉, 그 파이썬 (Python) 리스트의 0번째 요소, 그다음 그 'H'의 실제 포인트 데이터 (points data)를 가져오는 거죠.
재밌네요. 좋습니다. 그러니까 문자를 가져오는 대신, 그냥 기하학적 (geometrical)인 것을 가져온 겁니다. 그리고 거기서의 스무딩 (smoothing)에 대해서 말하자면, 제가 레이트 함수 (rate function)라고 부르는 속성이 있는데, 기본값은 그냥 부드럽게 보이는 'smooth'라는 것으로 설정되어 있습니다. 하지만 그것이 전형적인 스무스 스텝 (smooth step) 형태의 프로필이 아니라면, 기본적으로는 큐빅 베지에 (cubic bezier) 곡선입니다. 제 생각에 그것은 스무스 스텝 (smooth step)과 비슷할 거예요. 하지만 만약 선형 (linear)이었다면, 약간 끊기는 느낌이 든다는 점을 주목해 보세요. 실행 시간 (runtime)을 1로 설정하면 확인하기 더 쉬울 겁니다. 보시다시피, 시작과 끝이 덜컥거리는 (jerky) 느낌이 납니다.
때로는 그런 느낌이 필요할 때도 있죠. 네, 하지만 때로는 그렇지 않을 때도 있습니다. 사실 나중에 이 부분이 나올 텐데, 기본값이 부드러운 (smooth) 방식일 때 이를 선형 (linear)으로 바꾸는 방법입니다. 저는 이 부분이 정말 기대되는데, 왜냐하면 바로 그런 디테일들이 '무언가를 움직이게 만드는 것'과 '무언가를 보기 좋게 만드는 것'의 차이를 만들기 때문입니다. 맞아요, 맞아요. 그것을 정말 쉽게 만드는 것이죠. 제 생각에 그것이 Manim이 하고 있는 역할의 큰 부분인 것 같습니다. 우리가 언급했던, 많은 사람들이 들어봤을 법한 고전적이고 흥미로운 레크리에이션 수학 (recreational maths) 사례를 하나 해봅시다.
AI 자동 생성 콘텐츠
본 콘텐츠는 YouTube 3Blue1Brown (수학/ML)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기