프로그래밍 언어/python

[guard clause] 간결한 코드 로직을 위한 guard clause 패턴

이현찬 2023. 7. 9. 19:25
728x90

프로그램을 작성하다 보면 특정 기능을 실행할 때 여러 조건을 검증해야하는 경우가 있다. 이런 경우에 nested if 문을 사용해 각 조건을 검증할 수 있는데, 이런 경우에 indentation의 영향 등으로 가독성이 떨어지는 비효율이 존재한다.

Guard

guard는 프로그램에서 특정 기능을 수행하기 위해 True로 유지되어야 하는 bool type 변수다. 쉽게 말하면 프로그램을 진행하기 위해 만족해야하는 조건을 guard라고 한다.

다음과 같은 방식으로 로그인 기능이 있다고 하자.

line4의 guard 1에서 check_username으로 존재하는 username인지 여부를 True 혹은 False로 확인한다. 다음 단계인 암호 확인 단계로 넘어간다. line5의 guard 2 조건을 만족할 때 비로소 로그인 확인이 완료되고 다음 프로그램으로 넘어갈 수 있게 된다. 여기에는 가독성을 해치는 두 가지 문제점이 있다.

문제점 1. if - else block간 거리 문제

if - else 로직의 내용을 파악하기 위해서는 조건을 만족했을 때 실행되는 if 블럭과 만족하지 않았을 때 실행되는 else 블럭을 함께 파악해야한다. 그런데 이와 같은 구조에서는 조건의 수 만큼 if문이 중첩된다. 따라서 조건이 많아질수록, if 블럭과 else 블럭 사이의 거리는 멀어져 로직에 대한 파악을 어렵게 한다.

문제점 2. 코드 depth의 문제

if 문이 중첩됨에 따라 depth가 깊어진다. 깊어진 depth는 코드를 위에서 아래로 순차적으로 읽고 이해하는데 굉장한 걸림돌이 된다. 이에 따라 코드를 작성하는 과정에서도 depth 단계를 잘못 작성해 오류를 발생시킬 수 있고, 이후 유지보수에도 어려움이 발생할 수 있는 패턴이다.

Guard Clause로 조건문 flatten (평탄화)

기본적인 개념은 if 조건에 부여되는 guard를 부정 조건(not guard)으로 바꾸는 것이다. guard 조건을 만족하는지 확인하고 진행하는 것이 아니라, guard 조건을 만족하지 않는지 확인하고 로직을 중단시키는 것이다. guard clause pattern은 로직 진행 중 조건에 따라 early stop한다고 볼 수 있다.
아래 예시 코드에서 check_condition 함수는 기본적인 if-else문으로 두 조건의 만족 여부를 확인하고 그에 따른 결과를 반환하는 함수이고, check_condition_guard 함수는 guard clause pattern을 적용해 평탄화한 함수이다.

기본적인 if - else 문으로 작성한 check_condition 함수에서는 2단계의 indent가 발생했고, guard 조건과 그를 만족하지 않았을 때 실행되는 코드가 멀리 떨어져있어 순차적으로 코드를 읽으며 이해하기 어렵다. 반면에 guard clause pattern을 적용한 check_condition_guard 함수는 guard 조건을 만족하지 않았을 때 실행되는 코드를 바로 확인할 수 있고 1단계 depth만 유지하기 때문에 코드 이해가 쉽고 이후 유지보수를 중 조건이 추가/제거 될 때도 편리하게 수정할 수 있다.

결론

이번 포스팅에서는 여러 조건 점검이 필요한 상황에서 if문을 간결하게 사용할 수 있는 guard clause pattern에 대해 학습했다. 어떤 프로그램을 작성하더라도 여러 개의 조건에 따라 control하는 로직은 발생하게 된다. 그때마다 nested if문 대신 guard clause pattern을 도입해 가독성 향상, 코드 depth 감소, 유지 보수성 향상의 효과를 얻을 수 있다.
포스팅에서 작성한 예시 코드는 함수를 정의하고 return을 하는 방식만 설명했지만 반복문과 함께 사용할 경우 breakcontinue를 사용해 guard clause를 구현할 수 있다.

더보기

이 문제 풀이의 line 20~22를 참고