SiliconValley_survivor

SiliconValley_survivor

OOD, Object Oriented Design 모델링 디자인 예제 - ParkingLot [6]

개념과 이론들을 어떻게 실제로 적용해서 설계를 해야하는지 예제로 알아보도록 합니다.

SiliconValley_survivor's avatar
SiliconValley_survivor
Feb 02, 2026
∙ Paid

이 시리즈에서는 이론으로만 끝나는 설계가 아니라, 실제로 코드를 짜면서 SOLID 원칙과 디자인 패턴이 어떻게 적용되는지 직접 확인해 보는 것을 목표로 합니다.

오늘은 기술 면접/실무에서 가장 자주 나오는 주제 중 하나인 주차장(Parking Lot) 시스템을 Python으로 설계해 보겠습니다.
단순히 코드를 보여주는 게 아니라, 왜 이렇게 설계했는지, 어떤 원칙을 적용했는지, 어떤 트레이드오프가 있었는지까지 같이 이야기하겠습니다.

1. 요구사항 정의와 초기 사고 과정

핵심 기능

  • 여러 층(multi-level) 주차장

  • 차량 종류별 주차 가능 구역 (오토바이 / 소형차 / 대형차)

  • 입차 → 빈 자리 자동 배정 → 티켓 발행

  • 출차 → 시간 기반 요금 정산 → 자리 해제

  • 주차장이 만차면 입차 거부

  • 실시간 빈 자리 수 확인 가능

비기능 요구사항

  • 새로운 차종/요금 정책이 추가되어도 기존 코드 거의 수정하지 않기 (확장성)

  • 여러 대가 동시에 입·출차해도 안전하게 처리 (간단한 락으로 시작)

  • 유지보수성 최우선 → SOLID 원칙 적극 적용

초기 질문들 (이걸 고민하면서 시작합니다)

  • 차량과 주차 공간의 매칭 로직은 어디에 둘 것인가?

  • 요금 계산 로직이 바뀌면(시간당 → 정액제 → 회원제) 어디만 고치면 될까?

  • 새로운 주차 공간 타입(전기차 충전, 장애인 전용)을 추가할 때 기존 코드를 건드리지 않으려면?

  • ParkingLot 클래스가 모든 걸 다 하면 안 되는 이유는?

→ 여기서부터 단일 책임 원칙(SRP)과 개방-폐쇄 원칙(OCP)이 자연스럽게 떠오릅니다.

초기 질문조차 떠올리지 못할 때는 “이 시스템이 진짜로 해야 하는 일은 뭘까?”라는 아주 기본적인 질문을 먼저 스스로에게 던지는 게 가장 빠르고 효과적인 출발점입니다.

그리고 그 다음으로 자연스럽게 떠오르는 질문들을 “무엇 → 어디 → 어떻게 → 왜”라는 4단계 사고 흐름으로 정리하면, 거의 자동으로 핵심 초기 질문들이 만들어집니다.


“무엇(What)”, 이 시스템이 해야 하는 일은?

→ 가장 먼저 “이 시스템의 목적은 뭘까?”부터 시작하세요.
주차장이라면 → “차를 넣고 빼는 게 핵심 아닐까?”

→ 그러면 자연스럽게 이런 질문이 나옵니다

  • 차는 어떤 종류가 들어올 수 있나? (오토바이? 승용차? 버스? 전기차?)

  • 주차 공간도 차 종류별로 다르나?

  • 입차할 때 무슨 일이 일어나야 하나? (자동 배정? 티켓 발행?)

  • 출차할 때 무슨 일이 일어나야 하나? (요금 계산? 결제?)

“어디(Where)”, 그 일은 누가 / 어디서 / 어떤 객체가 담당해야 하나?

→ 기능이 떠오르면 바로 “이 로직은 어느 클래스에 넣어야 할까?”로 넘어갑니다.
이게 객체지향 설계의 핵심 질문이 될 수 있습니다.

주차장 예시에서 나온 질문들 대부분이 여기서 나옵니다.

  • 차량과 주차 공간의 매칭 로직은 어디에 둘 것인가? → ParkingLot? ParkingFloor? ParkingSpot? 별도 Matcher 클래스?

  • 요금 계산 로직이 바뀌면 어디만 고치면 될까? → ParkingLot 안에 if-else로 넣으면 안 되지 → 별도 클래스? 인터페이스?

  • 새로운 주차 공간 타입(전기차 충전, 장애인)을 추가할 때 기존 코드를 건드리지 않으려면? → Factory? 상속? Enum 확장?

  • ParkingLot 클래스가 모든 걸 다 하면 안 되는 이유는? → God Class가 되면 → 변경 시 영향 범위가 너무 커짐 → SRP 위반

다양한 접근이 생기게 되므로, 이 단계에서 “책임 분리”와 “확장성”에 대한 고민을 하실 수 있습니다.

“어떻게(How)”, 변경이 자주 일어날 만한 부분은 어디인가?

→ 실무에서 가장 많이 바뀌는 부분을 미리 생각하면 훨씬 좋은 질문을 만들 수 있어요.

주차장 예시로 보면,

  • 요금 정책 (시간당 → 정액제 → 회원제 → 첫 30분 무료 → 야간 할인…) → 자주 바뀜 → Strategy 패턴?

  • 주차 공간 종류 추가 (EV, 장애인…) → 자주 추가됨 → OCP 지켜야 함

  • 차량 종류 추가 (트럭, RV, 자전거…) → → 비슷하게 확장성 고민

  • 빈 자리 찾는 알고리즘 (가까운 곳? 가장 큰 곳? 우선순위?) → → 나중에 바뀔 수 있음

→ “가장 자주 바뀔 것 같은 부분을 미리 분리해라”라는 사고가 들어가면 질문이 저절로 나옵니다.

“왜(Why)” — 이걸 이렇게 하는 이유는 뭘까? (원칙 연결)

→ 위에서 나온 질문 뒤에 “왜?”를 붙여보세요.
그러면 SOLID, 디자인 패턴, 유지보수성 같은 개념이 자연스럽게 연결됩니다.

예시,

  • ParkingLot이 모든 걸 하면 안 되는 이유는? → 변경 시 파급 효과가 너무 커지니까 (SRP 위반) → 테스트하기 힘들고, 재사용도 안 되니까

  • 매칭 로직을 Spot에 두면 안 될까? → Spot은 “자기 자신을 관리”하는 게 책임인데, 다른 Spot과 비교하는 건 책임 초과

  • 요금 계산을 왜 Strategy로 빼나? → 정책이 바뀔 때마다 ParkingLot 코드를 수정하면 OCP 위반이니까


SOLID 원칙을 실제로 어떻게 적용했는지 (생각 과정 포함)

주차장 시스템을 설계하면서 가장 신경 쓴 부분은 바로 SOLID 원칙이었습니다. 이 원칙들을 단순히 “알고 있다” 수준이 아니라, 실제 코드 구조와 선택에 직접 반영하려고 노력했습니다. 아래는 각 원칙별로 어디에 어떻게 적용했는지, 그리고 그때 어떤 생각을 했는지 정리한 내용입니다.

S – 단일 책임 원칙 (Single Responsibility Principle)
대부분의 클래스들이 한 가지 일만 하도록 설계했습니다.
예를 들어 ParkingSpot은 오직 “자리 점유 상태 관리와 주차/출차 동작”만 담당합니다. 요금 계산은 절대 하지 않고, 층별 빈 자리 찾기도 하지 않습니다.
FeeStrategy(요금 전략) 클래스는 요금 계산만, Ticket은 입차 정보 기록만 담당합니다.

왜 이렇게 했을까요?
한 클래스가 “주차도 하고, 요금도 계산하고, 티켓도 발행하고, 빈 자리도 찾으면” → 나중에 요금 정책 하나만 바뀌어도 그 클래스를 통째로 뜯어고쳐야 합니다.
결국 변경이 다른 부분에까지 파급되고, 단위 테스트도 어려워지며, 버그가 쉽게 생깁니다.
그래서 최대한 책임을 쪼개서 “하나가 망가져도 나머지는 멀쩡하다”는 상태를 만들고자 했습니다.

O – 개방-폐쇄 원칙 (Open-Closed Principle)
“확장에는 열려 있고, 수정에는 닫혀 있어야 한다”는 원칙을 가장 중점적으로 지켰습니다.

새로운 차종(예: 전기차, 트럭)이 추가되거나, 새로운 주차 공간 타입(장애인 전용, EV 충전)이 생기거나, 요금 정책이 바뀔 때(시간당 → 정액 → 회원 할인) 기존 코드를 거의 건드리지 않고 확장할 수 있도록 했습니다.

This post is for paid subscribers

Already a paid subscriber? Sign in
© 2026 실리콘밸리_생존자 · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture