본문 바로가기
개발 관련 강의 정리/10분 테코톡

[10분 테코톡] 아벨의 상태 패턴 정리

by 코딩개발 2023. 6. 3.
728x90
반응형

디자인 패턴은 왜 생겼을까?

과거에 시간이 지나면서 소프트웨어의 개발이 복잡해진다. 그래서 소프트웨어의 개발자들은 공통적으로 발생하는 문제에 대한 해결책을 찾기 위해 노력하게 된다. 그 노력의 결과물 중 하나가 바로 디자인 패턴 이다. 즉 디자인 패턴 이란 공통적으로 발생하는 문제에 대한 해결책을 재사용 가능한 형태로 정리한 것이다.

 

디자인 패턴의 효과

유지보수성, 확장성, 재사용성 등 향상

 

디자인 패턴의 3가지 종류

생성 패턴, 구조 패턴, 행동 패턴

 

행동 패턴이란?

객체들이 서로 상호작용하는 방법책임을 분산하는 방법에 대한 문제를 해결하는 패턴

 

상태 패턴이란?

객체의 내부 상태에 따라 객체의 동작이 달라지는 패턴

 

처음에는 위 설명이 와닿지 않을 수 있다. 그래서 호텔 시스템 예시를 들어보려 한다.

 

호텔 시스템 사용법
1. 예약-reserveRoom()
2. 체크 인 - checkln()
3. 체크 아웃 - checkout(
0. 예약 취소 - cancelReservation()

 

레거시 코드

위 코드를 개선하는데 유용한 패턴이 상태 패턴이다.

 

 

상태 패턴의 흐름

 

개선된 후의 흐름을 좀 미리 살펴보면, 먼저 클라이언트에서 호텔 룸 객체를 통해서 호텔 시스템을 사용한다. 그리고 호텔 룸 객체는 이 상태에 역할을 맡은 인터페이스를 필드로 가지고 있으며 인터페이스를 구현한 각 구현체들이 존재한다. 그래서 구현체들이 번갈아 끼워질 때마다 호텔 룸의 객체상태가 변경되면서 행동도 같이 바뀔 수 있게 된다.

 

 

상태 패턴의 구조

 

구조를 보면 클라이언트가 있고 컨텍스트가 있으며 상태 인터페이스가 존재한다. 인터페이스를 구현하는 각 상태 구현체들을 콘크리트 스테이트 라고 한다.

 

 

상태 패턴 - State Interface (HotelRoomState)

- 각 상태별로 필요한 행동을 캡슐화한 인터페이스 이다.

 

클라이언트에서는 아래 네 개의 기능이 모두 필요하다. 그래서 이 네 개 메소드를 모두 추출을 할 것이다.

 


이 상태에 인터페이스로 먼저 정의 한다.

 

 

상태 패턴 - Concrete State (각 상태 구현체)

-  Context의 상태에 따른 실제 행동을 구현한 클래스

 

각 상태, 지금 여기서는 available 상태, 이 available 상태에 관한 로직을 각 메소드에서 추출한다.

 

 

available 상태의 구현체에 전부 위와같이 집어넣도록 한다.

다른 상태에 관한 로직들도 마찬가지로 아래와 같이 다 추출을 해서 집어 넣어주면 된다.

 

 

 


위와 같이 콘크리트 스테이트의 필드를 보면 호텔 룸객체를 필드로 가지고 있다. 이유는 이 콘크리트 스테이트가 호텔 룸 객체를 대신해서 행동을 실질적으로 해줘야 하기 때문이다.

 

 

상태 패턴 - Context (HotelRoom)

- 상태를 가지고 있는 객체로써, 상태에 따라 행동이 달라지는 클래스


상태의 인터페이스를 필드로 가지고 있습니다
그리고 자신의 모든 행동을 상태 인터페이스에 전부 위임을 하는 모습입니다
그래서 이 상태가 달라질 때마다 이 호텔 룸의 행동이 달라질 수 있게 됩니다

 

 

상태 패턴 - Client

 

이제 여기서 이 호텔 룸객체를 통해서 호텔 시스템을 사용을 할 것이다. 먼저 첫 번째 빨간 네모칸 처럼 호텔 룸의 초기 상태 설정을 해주었는데 이 컨텍스트의 객체가 콘크리트 스테이트에 관한 의존도를 최대한 없애기 위해서 한 것이다. 이것은 사람마다 구현하는 방법이 좀 다를 수 있다. 


첫번째 두번째 호출을 보면 체크 인과 체크 아웃이다. 체크인의 경우 예약이 먼저 선행이 되어야 하는데 선행이 안됐다. 그래서 상태 전이는 전혀 일어나지 않고 경고 문구만 출력된다.

 

네 번째 빨간 네모와 같이 예약이 일어나면 available 예약이 가능한 상태에서 reserved. 즉, 예약이 된 상태로 상태전이가 올바르게 일어나고 객실 예약이 완료됐다고 뜬다. 그런데 또 한번 예약이 되는데 이 경우 이미 예약이 된 상태이기 때문에 전혀 상태의 전이는 일어나지 않는다. 이처럼 같은 메서드가 호출이 된다고 하더라도 상태의 변화에 따라서 호텔 룸의 행동이 달라질 수 있다.

 

 

상태 패턴의 장점

1. SRP (Single Responsibility Principle) : 단일책임의 원칙
- 모든 클래스는 각각 하나의 책임만 가져야 한다는 원칙

 

 

위에 레거시코드를 보면 하나의 클래스가 모든 상태에 관한 책임을 가지고 있다.

 


개선된 후의 코드를 보면 각 상태의 구현체들이 각각 하나의 상태에 관한 책임 만을 갖게 된다.
그래서 이 원칙을 지킴으로써 부수적으로 나오는 효과들이 몇 가지 있다.


1) 상태의 전이를 더욱 명확하게 한다.


레거시 코드에서 필드를 보면 현재 상태를 내부 데이터의 값으로만 일단 정의 한다. 그리고 이 상태 전이의 로직을 보면 결국 상태 변수에 값을 할당 한다는 문장 정도밖에는 되지 않는다. 사실상 그 이상의 의미는 없다. 그 이상의 의미를 가지려면 if문까지 다 봐야한다.

 

 

개선된 후의 코드를 보면 이처럼 상태 전이를 할 때 객체를 완전히 바꿔준다. 그래서 더욱더 명백히 상태 전이를 할 수 있다. 따라서 이 컨텍스트의 일관성을 좀 안정성있게 유지 해줄 수가 있다.

 

2) 높은 응집도로 인해 각 상태 로직의 수정이 용이하다.


레거시 코드에서는 어떤 하나의 상태에 관한 로직을 수정을 하려고 할 때 이렇게 if문을 일일이 살펴봐야 한다.

 


개선된 후의 코드를 보면 해당하는 상태에 관한 구현체에 들어가서 수정을 해주면 되기 때문에 훨씬 알아보기가 쉽다.

 

2. OCP (Open-Closed Principle) : 개방 폐쇄의 원칙 
- 확장에는 열려있고 수정에는 닫혀있어야 한다는 원칙

 


레거시 코드에서는 어떤 요구 사항이 변경이 됐을 때 새롭게 상태가 추가될 수 있다. 그런데 새롭게 추가된 상태로 전이를 하는 그 로직에 의해서 기존의 코드에서 좀 많은 추가와 수정이 불가피하게 일어날 수 밖에 없다.

 


개선된 후의 코드를 보면 새롭게 생긴 상태에 대한 구현체를 하나 추가만 해주면 될 뿐이다. 기존의 코드는 거의 변경이 되지 않는다. 여기서 거의 라는 단어를 굳이 붙인 이유는 아예 건드리지 않는 것은 아니기 때문이다.

 

 

위와 같이 상태 패턴도 결국 어떤 새롭게 긴 상태로 전이를 하는 근로직이 일부에서 이처럼 추가가 될 수 있다.

 

3. 테스트의 용이성

개선 전 코드 개선 후 코드
하나의 테스트 클래스
모든 상태에 대한 테스트
각각의 테스트 클래스
하나의 상태에 대한 테스트


결국 장점들을 종합을 해보면 유지 보수성의 향상을 낳게 된다.

 

상태 패턴 - 주의 사항

상태에 변화가 적은 간단한 로직인 경우에 상태 패턴을 적용하려고 하면 비효율적일 수 있다.


참고

https://www.youtube.com/watch?v=BeoiIfvAmpE&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC 

728x90
반응형

댓글