65P by neo 3일전 | ★ favorite | 댓글 1개
  • 좋은 시스템 설계란 복잡해 보이지 않고 오랜 기간 별다른 문제가 발생하지 않는 형태
  • 상태(state) 를 다루는 것이 시스템 설계에서 가장 어려운 부분이며, 가능한 한 상태를 저장하는 컴포넌트 수를 줄이는 방향이 중요
  • 데이터베이스는 주로 상태가 보관되는 위치로, 스키마 설계와 인덱싱, 병목 해소에 중점을 둔 접근이 필요
  • 캐싱, 이벤트 처리, 백그라운드 작업 등은 성능 및 유지보수를 위해 신중하게 도입해야 하며, 남용을 피하는 것이 좋음
  • 복잡한 설계보다는 충분히 검증된 간단한 컴포넌트 및 방법론을 적절하게 사용하는 것이 지속 가능하고 안정적인 시스템 구축에 핵심

시스템 설계의 정의와 전체적인 접근

  • 소프트웨어 설계가 코드의 조립이라면, 시스템 설계는 다양한 서비스를 조합하는 과정
  • 시스템 설계의 주요 구성 요소는 앱 서버, 데이터베이스, 캐시, 큐, 이벤트 버스, 프록시
  • 좋은 설계는 "특별한 문제가 없다", "생각보다 쉽게 끝나다", "이 부분은 신경 쓸 필요가 없다"와 같은 반응을 이끌어냄
  • 반대로 복잡하고 눈에 띄는 설계는 근본 문제를 감추거나, 과도한 설계를 나타낼 수 있음
  • 복잡한 시스템은 초기부터 바로 도입하기보다는, 최소한의 작동 가능한 단순한 구조에서 점차 발전하는 방향이 유리함

상태(state)와 무상태(stateless)의 구분

  • 소프트웨어 설계에서 가장 까다로운 부분이 바로 상태 관리
  • 정보를 저장하지 않고 즉시 결과를 반환하는 서비스(GitHub의 PDF 렌더링과 같은)는 무상태적임
  • 반면 데이터베이스에 쓰기를 수행하는 서비스는 상태를 관리함
  • 시스템 내 상태 저장 컴포넌트를 최대한 줄이는 것이 좋음. 이는 시스템의 복잡도와 장애 발생 가능성을 낮춤
  • 상태 관리를 한 서비스에서만 수행하고, 나머지 서비스는 API 호출 혹은 이벤트 발생 등 무상태 역할에 집중하는 구조가 권장됨

데이터베이스 설계와 병목 지점

스키마 및 인덱스 설계

  • 데이터 보관을 위해서는 사람이 읽기 쉬운 형태의 스키마 설계가 필요함
  • 너무 유연한 스키마(예: 전체를 JSON 컬럼에 저장)는 애플리케이션 코드 및 성능에 부담을 줄 수 있음
  • 쿼리가 빈번하게 발생할 컬럼을 기준으로 적절한 인덱스를 설정해야 함. 모든 것에 인덱스를 거는 것은 오히려 쓸데없는 오버헤드 발생

병목 해결 방법

  • 데이터베이스 접근이 종종 무거운 병목이 됨
  • 가능한 한 복잡한 데이터를 애플리케이션에서가 아닌 데이터베이스 내에서 조인(JOIN) 등으로 처리하는 것이 성능상 유리함
  • ORM 사용 시, 루프 안에서 쿼리를 발생시키는 실수를 주의해야 함
  • 필요에 따라 쿼리를 분할하여, 데이터베이스의 부담이나 쿼리 복잡도를 조절하는 것도 한 방법
  • 읽기 쿼리는 복제본(read-replica)으로 분산하여, 주(Write) 노드의 부하를 줄이는 전략이 효과적
  • 대량의 쿼리가 몰릴 때 트랜잭션 및 쓰기 연산은 데이터베이스를 쉽게 과부하 상태로 만들 수 있으므로, 쿼리 스로틀링(제한) 처리를 고려해야 함

느린 작업과 빠른 작업의 분리

  • 사용자가 인터랙션하는 작업은 수백 밀리초 내 응답이 필요
  • 시간이 오래 걸리는 작업(예: 대용량 PDF 변환 등)은 최소한의 작업만 프론트에서 즉시 제공하고, 나머지는 백그라운드로 넘기는 패턴이 효과적
  • 백그라운드 작업은 일반적으로 큐(예: Redis)와 잡 러너가 묶여 동작
  • 멀리 예약된 작업 처리는 Redis보다 DB 테이블을 별도로 만들어 관리하고, 스케줄러를 이용하여 실행하는 형태가 실용적

캐싱

  • 캐싱은 동일하거나 비싼 연산을 반복하는 경우 비용 절감과 성능 향상에 기여
  • 보통 캐시를 처음 배운 주니어 엔지니어는 모든 것을 캐시하고 싶어하고, 경험 많은 엔지니어일수록 캐시 도입은 신중
  • 캐시는 새로운 상태를 도입하므로, 동기화 이슈/오류/스테일 데이터 등의 위험이 존재
  • 먼저 쿼리의 인덱스 추가 같은 성능 개선을 시도한 뒤 캐싱을 적용하는 것이 바람직
  • 대용량 캐시는 Redis/Memcached가 아니라 S3/Azure Blob Storage와 같은 문서 저장소에 주기적으로 저장하는 방식도 활용 가능

이벤트 처리

  • 대부분의 기업은 이벤트 허브(예: Kafka) 를 갖추고, 다양한 서비스가 이벤트 기반으로 분산 처리
  • 이벤트의 남발보다는, 단순한 요청–응답 API 설계가 로깅과 문제 해결 면에서 더 유용
  • 이벤트 기반 처리는 발신자가 수신자 동작에 신경 쓰지 않아도 될 때, 혹은 고용량·지연 허용 시나리오에 적합

데이터의 전달 방식: 푸시와 풀

  • 데이터 전달에는 Pull(요청 후 응답)Push(변경 시 자동 전달) 두 방식이 있음
  • Pull 방식은 단순하지만 반복 요청/과부하 문제가 발생
  • Push 방식은 서버에서 데이터 변경 시 클라이언트에 즉시 전달하므로, 효율적이며 최신 데이터 유지에 유리
  • 대량 클라이언트 처리에는 각각 방식에 맞게 인프라(이벤트 큐, 여러 캐시 서버 등) 확장이 필요

핫패스(Hot Paths) 집중

  • 핫패스란 시스템 내에서 가장 중요하고 데이터가 많이 흐르는 경로를 의미
  • 핫패스는 선택지가 적고, 설계 실패 시 서비스 전체에 심각한 문제를 유발할 수 있으므로, 신중한 설계가 필수
  • 옵션이 다양한 마이너 기능보다, 핫패스에 집중하여 설계 및 테스트에 자원을 배분하는 것이 효과적

로깅, 메트릭, 추적

  • 장애 발생 시 원인 진단을 위해, 비정상 경로(unhappy path)에 대한 상세 로그 기록을 적극적으로 해야 함
  • 시스템 자원(CPU/메모리), 큐 크기, 요청/작업 시간 등 기본적인 관측성 지표 수집이 필요
  • 평균값만 보는 대신 p95, p99 지연 시간 같은 분포 지표도 반드시 관찰해야 함. 상위 소수의 느린 요청이 핵심 사용자의 문제일 수 있음

킬스위치, 재시도, 장애 복구

  • 킬스위치(시스템 일시 차단) , 재시도의 전략적 활용이 중요함
  • 무작정 재시도는 다른 서비스에 부담만 주며, 사전에 회로 차단기(circuit breaker) 등으로 요청을 제어해야 효과적임
  • Idempotency Key(멱등키) 도입으로 동일 요청 재처리 시 중복 작업 방지가 가능함
  • 일부 장애 상황에서 열린 실패(fail open) 또는 닫힌 실패(fail closed) 중 선택이 필요함. 예를 들어, Rate Limiting은 fail open(허용) 쪽이 사용자 영향이 적은 방향임. 반면 인증은 fail closed가 필수임

마무리

  • 서비스 분리, 컨테이너, VM 도입, 트레이싱 등 일부 주제는 생략됐으나, 잘 검증된 컴포넌트를 적재적소에 사용하는 것이 장기적으로 가장 안정적인 시스템 구축으로 이어짐
  • 기술적으로 특별한 설계는 실제로 매우 드물며, 지루할 정도로 단순한 설계가 오히려 실무에서 가장 자주 쓰임
  • 본질적으로 좋은 시스템 설계란 눈에 띄지 않고, 충분히 입증된 방법론을 안전하게 조합하는 과정임
Hacker News 의견
  • 나는 이 부분에 종종 혼자임을 느낌. 엔지니어들은 복잡한 시스템을 보면 흥미로운 요소가 많아서 “여기서 진짜 시스템 설계가 이뤄지고 있음!”이라고 생각하지만, 사실 복잡한 시스템은 좋은 설계가 부재한 결과인 경우가 많음. 구직자라면, 이 사실을 면접 중에는 완전히 잊어야 함. 나도 시스템 설계 면접에서 이런 생각을 솔직하게 전달했다가 실수한 경험이 있음. 가상의 스타트업 앱 면접에서 “이 정도 QPS에선 backpressure는 무관심해도 됨”, “cron job 대신 큐를 쓸 필요가 없음, 물론 트레이드오프는 있음”, “SQL vs NoSQL? 팀이 가장 잘 아는 걸 쓰면 됨” 같은 답을 했지만, 면접관들은 이런 답을 원하지 않음. 하얀 보드판을 가득 채우고 Kubernetes가 Kubernetes를 관리하는 수준으로 복잡한 설계를 보여줘야 그들이 원하는 신호를 줄 수 있음

    • 내가 수백 번 시스템 설계 면접을 봤고 여러 명을 트레이닝한 입장에서 말해봄. 네가 언급한 답변은 신호가 약함(큐 관련 답변은 예외), 면접관들이 진짜 알고 싶은 건 ‘왜’ 이런 결정을 내렸는지, 어떤 요소를 고려했는지, 네 사고과정을 듣고 싶어함. 답에 대해 자세히 설명하지 않으면, 면접관 입장에선 “얻을 정보가 별로 없다”라고 생각하기 쉬움. 그래서 면접자는 면접관이 원하는 정보를 적극적으로 전달해야 함. 또 좋은 면접관이라도 답을 억지로 끌어내야 한다면 “설명은 합리적이지만 커뮤니케이션이 비효율적임”이라고 메모할 것임. 커뮤니케이션 스킬도 평가 대상임. 마지막으로 SQL/NoSQL 답변은 동의하지 않음. 팀 경험도 중요하지만, 기술 간의 차이가 명확하고 상황에 따라 성능 차이도 큼. 해당 답은 다양한 상황 경험이 부족해 보인다는 인상을 남김

    • “면접은 양방향”이라는 말처럼, 네 답변들은 매우 합리적이라고 생각함. 내가 면접관이었다면 오히려 높은 점수를 줬을 것임. 반면 네 답변으로 불합격시키는 회사라면 오히려 그 회사가 별로일 가능성이 높음. 하지만 현실적으로는 빨리 자리를 잡아야 하는 경우가 많으니, 균형을 잘 맞춰서 상대가 원하는 쪽으로 답을 맞추는 것도 필요함

    • 이 조언은 좋지 않음. 단순하면서도 우아한 설계는 잠재적 문제를 무시하는 것에서 출발하지 않음. 추궁 질문은 기술 트리비아 쏟아내는 시간이 아니라 서로 논의하자는 신호임. 네 답변들은 현명함을 보여주지 못하고, 아직 미성숙하다는 인상을 줌. 면접관 탓이 아님

    • 옆 댓글이 지적한 “면접은 양방향”이라는 지점에 공감하지만, 좋은 면접관은 “이 답도 좋은데, 나는 지금 이 테마에서 지식을 테스트하는 중임”이라고 솔직히 말해줄 것임. 본인이 엉뚱한 얘기만 계속하는 건 오히려 불안 신호임

    • LinkedIn-driven development가 왜 존재하는지 그대로 보여주는 예시라고 생각함. 수많은 기술을 CV에 나열하는 게, 하나의 Postgres와 모듈형 모놀리스만 잘 썼다고 설명하는 것보다 훨씬 더 멋져 보이는 게 현실임

  • 정말 좋은 글이라는 생각임. 하지만 이런 베스트 프랙티스에 대해 한계도 언급하고 싶음. 예를 들어, “서로 다른 5개 서비스가 한 테이블에 쓰지 말고, 4개가 API 호출하거나 이벤트를 던지도록 하고, 1개 서비스만 테이블에 쓰기”라는 조언이 있는데, 현실은 그렇게 깔끔하게 나뉘지 않음. 다섯 모두가 DB에 접근하면 이미 분산 시스템을 만들고 있는 셈인데, DB가 기본적으로 권한·트랜잭션·커스텀 쿼리를 지원하니 별도 인터페이스 설계가 필요 없기도 함. 반면, 한 서비스로 높은 수준 인터페이스를 만들면, 이제는 별도의 인증·트랜잭션·예외처리까지 직접 구현해야 함. 실질적으로는 장애모드와 복잡한 마이크로서비스 관리세가 더 생기는 것 아닌가라는 의문임. 한편, 여러 서비스가 한 DB 접근한다는 자체가 코드 스멜일 수도 있음. 아마 이 DB가 여러 개가 합쳐진 흔적일 수 있고, 서비스도 실은 두세 개로 줄일 수 있을지도 모름

    • “무엇을 얻냐”는 질문에 대해, API는 공유 DB 스키마를 사용하는 것보다 변화 적응성이 훨씬 높음. 여러 시스템을 일해본 결과, 한 DB를 여러 서비스가 공유하는 구조는 다시 설계하지 않을 것임. 2000년대 초 소규모 회사 때는 괜찮았을 수 있지만, 그 이후론 늘 실패 사례뿐이었음(동일 서비스 내에서 읽기/쓰기 경로만 분리된 경우는 예외임)

    • DB가 인터페이스라서 별도 설계가 필요하지 않다는 주장에 동의하지 않음. 여러 클라이언트가 같은 DB를 쓰면, 접근 패턴이 다르고 마이그레이션 문제도 커짐. 결국 뷰·권한관리 등 별도 추가 설계가 필요하고 유지부담도 늘어남. 이상적인 상황에선 API가 훨씬 깔끔함. 현실은 빠른 기능출시 압박 때문에 편법으로 DB 직접접근을 허용하게 되지만, 근본은 많은 이들이 새로운 요구나 디자인에 맞춰 전체 재설계를 꺼리기 때문임

    • 변경이 필요할 때, 관련된 조정 범위를 최소화하는 게 목표임. 데이터스토어 구조를 바꿔야 할 때, 해당 데이터스토어에 접근하는 모든 부분을 통제해야 하니까, 접근 경로가 적을수록 변경이 쉬워짐. 예를 들어, 실제 업무 현장에서 DB를 분리했더니 40팀 이상이 코드 고쳐야 했음. 이런 변화가 “피처 요구” 때문에 발생했다면 이 정도다. 만약 “확장성” 이슈였으면, 제품 자체가 망가질 수도 있음

    • 여러 서비스를 한 DB에 붙이는 구조를 “코드 스멜”이라고 했지만, 반대로 각각의 서비스에 물리적으로 별도 DB를 줘야 하면 가용성이 N에서 N의 M승으로 커져 실제로는 더 불안정해질 수도 있음(DB 클러스터 단위에서 얘기한다면)

  • 데이터베이스를 질의할 때는, 정말 DB에 질의하는 게 가장 효율적임. 여러 테이블의 데이터가 필요하면, 애플리케이션에서 각각 질의해서 합치는 것보다 조인을 써야 함. 그리고 뷰나 심지어 저장 프로시저도 적극 추천함. 뷰는 데이터 추상화 계층이므로 설계에 큰 도움이 되며, SQL 코드도 잘 짜면 이해하기 쉽고 유지보수도 편함

    • 이 점 때문에 ORMs이 많은 문제를 일으킴. SSR 환경의 MVC 뷰마다 SQL 뷰/커스텀쿼리를 직접 쓰는 게 대형 웹 서비스를 효율적이고 우아하게 만드는 방법임. RDBMS에게 무거운 작업을 맡기고, 웹서버는 SQL 결과를 테이블에 바로 넘겨주면 됨. MSSQL, Oracle 같은 레거시 RDBMS엔 내장 최적화가 아주 많기 때문임. 반면 ORMs은 단일 오브젝트 모델을 강요해서 유연성이 없다시피 함

    • 저장 프로시저가 유용해 보이지만, 실제론 언어(T-SQL 등) 한계로 인해 팀원들이 모두 친숙한 최신 언어로 통일해 개발하기 어려움. 대형 T-SQL 코드베이스를 유지보수하는 중인데, 버전 관리나 진단툴도 별로고, 신규 입사자 코드는 그래도 읽을 만하지만 T-SQL은 악몽임

    • 나는 동의하지 않음. 최신 확장성 위주 아키텍처에선 조인을 DB 앞단 백엔드에서 하는 것이 나음. DB에 단순 인덱스 검색을 맡기고, 조인은 백엔드에서 하도록 구조화하면 DB 확장성도 좋고 속도도 빨라짐. 서버 인스턴스 증설이 DB 증설보다 쉽기 때문임. 조인이 반드시 DB에서만 할 수 있는 어마어마한 데이터일 경우, 그때 구조를 변경해야 함. 프론트로 조인까지 옮길 수 있다면 결과 캐시도 유리하고 이득임

    • 정말 그런가? 예를 들어 고객 1만명, 주문 100만 건에서 고객 20필드+주문 5필드 테이블을 모두 조인해서 전송하면 2500만 필드를 전송하게 됨. 두 개 쿼리로 독립적으로 가져와서 조인하면, 주문 500만 필드+고객 20만 필드가 됨. 대역폭, 성능에선 이게 훨씬 나음

    • 이 규칙은 첫 출발로 괜찮지만, 언제 예외가 필요한지 잘 알아야 함. 내가 맡았던 앱은 조인 때문에 레코드가 기하급수적으로 불어나는 구조였음. 그래서 쿼리를 분리했더니 오히려 네트워크 오버헤드보다 결과 가공/필터링 이득이 커서 훨씬 빨라졌음. 나중엔 모든 데이터를 JSONB로 저장하는 구조로 바꿔서 오히려 더 나아졌음

  • 좋은 시스템 설계에 대해 얘기하면서 정작 문제 도메인은 전혀 언급하지 않은 점이 아쉽다는 생각임. 시스템 설계에서 가장 핵심이자 어려운 것은 시스템이 사용자에게 제공하는 인터페이스임. 결국 소프트웨어 시스템은 “이 기능을 제공해줄 테니, 그 대신 이런 구조/모델을 이해해야 한다”처럼 문제의 교환임. 인터페이스 설계 실수가 가장 큰 비용이고, 모든 시간의 대부분을 인터페이스에 대해 논의하지 않는다면 정말 중요한 것을 놓치고 있음. 그 밖의 시스템 요소는 나중에 사용자를 건드리지 않고 얼마든지 고칠 수 있음

  • “좋은 설계는 자기를 드러내지 않고, 나쁜 설계가 오히려 더 그럴듯해 보인다”라는 말에 현장감 있게 공감함. 기술자 평가가 “복잡함” 기준으로 이루어지면서 과설계를 장려하는 구조가 되어버린 듯함. KISS 원리가 오랫동안 충분히 인식되지 않고 있음

    • 때때로 코드베이스에서 딱히 생각하지 않고 그냥 넘어가는 부분들을 돌아보는데, 이런 게 오히려 좋은 설계를 한 흔적임

    • 이건 불행하게도 사실임. 대다수는 복잡한 솔루션에 더 매력을 느끼고, 단순한 답을 내놓으면 무능해 보인다는 인상도 있음. 하지만 현실적으로 관리가 쉬운 단순한 구조가 전체 프로젝트 성공에 더 크게 기여함. 물론 필연적으로 복잡한 문제도 있지만, 대부분은 그냥 평범한 웹앱임

  • 스키마 설계에서 가장 중요한 것은 유연성임. 데이터가 쌓이면 스키마 변경이 매우 어렵기 때문임. 하지만 너무 유연하게 설계하면(모든 데이터를 JSON에 넣거나 EAV 구조로!) 애플리케이션 코드가 한없이 복잡해지고 이상한 퍼포먼스 문제가 추가됨. 그래서 보통은 테이블 구조만 봐도 무슨 용도인지 직관적으로 알 수 있을 만큼, 사람 읽기 쉬운 스키마를 선호함. EAV, JSON 컬럼/테이블을 자주 보면 정말 개발을 그만두고 싶어짐. 분명 EAV에도 쓸모 있는 케이스가 존재하지만, 대부분의 경우엔 현장에 혼란만 줌. N+1 문제, 쿼리문 동적생성, 오디트 데이터를 동일 DB에 저장해서 그게 비즈니스 로직으로 흡수되는 패턴, 복잡한 오라클 환경, 그리고 뭘 DB에 넣을지-앱에 둘지 잘못 분리하는 설계 등, 이런 변수 하나하나가 개발자 삶의 질을 엄청나게 깎아먹음

    • 이와 관련해 Bill Karwin의 “SQL Antipatterns”라는 책에서 EAV 패턴의 위험과 한계를 잘 소개함. 그럼에도 때때로 스키마를 그리기 어려울 때(Postgres에서는 JSONB 컬럼 등) 임시 방편으로 사용할 수 있지만, 모범 규칙은 될 수 없음. 정규화가 가능하면 항상 정규화를 택하는 게 좋음

    • “오디트 데이터를 같은 DB에 저장하면 그게 결국 비즈니스 로직 일부가 돼서 곤란하다”라는 데, 그럼 “정석”은 뭔지 궁금함. 별도 DB? 완전 독립 스토리지?

  • “5개의 서비스가 동일 테이블에 쓰는 걸 피하라, 4개는 API 호출이나 이벤트만 던지고 1개만 직접 DB에 쓰라”는 조언에 대해, 최선은 애초에 5개 서비스가 동일 테이블에 쓸 일이 없게 하는 구조임. 만약 쓴다면, 실제로 서비스 간 로직이 많이 겹쳐져 있을 수도 있음. 그럼 이 5개 서비스가 과연 정말 모두 달라야 하는지, 하나로 합칠 수 없는지 고민해봐야 함. 실질적으론 별도 데이터 테이블을 주거나 리팩터링으로 오히려 문제를 해결할 수 있음

  • 상태(stateful)/비상태(stateless) 구분은 인프라와 개발 책임을 나누는 핵심임. 컨테이너로 Stateless하게 돌릴 땐 잘못될 게 많지 않으므로, 실패하면 그냥 다시 배포하면 됨. 데이터셋을 깨뜨릴 수준의 DB 실수만 피한다면 대부분 빠르게 복구 가능함. 커리어 경험, 시간, 성실도가 다양한 인력이 여기까진 괜찮음. 반면 데이터베이스, 파일스토리지 등 State가 붙는 영역은 전혀 다름. 실수 하나로 사업 전체가 위험해질 수도 있으므로, 실무 경험 풍부한 전담 인력이 맡아야 함. DB는 문제없이 작동해도 백업이 없다면 이미 큰 리스크임. 실제로 이런 영역은 몇 분 만에 배포해도 해결이 안 되는 문제임

    • “stateless 컨테이너 앱이면 큰 사고가 없다→배포하면 복구”에서, 언제부턴가 stateful 얘기로 바뀐 것 같아 논리 흐름이 이해 안 감
  • “bool 대신 timestamp로 표시” 조언에 대해, 너무 포괄적 지침 아닌지 싶음. 예를 들어 is_on → true, on_at → 1023030은 명확하지만, is_a_bear → true, a_bear_at → 12312231231은 뜬금없음. 대부분 곰은 언제 곰이 되는 게 아니니까… 특정 상황에만 맞는 얘기임

    • 나는 거의 모든 경우에 boolean 대신 timestamp나 integer를 쓰는 게 나음. 특히 상태가 둘뿐인 필드는 대개 “유형 분류”로 발전하는 경우가 많음. 예를 들어 곰만 있다고 해도 enum 타입으로 확장 가능성 대비하는 게 낫고, 상태 필드도 단순 활성/비활성 외에 다양한 상태(중지, 삭제, 일시정지 등)로 확장되기 때문에 boolean이 늘어나면서 오히려 복잡해짐. integer가 나음

    • 명제 그대로라면, DB에 boolean 쓰는 것 자체가 냄새라는 건데, 이에 동의함. 다만 이런 접근(bool → timestamp 전환 자체)이 조인에선 편의로 되는 경우가 많지, 소위 “완결적 해법”은 아님. 실시간 변경이 중요하면 애초에 오디트 테이블이 맞음. soft delete도 마찬가지로 미적지근한 해법 같다 생각함. 진짜 의도는 지우기 막기 위함인데, 사실 백업-복구로 더 효과적인 보호 가능함

    • boolean 타입이 더 작은 데이터 크기를 가지므로 일부 워크로드(분석용 대량 데이터 등)에선 효율적임. 때때로 논리적으로 boolean을 저장하는 게 맞는 경우도 있음. 예를 들어, 프로세스 결과(성공/실패 표기)는 boolean이 실용적임

    • 굳이 boolean만 timestamp로 쓸 이유가 있을지 의문임. isDarkTheme, paginationItems 등도 변경 시점이 궁금할 수 있음. 사실상 poor-man changelog라는 느낌임

    • 그런 경우라면 Bear 같은 enum 값을 쓰는 게 나음

  • 좋은 시스템 설계에 좀 더 추상적인 관점에서 배울 수 있는 책을 찾는다면, John Gall의 Systemantics 강력 추천함. 엔지니어로서 꼭 읽을 가치를 느낌

    • 이 책 짧지만 읽는 재미가 컸음. 문체가 아주 색다른 것도 인상적임