본문 바로가기
C.W.K.
Stream
Lesson 01 of 04 · published

프로세스 하나가 전부 책임진다

~11 min · single-process, launchd, ownership, operations

Level 0Open Gate
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"프로세스 하나가 앱을 서빙하고, 스케줄을 돌리고, 쓰기를 쥐고, 백업을 순환시켜. 주인이 하나면 누가 뭘 했는지 물을 일 자체가 없어."

한 지붕 아래 전부

Keep 는 launchd agent 하나로 돌아가. 그 한 프로세스가 전부 해. API 를 서빙하고, 빌드된 PWA 를 서빙하고(웹 앱을 나눠 주는 프로세스와 그 앱의 호출에 답하는 프로세스가 같아), 06:31 일일 loop 를 돌리고, SQLite writer 를 쥐고, 백업을 순환시켜. 따로 도는 웹 서버도, 따로 도는 스케줄러도, 백업 daemon 도 없어. 프로세스 하나, 움직이는 모든 부품의 주인 하나. 가족 하나가 쓰는 local-first 앱에서 이건 제약이 아니야. 시스템 전체를 머리로 따라갈 수 있게 만드는 의도된 단순함이지.

프로세스 하나가 딱 맞는 양인 이유

클라우드 아키텍처로 단련된 본능은 쪼개라고 말해. 웹 tier, worker tier, cron 서비스, 백업 job, 각자 따로 스케일하게. 그 규모에선 맞는 말이야. Mac 한 대 위의 가족 한 팀한텐 터무니없는 과잉이고. 쪼갤 때마다 새 조율 문제가 생겨. 스케줄러와 웹 서버는 상태를 어떻게 합의하지? DB 에 쓰는 게 하나뿐이란 걸 어떻게 보장하지? 백업 daemon 과 일일 loop 가 겹치면? Keep 는 이 질문들을 푸는 대신 아예 안 생기게 만들었어. 프로세스가 하나면 writer 의 주인이 누군지를 두고 자기 자신과 다툴 수 없어. 자기가 곧 writer 니까.

프로세스 경계를 하나 더할 때마다 조율 문제를 하나 사들이는 거야. 서비스로 쪼개면 독립 스케일을 얻는 대신 분산 시스템의 복잡성을 지불해. consensus, 순서 보장, 부분 실패까지. 그 스케일이 필요 없는 규모에선 아무것도 아닌 것에 값을 치르는 셈이야. 프로세스 수는 상상 속 다이어그램이 아니라 실제 운영 필요에 맞춰. 그러면 주인 하나가 정답인 경우가 꽤 많아.

single writer 를 실물로 만드는 건 single process 야

snapshot 트랙에서 본 single-writer DB 보장 기억하지? 그게 물리 법칙이 되는 자리가 여기야. SQLite writer 가 정확히 하나인 이유는 프로세스가 정확히 하나고 그 프로세스가 writer 라서야. lock 이나 서비스 간 조율로 single-writer 를 강제할 필요가 없어. 아키텍처가 여러 writer 를 아예 불가능하게 만들었으니까. 쓸 수 있는 프로세스 자체가 하나뿐이잖아. 깔끔한 데이터 레이어의 invariant 과 깔끔한 프로세스 모델은 같은 사실을 두 각도에서 본 거야.

살려 두는 일은 launchd 몫이야. 프로세스 바깥에 있는 유일한 존재가 supervisor 야. launchd 가 agent 를 띄우고, 죽으면 다시 살리고, 부팅 때 시작시켜. 이게 옳은 분업이야. OS 레벨 supervisor 는 프로세스의 존재를 보장하고, 프로세스는 그 안의 전부를 보장하고. 자기만의 babysitter 를 짓지 마. 플랫폼의 supervisor 한테 그것이 만들어진 단 하나의 일을 맡겨.

Code

프로세스 하나, 책임 전부 (예시)·text
com.cwk.keep-serve  (launchd agent 하나)
  ├─ API 서빙                (HTTP endpoint)
  ├─ 빌드된 PWA 서빙          (웹 앱 자체)
  ├─ 06:31 일일 loop 실행     (in-process 스케줄러)
  ├─ SQLite writer 담당        (유일한 writer)
  └─ 백업 순환                 (crash-safe 스냅샷)

# 두 번째 웹 서버 없음. 두 번째 스케줄러 없음. 백업 daemon 없음.
# '누가 writer 를 쥐고 있지?' 는 프로세스가 하나라 답도 하나야.
# launchd 의 유일한 일: 이 프로세스를 살려 두고, 죽으면 재시작.

External links

Exercise

네가 지었거나 상상해 본 작은 앱을 놓고 프로세스를 세어 봐. 웹 서버, worker, 스케줄러, 백업 job. 쪼개진 곳마다 물어봐. 이게 진짜로 독립 스케일이 필요해서 쪼갠 거야, 아니면 습관이야? 그다음 단일 프로세스 버전을 설계하고, 그 순간 그냥 사라져 버리는 조율 문제들을 나열해 봐. 마지막으로 진짜로 프로세스 밖에 있어야 하는 단 하나를 짚어 봐. 힌트는 '살려 두기' 야.
Hint
작은 앱의 프로세스 분리는 대부분 클라우드 다이어그램을 무늬만 따라 한 거야. 접어 버리면 진짜 복잡성이 사라져. 프로세스 간 상태 sync 도 없고, '누가 DB 에 쓰지' 라는 질문도 없고, cron 과 앱이 경주할 일도 없어. 밖에 남아야 할 하나는 supervisor 야. 네 프로세스를 다시 살리는 건 OS 여야 하고, 프로세스가 스스로를 살리는 구조는 아니어야 하니까.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.