배경
최근에 유니티로 서비스하고 있는 앱에서 기능 추가를 위해 불가피하게 레거시 코드를 리팩토링하고 있다.
기존에도 다른 사람이 작성한 코드를 수정해야할 일이 당연히 있었지만, 이렇게 레거시 코드를 뜯어 고치다보니 남의 코드를 수정하는 일이 정말 쉽지 않다는 것을 다시 한번 느끼게된다.
리팩토링을하며 소소한 버그도 발견하거나 이해할 수 없는 로직을 분석하는 것도 힘들었지만, 나를 은은하게 열받게(?)하는 포인트는 중첩으로 사용된 if문이었다. 잘 못된 코드는 아니지만 묘하게 보기 불편한 이 중첩 조건문들을 보며 '혹시 나도 이런 코드를 짜지 않았나?' 반성하게 되었다.
문제
중첩 조건문의 문제가 뭘까?
void someFunction() {
if (isLogin) {
if (isUser) {
if (isAdmin) {
if (isAuthorized) {
if (isSuccess) {
anotherFunction();
} else {
throw Exception("error");
}
} else {
throw Exception("error");
}
} else {
throw Exception("error");
}
} else {
throw Exception("error");
}
} else {
throw Exception("error");
}
}
위 코드는 기능상 전혀 문제가 없다. 하지만 코드 블럭이 많아지고 직관적이지 못하다. 예시에는 분기마다 한 줄의 코드만 있어 그나마 코드진행을 유추할 수 있지만, 실제 코드에서는 비즈니스 로직이 길어지기 때문에 직관성이 더욱 떨어지게 된다.
또한, 조건이 추가될 때마다 코드가 n배 이상 더 복잡해지는 결과를 야기한다.
해결
중첩 조건문을 해결하기 위한 방법으로 Guard Clause를 사용할 수 있다.
Guard Clause란 함수나 메써드에서 특정 조건이 만족되지 않을 경우 즉시 반환, 종료, 예외를 발생시켜 코드의 중요 로직이 중첩되지 않도록 방지하는 방식이다.
중첩을 제거하고, 주요 로직에 초점을 맞춰 가독성을 높일 수 있다. 또한 이를 통해 코드가 간결해져 유지보수가 용이하도록 해준다.
Guard Clause방식을 적용하여 위 함수를 개선해보자.
void someFunction() {
if (!isLogin) throw Exception("error");
if (!isUser) throw Exception("error");
if (!isAdmin) throw Exception("error");
if (!isAuthorized) throw Exception("error");
if (!isSuccess) throw Exception("error");
anotherFunction();
}
기존보다 가독성이 훨씬 더 좋아진 것을 확인할 수 있다. 또한 새로운 조건이 추가되더라도, 이후 로직을 수정할 때 전혀 영향이 미치지 않는다.
중첩된 조건문 대신 Guard Clause를 사용함으로써 가독성 증가, 유지보수 용이, 단일 책임 원칙 준수, 코드 중복 감소 등의 효과를 얻을 수 있는 것이다.
나는 주로 위 방식을 서버api개발을 할 때 사용했었다.
API에서는 주로 입력값의 검증, 리소스 접근, 권한 확인 등의 절차 이후에 비즈니스 로직을 실행하기 때문에 위와같은 방식으로 조건문을 사용하는 것이 훨씬 바랍직하다고 생각한다.
조건문에서는 긍정문을 사용?
이전에 클린코드를 공부하며 조건문에서는 긍정문을 사용하는 것이 좋다는 것을 배웠었다. 하지만 Guard Clause를 사용하면 부정문을 사용하게 되는 경우가 생기게 된다. 이로인해 나쁜 코드가 된것이냐? 라고 묻는다면 그것은 아니라고 생각한다. 위 if (!isSuccess) 를 긍정문으로 바꿔서 if (isUnSuccess)로 바꾼다면 클린코드가 되는것일까?
나는 아니라고 생각한다. 결국 클린코드를 짜기 위해서 지켜야할 대원칙들이 있겠지만, 모두의 입맛에 맞출 수는 없으며 모든 상황마다 최대한 다른 사람들을 배려하면서 코드를 짠다면 그것이 클린코드라고 생각한다.
그냥 읽기 좋은 코드를 짜는 것을 목표로 해보자!
'Flutter' 카테고리의 다른 글
[Flutter] 패키지 pub.dev에 배포하기 (0) | 2025.01.16 |
---|---|
[Flutter] Windows 자동 업데이트 구현 (0) | 2024.09.20 |
[Flutter] Unable to load asset 오류 해결 (0) | 2024.08.03 |
[Flutter] JSON 다루기 (리스트, 중첩) (0) | 2024.07.27 |
[Flutter] Animation을 사용하여 ListView 선택 효과 만들기(AnimatedPositioned) (0) | 2024.07.21 |