32.3 goto와 에러 처리 패턴

예를 들어 가상의 통지서가 있는데 이 통지서를 집집마다 방문하여 "자가 주택을 소유한 30대 남자"에게 전달한다고 합시다. 그럼 간단하게 다음과 같은 코드로 만들 수 있겠죠?

if_error_pattern.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    int gender;      // 성별: 남자 1, 여자 2
    int age;         // 나이
    int isOwner;     // 주택 소유 여부: 자가 1, 전월세 0

    scanf("%d %d %d", &gender, &age, &isOwner);

    printf("안녕하세요.\n");
    printf("문을 연다.\n");

    if (gender == 2)                 // 여자라면
    {
        printf("안녕히계세요.\n");    // 중복 코드
        printf("문을 닫는다.\n");     // 중복 코드
        return 0;                    // 프로그램 종료
    }

    if (age < 30)                    // 30세 미만이라면
    {
        printf("안녕히계세요.\n");    // 중복 코드
        printf("문을 닫는다.\n");     // 중복 코드
        return 0;                    // 프로그램 종료
    }

    if (isOwner == 0)                // 전월세라면
    {
        printf("안녕히계세요.\n");    // 중복 코드
        printf("문을 닫는다.\n");     // 중복 코드
        return 0;                    // 프로그램 종료
    }
 
    return 0;                        // 프로그램 종료
}

문을 열고 성별, 나이, 주택 소유 여부를 확인한 뒤 "자가 주택을 소유한 30대 남자"에 하나라도 해당하지 않는다면 인사를 한 뒤 문을 닫습니다(프로그램의 실행도 끝냅니다). 이렇게 주어진 조건에 해당하지 않아서 프로그램을 종료하는 상황을 에러라고 할 수 있습니다.

코드를 잘 보면 에러 조건마다 인사하는 코드와 문을 닫는 코드가 중복됩니다. 만약 조건이 늘어난다면 중복 코드는 더 늘어나겠죠?

goto를 사용하면 에러 상황 때 항상 실행해야 하는 중복 코드를 하나로 모을 수 있습니다.

goto_error_pattern.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    int gender;      // 성별: 남자 1, 여자 2
    int age;         // 나이
    int isOwner;     // 주택 소유 여부: 자가 1, 전월세 0

    scanf("%d %d %d", &gender, &age, &isOwner);

    printf("안녕하세요.\n");
    printf("문을 연다.\n");

    if (gender == 2)
        goto EXIT;    // 에러가 발생했으므로 EXIT로 이동

    if (age < 30)
        goto EXIT;    // 에러가 발생했으므로 EXIT로 이동

    if (isOwner == 0)
        goto EXIT;    // 에러가 발생했으므로 EXIT로 이동
 
EXIT:
    printf("안녕히계세요.\n");    // 에러 처리 코드를
    printf("문을 닫는다.\n");     // 한 번만 사용함

    return 0;    // 프로그램 종료
}

이제 조건이 맞지 않아 에러가 발생할 때마다 EXIT로 이동하여 에러 처리 코드(인사를 한 뒤 문을 닫기)를 실행합니다. 즉, 종료 직전에 항상 실행해야 하는 에러 처리 코드들은 한 곳에 모아놓고 goto를 사용하면 중복 코드를 없앨 수 있고, 코드의 의도도 좀 더 명확해집니다.

실무에서는 파일을 열어놓거나 메모리를 할당한 상태에서 에러가 발생하면 파일을 닫거나 메모리를 해제한 뒤 프로그램을 종료하는 패턴을 주로 사용합니다. 패턴 사용 예제는 'Unit 82 실전 예제: 파일 아카이브 구현하기'를 참조하세요.