BioPlayground

🧬
목록으로

Guard Clause — 더러운 if문 이쁘게 바꾸기

if문 안에 if문이 겹겹이 쌓이는 코드를 Guard Clause와 Early Return으로 깔끔하게 정리하는 방법을 배웁니다.

입문
|
4
|
검증 완료 (2026-07)
진행률0/11 (0%)

Guard Clause — 더러운 if문 이쁘게 바꾸기

이 토픽을 마치면

중첩된 if문을 Guard Clause로 정리하는 방법을 알게 되고, 코드 가독성이 왜 중요한지 체감하게 됩니다.


회원가입 검증 코드를 써봤더니

회원가입 폼에서 아이디, 비밀번호, 이메일을 검증한다고 합시다. 처음엔 이렇게 쓰게 됩니다:

javascript
function register(id, pw, email) {
  if (id.length > 0) {
    if (pw.length >= 8) {
      if (email.includes('@')) {
        if (!existingUsers.includes(id)) {
          createAccount(id, pw, email);
          return '가입 완료';
        } else {
          return '이미 존재하는 아이디';
        }
      } else {
        return '이메일 형식 오류';
      }
    } else {
      return '비밀번호 8자 이상';
    }
  } else {
    return '아이디를 입력하세요';
  }
}

동작은 합니다. 근데 읽어보세요. if 안에 if 안에 if 안에 if — 오른쪽으로 계속 밀려갑니다. 조건이 두 개만 더 추가되면 화면 오른쪽 끝을 뚫을 기세입니다.

6개월 뒤에 이 코드를 다시 열면 "이 else가 어느 if의 else지?" 하면서 위아래로 왔다 갔다 하게 됩니다.


Guard Clause로 바꾸면

같은 로직을 이렇게 쓸 수 있습니다:

javascript
function register(id, pw, email) {
  if (id.length === 0) return '아이디를 입력하세요';
  if (pw.length < 8) return '비밀번호 8자 이상';
  if (!email.includes('@')) return '이메일 형식 오류';
  if (existingUsers.includes(id)) return '이미 존재하는 아이디';

  createAccount(id, pw, email);
  return '가입 완료';
}

같은 동작입니다. 근데 읽는 느낌이 완전히 다릅니다.

달라진 건 두 가지입니다:

  1. 조건을 뒤집었습니다 — "아이디가 있으면 다음으로" 대신 "아이디가 없으면 여기서 끝"
  2. 즉시 return합니다 — 문제가 있으면 그 자리에서 바로 빠져나감

이게 Guard Clause(가드 클로즈)입니다. 통과하면 안 되는 조건을 함수 앞부분에 세워두고, 하나라도 걸리면 즉시 돌려보냅니다. 문지기(Guard)가 입구에서 검문하는 것과 같습니다.


왜 이게 나은가

핵심은 읽는 순서입니다.

중첩 if문은 "정상 경로"와 "에러 경로"가 섞여 있습니다. 코드를 끝까지 읽어야 어디가 정상 흐름인지 보입니다.

Guard Clause는 에러를 먼저 처리하고, 마지막에 정상 경로만 남깁니다. 위에서 아래로 읽으면 자연스럽게 "이건 안 되고, 저것도 안 되고, 다 통과했으면 실행" 흐름이 됩니다.

text
Guard Clause 적용 후 읽는 흐름:

✗ 아이디 없으면 → 끝
✗ 비밀번호 짧으면 → 끝
✗ 이메일 틀리면 → 끝
✗ 중복 아이디면 → 끝
✓ 여기까지 왔으면 → 가입!

주의할 점

Guard Clause가 만능은 아닙니다. 함수가 아닌 곳에서 return을 쓸 수 없으니, 반복문 안에서는 continue를 대신 씁니다. 그리고 조건이 복잡하게 얽혀있을 때(A이면서 B가 아니고 C일 때)는 Guard Clause보다 논리 연산자로 조건을 합치는 게 나을 수 있습니다.

리팩토링은 코드가 복잡해질 때 자연스럽게 적용하는 겁니다. 처음부터 최적화된 코드를 쓰려고 하면 오히려 시간만 낭비합니다. 일단 작동하게 만들고, 읽기 힘들어졌을 때 정리하세요.


다른 언어에서도 똑같이

Guard Clause는 JavaScript만의 패턴이 아닙니다. return이 있는 언어면 전부 됩니다:

python
# Python
def register(id, pw, email):
if not id:
raise ValueError("아이디를 입력하세요")
if len(pw) < 8:
raise ValueError("비밀번호 8자 이상")
if "@" not in email:
raise ValueError("이메일 형식 오류")
create_account(id, pw, email)
go
// Go
func Register(id, pw, email string) error {
    if id == "" {
        return errors.New("id required")
    }
    if len(pw) < 8 {
        return errors.New("password too short")
    }

    createAccount(id, pw, email)
    return nil
}

Go에서는 에러를 return하는 게 언어 관례라서, Guard Clause가 자연스럽게 표준 패턴이 됩니다. 어떤 언어를 쓰든 **"비정상을 먼저 걸러내고, 정상 흐름만 남긴다"**는 원칙은 동일합니다.


핵심

Guard Clause는 **"통과 못 하는 조건을 앞에서 먼저 걸러내고 즉시 return"**하는 패턴입니다. 중첩 if문의 들여쓰기 지옥을 없애고, 에러 처리와 정상 흐름을 분리합니다. 조건을 뒤집고(if 정상if 비정상), 즉시 빠져나오는 것 — 이 두 가지가 전부입니다.