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 실전 예제: 파일 아카이브 구현하기'를 참조하세요.