모든 프로그래머가 도전해야 할 프로젝트들 (2019)
(austinhenley.com)- 사이드 프로젝트를 고르기 어렵다면 텍스트 에디터, 2D 게임, 컴파일러, 미니 운영체제처럼 반복해서 만들수록 학습 폭이 넓어지는 프로젝트가 좋은 출발점이 됨
- 텍스트 에디터는 문서 저장 구조, 커서 동작, 실행 취소/다시 실행, 줄바꿈을 직접 구현하며 자료구조와 추상화를 익히게 함
- Space Invaders 같은 단순한 2D 게임도 화면 그리기, 입력 처리, 게임 루프, 객체 상태 관리, 적 AI, 사운드, 셰이더, 네트워킹까지 게임 프로그래밍의 기본 구조를 드러냄
- Tiny BASIC 컴파일러와 미니 운영체제는 각각 렉싱·파싱·의미 분석·코드 생성, 크로스 컴파일·부트로딩·메모리 관리·스케줄링 같은 저수준 개념을 직접 다루게 함
- 스프레드시트와 콘솔 에뮬레이터는 앞선 프로젝트들의 난이도를 결합하며, 실제 동작을 흉내 내는 가상 머신까지 만들어보는 단계로 확장됨
반복해서 만들어볼 만한 프로젝트들
- 사이드 프로젝트가 필요하거나 새 프로그래밍 언어·프레임워크를 배우고 싶을 때, 같은 프로젝트를 여러 번 만들어도 매번 다른 것을 배울 수 있음
- 추천 프로젝트는 난이도와 학습 영역이 서로 다름
- 텍스트 에디터: 자료구조, 커서 동작, 실행 취소/다시 실행, 화면 표현
- 2D 게임: 화면 그리기, 입력 처리, 게임 루프, 객체와 상태 관리
- 컴파일러: 렉싱, 파싱, 의미 분석, 코드 생성
- 미니 운영체제: 부팅, 메모리 관리, 스케줄링, 파일 시스템
- 스프레드시트와 콘솔 에뮬레이터: 앞선 프로젝트들의 개념을 더 큰 구조로 결합
텍스트 에디터
- 텍스트 에디터는 매일 쓰는 도구지만, 기본 텍스트박스 컴포넌트 없이 직접 구현하면 커서 이동, 선택, 삽입, 삭제의 세부 동작을 다루게 됨
- 가장 큰 과제는 텍스트 문서를 메모리에 저장하는 방식임
- 단순 배열은 문서 끝이 아닌 위치에 텍스트를 삽입할 때 성능이 나쁨
- 비교해볼 구조로 배열, rope, gap buffer, piece table이 있음
- 커서는 단순히 위아래로만 움직이지 않음
- 짧은 줄로 이동하면 가능한 위치로 갔다가, 이후 충분히 긴 줄이 나오면 원래 열로 돌아가려는 열 기억 동작이 있음
- 기본 에디터 이후에는 실행 취소/다시 실행과 줄바꿈을 추가해볼 수 있음
- 참고 자료
2D 게임 - Space Invaders
- 단순한 게임도 고유한 자료구조와 디자인 패턴을 요구함
- 큰 게임 엔진보다 SDL, SFML, PyGame 같은 기본 2D 그래픽 라이브러리를 쓰면 흥미로운 부분이 숨겨지지 않음
- 게임은 화면을 지우고 각 요소를 빠르게 다시 그리면서 물체가 움직이는 효과를 만듦
- 실제 흐름은 게임 루프 안에서 그리기, 사용자 입력 받기, 게임 로직 처리를 반복하는 구조임
- 입력 처리는 키나 마우스 버튼의 최초 누름, 누르고 있음, 뗌, 더블클릭 같은 세부 동작을 고려해야 함
- 입력만 계속 확인하면 게임의 나머지 부분이 멈춘 상태가 됨
- 게임 객체와 상태 관리도 직접 다뤄야 함
- 동적으로 늘어나는 적을 생성하는 데 factory pattern이 도움이 됨
- 적 AI에는 상태 기계를 적용할 수 있음
- 기본 게임 이후에는 타이틀 메뉴, 게임 오버 화면, 컴퓨터가 달라도 같은 속도로 실행되게 하는 처리, 더 흥미로운 적 AI를 추가할 수 있음
- 더 확장하면 셰이더 효과, 사운드, 온라인 멀티플레이어까지 구현해볼 수 있음
- 참고 자료
컴파일러 - Tiny BASIC
- 컴파일러는 다른 사람이 더 많은 것을 만들 수 있게 해주는 도구를 만드는 프로젝트임
- 작은 BASIC 계열 언어인 Tiny BASIC을 대상으로, 잘 아는 다른 언어로 출력하는 컴파일러를 처음부터 작성해볼 수 있음
- 예를 들어 Python으로 Tiny BASIC 컴파일러를 만들고 C# 코드를 출력할 수 있음
- 어셈블리나 C를 출력하지 않으면 컴파일러 자체에 더 집중할 수 있음
- 구현 흐름은 언어 처리 과정을 단계별로 따라감
- 입력 코드를 토큰으로 나누는 lexical analysis
- 입력 구조를 확인하고 트리 표현을 만드는 syntactic analysis
- recursive descent parsing
- abstract syntax tree
- 코드가 의미적으로 맞고 타입 규칙을 따르는지 확인하는 semantic analysis
- optimization passes
- code generation
- 단순한 컴파일러는 며칠 안에 완성할 수 있고, 이후 표준 라이브러리, 최적화 패스, 오류 메시지 개선을 추가할 수 있음
- PeayBASIC에는 간단한 2D 그래픽 기능이 표준 라이브러리로 추가됨
- 참고 자료
미니 운영체제
- 운영체제의 알고리듬과 자료구조는 교실에서는 추상적이거나 쓸모없어 보일 수 있지만, 게임이나 인간 행동 예측 모델 같은 여러 영역에도 적용될 수 있음
- 직접 구현해보면 운영체제 내부에서 어떤 일이 일어나는지 더 깊게 이해하게 됨
- 하드웨어 의존성 때문에 시작 장벽과 학습 곡선이 있지만, 책이나 튜토리얼을 따르면 직접 만든 프로그램을 실행할 수 있는 부팅 가능한 OS를 만들 수 있음
- 학습 항목은 다음과 같음
- Cross compiling
- Bootloading
- BIOS interrupts
- x86 modes
- 메모리 관리와 페이징
- Scheduling: 예를 들어 round robin
- File systems: 예를 들어 FAT
- 참고 자료
더 어려운 프로젝트: 스프레드시트와 콘솔 에뮬레이터
- 스프레드시트 애플리케이션은 Excel처럼 텍스트 에디터의 과제와 컴파일러의 과제를 결합함
- 셀 내용을 메모리에 표현해야 함
- 수식에 쓰이는 프로그래밍 언어용 인터프리터를 구현해야 함
- 스프레드시트 참고 자료
- 비디오 게임 콘솔 에뮬레이터는 컴파일러, 운영체제, 게임 엔진 구현의 어려움을 하나로 합친 프로젝트임
- 실제 콘솔을 에뮬레이션하려면 CPU와 다른 하드웨어 구성 요소처럼 동작하는 가상 머신을 작성해야 함
- 이 가상 머신에서 해당 콘솔용 게임을 실행할 수 있음
- 시작점으로는 실제 콘솔보다 단순한 가상 콘솔 CHIP-8 에뮬레이션이 권장됨
- NES, SNES, Gameboy, Gameboy Advance도 에뮬레이션이 가능하고 문서와 오픈소스 에뮬레이터가 꽤 있지만, 각 콘솔에는 흥미로운 특이점이 있음
- 특정 게임은 특정 하드웨어의 문서화되지 않은 버그나 기능에 의존할 수 있음
- PICO-8은 수익성 있는 “fantasy” 콘솔이 되었음
- 에뮬레이터 참고 자료
추가로 제안된 프로젝트
- Hacker News, Reddit, Twitter, 이메일에서 추가 프로젝트 아이디어가 모였음
- 처음부터 만드는 데이터베이스
- 레이 트레이서
- MS Paint 클론
- 벡터 그래픽 에디터
- 이미지 디코더
- 채팅방 웹 앱
- 원주율 자릿수 계산기
- grep 같은 일반 터미널 유틸리티
- FTP 클라이언트와 서버
댓글과 토론
Hacker News 의견들
-
텍스트 편집기, 컴파일러, 운영체제, 레이 트레이서를 만들면 더 나은 프로그래머가 될 수는 있지만, 더 나은 소프트웨어 엔지니어가 되는 건 아님
오히려 재앙적인 “Not Invented Here” 교리를 체화해서 소프트웨어 엔지니어링에는 더 나빠질 수도 있음
해커들은 빅오, 자료구조, HoTT 같은 고이론에 집착하지만, 실제 엔지니어링에 필수인 “직접 만들 것과 라이브러리를 쓸 것의 판단”, “좋은 라이브러리와 프레임워크 식별”, “최적화할 가치가 있는 지점 판단”, “몇 년 뒤에도 읽히는 코드 작성”, “소프트웨어와 비소프트웨어 의존성을 포함한 대규모 복잡계로 프로젝트를 바라보기”는 거의 논의도 연습도 안 됨
그래서 대안 과제로 웹 검색 엔진을 제안함. 문자열 매칭 알고리즘 같은 건 이미 남들이 해뒀으니 신경 쓰지 말고, 처음에는 웹의 일부와 동시 사용자 1명만 지원하더라도 실제로 작동하는 검색 엔진과 크롤러를 “그냥” 만들어보면 됨- 검색 엔진이 라이브러리 선택이나 최적화 기회 판단 같은 “진짜 엔지니어링 기술”을 특별히 요구한다고 보는 이유를 모르겠음
텍스트 편집기, 컴파일러, 운영체제, 레이 트레이서도 똑같은 활동을 모두 훈련할 수 있음
여러 장편 영화에 쓰인 레이 트레이서 작업을 해본 입장에서, 위에 든 항목들은 그 프로젝트에도 전부 적용됐음
결국 작고 재미있는 걸 할지, 아니면 회사에서 돈 받고 하는 영혼을 갉아먹는 제약을 그대로 적용해 즐거움을 없앨지의 차이에 더 가까움 - 그 조언은 합리적으로 들리지만, 준비된 빌딩 블록만으로 소프트웨어를 만들 때는 문제가 있음
첫째, 준비된 블록은 대체로 형편없는 경우가 훨씬 많고, 그 결과 소프트웨어도 그 형편없음을 반영하며, 삶은 소프트웨어를 쓰는 일이 아니라 그 형편없는 것들을 유지보수하고 달래는 일이 됨
둘째, 설령 블록 품질이 좋아도 쓸 수 있는 소프트웨어의 종류를 제한함. 이상적으로는 원하는 동작을 상상하고, 그걸 하도록 소프트웨어를 쓰며, 그 과정에서 블록을 만들어야 함
준비된 블록만 쓰면 훌륭한 소프트웨어 상당수는 아예 만들 수 없고, 실제로 주변에 훌륭한 소프트웨어가 많지 않은 이유도 거기에 있다고 봄
“늘 보던 것과 거의 같은 소프트웨어”를 만든다면 두 번째 문제는 해당이 덜 되고, 첫 번째도 주로 행복 경로만 쓰니 감당 가능할 수 있음. 하지만 그런 소프트웨어는 곧 사람이 아니라 AI가 쓰게 될 것임 - 악기를 배우는 학생에게 오케스트라에서 필요한 다른 기술이 있으니 음계나 연습곡은 연습하지 말라고 하는 것과 비슷함
그런 기술도 중요하지만, 어느 시점에는 기초 실력을 키워야 하고, 더 나은 프로그래머가 되는 일은 위에 나열한 기술 전반에도 분명 도움이 됨 - 글에서는 소프트웨어 엔지니어가 아니라 프로그래머라고 했음
개인적으로 소프트웨어 엔지니어링은 청구서를 내기 위해 하는 일이고, 프로그래밍은 재미있어서 시작한 일임
이 글의 프로젝트들은 시간이 있다면 재미로 해보고 싶은 종류임
- 검색 엔진이 라이브러리 선택이나 최적화 기회 판단 같은 “진짜 엔지니어링 기술”을 특별히 요구한다고 보는 이유를 모르겠음
-
UI/Web 쪽 관점이라면, 데이터 흐름 시스템을 이해하는 데 매우 유용한 스프레드시트 외에 이런 것들을 추천함
Unity나 Unreal로 간단한 비디오 게임을 만들어보면 30~60fps가 중요한 게임에서 성능 제약을 이해하게 되고, 웹을 포함한 다른 곳에서도 빠른 인터페이스를 만드는 데 도움 됨
React와 비슷한 간단한 JavaScript 프레임워크를 만들면 데이터 흐름과 이벤트 처리를 이해하는 데 도움이 됨
XMLHTTPRequest를 감싸는 HTTP 라이브러리를 직접 만들면, 지금은 fetch가 있더라도 HTTP 요청을 보내고 읽는 방식을 처음부터 이해하게 되어 나중에 CORS 문제나 OPTIONS 요청 같은 디버깅에 도움이 됨- 이 용도라면 Unity나 Unreal보다 Godot이 더 나은 대안일 수도 있음. 독점 라이선스에 빠질 필요가 없을 뿐 아니라 내부에서 무슨 일이 벌어지는지도 볼 수 있음
-
당시에도 논의됐음
Challenging projects every programmer should try - https://news.ycombinator.com/item?id=21790779 - Dec 2019 (297 comments)
관련 글도 있음
More challenging projects every programmer should try - https://news.ycombinator.com/item?id=25489879 - Dec 2020 (223 comments)- 두 번째 글의 외부 링크는 404가 남
-
미니 운영체제에 +1
애플리케이션 개발자는 메모리 관리, 파일시스템 등 많은 운영체제 기능에 의존하고 있고, 결국 “뒤에서는 이런 것들이 어떻게 돌아가지?”라고 묻게 됨
그래서 여가 시간에 xv6(https://github.com/mit-pdos/xv6-public)를 만져봄
교과서에서 여러 프로세스 스케줄링 알고리즘을 배우는 것과 직접 구현하는 것은 전혀 다르고, 많이 배움
모바일 앱 개발자로서 이 지식이 업무와 관련될 가능성은 거의 0에 가깝지만, 확실히 재미있음 -
엔진 없이 2D 게임 개발을 해본 것이 컴퓨터가 얼마나 말도 안 되게 빨라졌는지 깨닫게 해준 가장 겸손해지는 경험이었음
너무 느릴 것 같다고 확신하는 일을 해도, Game Boy에서도 초당 백만 번 연산을 하니 그냥 돌아감. 백만이라는 수가 생각보다 큰 수였던 것임
“잠깐, 매번 모든 스프라이트를 찾아서 그린다고? 바꿔야 할 것만 아는 영리한 차분 계산도 없고, 이전 프레임을 참조해 일을 줄이는 두 번째 버퍼도 없다고?”라고 하다가, 이런 기법을 실제로 쓰기 시작한 훨씬 복잡한 게임을 보면 더 놀라움- 예전에도 애플리케이션과 하드웨어 양쪽에서 이런 문제를 돕는 흥미로운 트릭들이 있었음
예를 들어 스프라이트 아틀라스는 이런 자료구조가 활용되는 전형적인 방식임. 보통 예측 가능한 방식으로 렌더링되는 스프라이트 여러 장을 매번 올릴 이유가 없으니, 큰 이미지 하나를 올리고 그 일부를 샘플링하면 됨
오늘날 기준으로는 맞음. 보급형 상용 하드웨어, 심지어 게이밍 PC가 아니어도 15년 전쯤의 거의 모든 것은 장면을 그리고 다시 그리는 식의 무식한 렌더링으로 처리 가능함 - TRS-80 Color Computer에서 2D 게임을 만들며 시작했고, 그게 컴퓨터에 대한 좋은 기초 이해를 줬음
순수 하드웨어와 어셈블리뿐이라 그래픽, 사운드, 입력, 메모리 관리 등을 전부 수동으로 해야 했음
초보 프로그래머가 이런 것들을 모두 다뤄 2D 게임을 만들 수 있되, 작동시키기 위한 과도한 짐은 덜어낸 단순화된 환경이 있다면 이상적인 입문이 될 것 같음
- 예전에도 애플리케이션과 하드웨어 양쪽에서 이런 문제를 돕는 흥미로운 트릭들이 있었음
-
Space Invaders를 만들기 위해 팩토리 패턴이 필요하다고 생각한다면 뭔가 잘못된 것임
원작에 그런 설계 개념이 들어갔을 가능성은 거의 없다고 봄- 30년간의 객체지향 프로그래밍과 디자인 패턴이 낳은 결과임
뇌가 거기에 감염되면 감염을 퍼뜨릴 방법을 찾기 시작함 - 글 어디에서도 Space Invaders 구현에 팩토리 패턴이 필요하다고 말하거나 암시하지 않음
우리가 서로 다른 글을 읽은 건가?
- 30년간의 객체지향 프로그래밍과 디자인 패턴이 낳은 결과임
-
로봇, 자동 조종 드론, 프로그래밍 가능한 GNC 파라미터가 있는 우주비행체의 비행 동역학 정밀 시뮬레이션처럼 훨씬 물리적인 걸 해보고 싶음
Bate, Mueller 등의 “Fundamentals of Astrodynamics”를 갖고 있고, 이번 휴가철에 뭔가 해보고 싶음
나머지는 비용이 많이 들 것 같아서 시뮬레이션을 말하는 것임. 로봇의 GNC 측면에 정말 관심이 많고, 좋은 자료 추천이 있으면 좋겠음- https://ksp-kos.github.io/KOS/ Kerbal Space Program이 원하는 수준만큼 공기역학을 현실적으로 시뮬레이션하지는 않을 수 있지만, 많은 사람들이 거기서 GNC 소프트웨어를 작성하는 걸 즐기는 듯함
- 자기 균형 이륜 로봇은 재미있고 비교적 안전한 프로젝트일 것 같음
넘어지거나 탁자 밖으로 날아가지 않고 한자리에서 서 있을 수 있는 Segway 같은 것을 말함
마이크로컨트롤러, IMU, 스테퍼 모터 컨트롤러, 모터, LEGO 바퀴, 어쩌면 나무토막 하나가 필요할 것 같음
직접 해본 건 아니라 추측이 많이 빗나갔을 수 있음 - “Fundamentals of Astrodynamics”로 뭘 할 계획인지 궁금함
책이 어떤 내용인지, 어떤 프로젝트를 해볼 수 있을지 더 듣고 싶음 - 같은 느낌임. 개인 프로젝트는 거의 전부 하드웨어 요소가 있음
하루 종일 소프트웨어를 다룬 뒤에는 물리적인 물체를 향해 작업하는 게 정말 좋음
-
작은 장난감 레이 트레이서도 해볼 만한 훌륭한 과제라고 봄
구와 몇 개의 광원, 난반사와 정반사를 처리해서 비트맵 그래픽을 출력하는 정도면 됨
너무 과하게 키우지만 않으면 비교적 범위가 잘 제한된 프로젝트가 될 수 있음- 컴퓨터과학과 비디오게임 전공이 훌륭한 대학에 다녔고, 모든 학점을 끝내지는 못했지만 비디오게임 수업 몇 개를 들었음
그래픽을 렌더링하려고 하면 기하학과 자료구조를 얼마나 혹사할 수 있는지 정말 많이 배우게 됨 - 그건 후속편 “More challenging projects every programmer should try”에 있음
https://austinhenley.com/blog/morechallengingprojects.html - 직접 해보고 싶다면 Ray Tracing in One Weekend가 인기 있는 튜토리얼 시리즈임
https://raytracing.github.io/ - 친구가 주말 동안 이런 걸 하나 만들었음
https://raytracing-iow.shuttleapp.rscurl --request POST --header 'Content-Type: application/json' --data '{"height":10,"width":10}' [https://raytracing-iow.shuttleapp.rs](<https://raytracing-iow.shuttleapp.rs>) - 더 난해하게 가면 “Raycasting engine in Factorio 1.1”도 있음: https://youtube.com/watch?v=0bAuP0gO5pc
- 컴퓨터과학과 비디오게임 전공이 훌륭한 대학에 다녔고, 모든 학점을 끝내지는 못했지만 비디오게임 수업 몇 개를 들었음
-
흥미로운 목록이고, 개인 성향과 상황에 따라 다르겠지만 아이디어를 찾는다면 좋은 출발점임
모든 프로그래머가 뭘 해봐야 한다고까지 말하진 않겠고, 개인적으로 선택했던 것만 적어봄
Sinclair ZX Spectrum에서는 음악 오선 편집기와 트래커를 아주 조악하게 만들었고, 2D 게임으로 침입자가 하나뿐인 Space Invaders를 만들었음
그 컴퓨터는 내 것도 아니었음. 첫 컴퓨터였던 386에서는 Huffman 압축기, DBase/Clipper보다 빨랐던 B-Tree 인덱스, 객체지향 폼 생성기, 여러 DOS 백그라운드 프로그램을 만들었고, 그중 하나는 나중에 큰 회사의 설치 과정에 쓰였음
몇 년 뒤에는 다이얼업용 이메일 확인기, 구문 강조를 위한 수동 파서, 스프레드시트 비슷한 것까지 만들었고 지금도 그걸 하고 있음. 빠뜨린 것도 분명 있을 것 같음 -
좋은 목록임. 시간이 지나며 함께 발전시킬 수 있도록 살아 있는 목록으로 유지하면 좋겠음
두 가지를 추가하고 싶음
가벼운 memcached를 만들면 기본 알고리즘과 좋은 시스템 설계 실천이 섞여 필요함. “단순한” 문제지만 무효화, 동시성, 메모리 관리 등 여러 각도에서 잘 생각해야 함
자기만의 Docker를 만들어보는 것도 좋음. 들리는 것만큼 복잡하지 않고, 요즘 엔지니어들이 일상 업무에서 많이 쓰지 않는 운영체제 프로그래밍의 기본을 이해할 기회를 줌