recover 사용하기
Coddy GO 여정의 로직 & 흐름 섹션에 포함된 레슨 — 68개 중 43번째.
panic이 프로그램을 즉시 중단시키지만, Go는 recover 함수를 통해 제어권을 다시 얻는 방법을 제공합니다. recover 함수를 사용하면 패닉을 포착하고 이를 정상적으로 처리하여 전체 프로그램이 충돌하는 것을 방지할 수 있습니다.
하지만 recover에는 매우 구체적인 요구 사항이 있습니다. 이는 지연된(deferred) 함수 내부에서만 사용할 수 있습니다. 패닉(panic)이 발생하면 Go는 프로그램이 종료되기 전에 모든 지연된 함수를 실행하여 recover가 패닉을 가로챌 수 있는 기회를 제공합니다:
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}recover 함수는 panic에 전달된 값을 반환하거나, 패닉이 발생하지 않은 경우 nil을 반환합니다. 이를 통해 패닉 발생 여부를 확인하고 에러 로깅이나 정리 작업 수행과 같은 적절한 조치를 취할 수 있습니다.
panic과 마찬가지로, recover는 Go에서 드물게 사용되어야 합니다. 이는 단일 요청의 패닉이 전체 서버를 중단시키는 것을 방지하고, 서버가 다른 요청을 계속 처리할 수 있도록 하려는 웹 서버와 같은 시나리오에서 가장 흔히 볼 수 있습니다.
챌린지
쉬움recover를 사용하여 패닉을 우아하게 처리하고 전체 서버가 중단되는 것을 방지하는 웹 서버 요청 핸들러를 구축하세요. 이 챌린지는 패닉을 포착하고 서버 안정성을 유지하기 위해 지연된 함수(deferred function) 내에서 recover를 사용하는 방법을 보여줍니다.
두 개의 입력을 받게 됩니다:
"endpoint,method,action"형식의 요청 세부 정보가 포함된 문자열 (예:"/api/users,GET,process")"server_name,max_requests"형식의 서버 설정이 포함된 문자열 (예:"WebServer,100")
수행할 작업은 다음과 같습니다:
- 첫 번째 입력을 쉼표로 분리하여 endpoint, method, action을 파싱합니다.
- 두 번째 입력을 쉼표로 분리하여 server name과 max requests를 파싱합니다.
- max requests 문자열을 정수로 변환합니다.
- endpoint, method, action, server name을 매개변수로 받는
handleRequest함수를 생성합니다. handleRequest내부에recover를 사용하여 패닉을 포착하는 지연된 함수(deferred function)를 추가합니다:- 패닉이 복구되면(recover가 non-nil을 반환하면), 다음을 출력합니다:
"Server [server_name] recovered from panic: [panic_value]" - 패닉을 처리한 후, 다음을 출력합니다:
"Request handling completed safely"
- 패닉이 복구되면(recover가 non-nil을 반환하면), 다음을 출력합니다:
- 지연된 함수 다음에 action에 따라 요청 처리를 시뮬레이션합니다:
- action이
"process"인 경우:"Processing [method] request to [endpoint]"를 출력합니다. - action이
"panic_nil"인 경우:"Attempting dangerous operation"을 출력한 다음panic("nil pointer access")를 호출합니다. - action이
"panic_overflow"인 경우:"Attempting resource allocation"을 출력한 다음panic("memory overflow")를 호출합니다. - action이
"panic_timeout"인 경우:"Attempting database connection"을 출력한 다음panic("connection timeout")를 호출합니다. - 그 외의 action인 경우:
"Unknown action: [action]"을 출력한 다음panic("invalid action")을 호출합니다.
- action이
- main 함수에서 서버 시작 메시지를 출력합니다:
"Starting [server_name] with max [max_requests] requests" - 파싱된 매개변수를 사용하여
handleRequest함수를 호출합니다. - 함수 호출 후, 서버 상태를 출력합니다:
"Server [server_name] is still running" - 마지막으로 요약을 출력합니다:
"Server Summary:""Name: [server_name]""Max Requests: [max_requests]""Last Request: [method] [endpoint]""Action Performed: [action]""Status: Operational"
입력 문자열을 쉼표로 분리하려면 strings 패키지를 사용하고, max requests 문자열을 정수로 변환하려면 strconv 패키지를 사용하세요. 이 챌린지는 recover를 통해 서버가 예기치 않은 패닉을 우아하게 처리하여 개별 요청의 실패가 전체 시스템을 중단시키지 않도록 하는 방법을 보여줍니다.
직접 해보기
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// 입력 읽기
var requestDetails string
var serverConfig string
fmt.Scanln(&requestDetails)
fmt.Scanln(&serverConfig)
// 요청 세부 정보 파싱
requestParts := strings.Split(requestDetails, ",")
endpoint := requestParts[0]
method := requestParts[1]
action := requestParts[2]
// 서버 구성 파싱
configParts := strings.Split(serverConfig, ",")
serverName := configParts[0]
maxRequests, _ := strconv.Atoi(configParts[1])
// TODO: 아래에 코드를 작성하세요
// 복구 메커니즘을 포함한 handleRequest 함수 생성
// 서버 시작 메시지 출력
// handleRequest 함수 호출
// 서버 상태 및 요약 출력
}이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
로직 & 흐름의 모든 레슨
7에러 처리 심화
사용자 정의 에러 타입%w를 사용한 에러 래핑errors.Is를 사용한 언래핑errors.As를 사용한 언래핑panic 이해하기recover 사용하기요약 - 안전한 나눗셈