Menu
Coddy logo textTech

errors.As를 사용한 언래핑

Coddy GO 여정의 로직 & 흐름 섹션에 포함된 레슨 — 68개 중 41번째.

errors.Is가 체인에서 특정 에러 값을 식별하는 데 도움을 주지만, 때로는 사용자 정의 에러 타입의 실제 필드와 데이터에 접근해야 할 때가 있습니다. errors.As 함수는 체인에서 특정 타입과 일치하는 첫 번째 에러를 찾아 검사를 위해 이를 추출함으로써 이 기능을 제공합니다.

errors.As 함수는 두 개의 매개변수를 받습니다: 검사할 에러와 대상 에러 타입의 변수에 대한 포인터입니다. 만약 에러 체인에서 일치하는 에러 타입을 찾으면, 해당 변수에 그 에러를 설정하고 true를 반환합니다:

var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
    fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}

이는 추가적인 컨텍스트를 포함하는 사용자 정의 에러 타입을 다룰 때 특히 강력합니다. 단순히 일치 여부만 확인하는 errors.Is와 달리, errors.As는 실제 에러 인스턴스를 추출하여 필드와 메서드에 접근할 수 있게 해줍니다. 이를 통해 복잡한 애플리케이션에서 에러 처리를 더욱 정교하고 유익하게 만들 수 있습니다.

quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

challenge icon

챌린지

쉬움

래핑된 에러 체인에서 커스텀 에러 타입을 추출하고 검사하기 위해 errors.As를 사용하는 API 에러 처리 시스템을 구축하세요. 이 챌린지는 추가적인 컨텍스트와 함께 래핑된 경우에도 errors.As를 사용하여 특정 커스텀 에러 타입의 필드와 데이터에 액세스하는 방법을 보여줍니다.

두 개의 입력을 받게 됩니다:

  • "endpoint,method,error_code,error_field" 형식의 API 요청 세부 정보가 포함된 문자열 (예: "/users,POST,400,email")
  • "service_name,request_id" 형식의 시스템 컨텍스트가 포함된 문자열 (예: "UserAPI,req_12345")

여러분의 과제는 다음과 같습니다:

  1. 세 개의 필드를 가진 APIError 구조체라는 커스텀 에러 타입을 생성하세요:
    • Code (int) - HTTP 상태 코드
    • Field (string) - 에러를 발생시킨 필드
    • Message (string) - 에러에 대한 설명
  2. "API error [code]: [message] (field: [field])"를 반환하는 APIErrorError() string 메서드를 구현하세요.
  3. 첫 번째 입력을 쉼표로 분리하여 endpoint, method, error code, error field를 파싱하세요.
  4. 두 번째 입력을 쉼표로 분리하여 service name과 request ID를 파싱하세요.
  5. 에러 코드 문자열을 정수로 변환하세요.
  6. 에러 코드를 기반으로 APIError 인스턴스를 생성하세요:
    • 코드가 400인 경우: 메시지 "invalid request data"
    • 코드가 401인 경우: 메시지 "authentication required"
    • 코드가 404인 경우: 메시지 "resource not found"
    • 코드가 500인 경우: 메시지 "internal server error"
    • 그 외의 코드: 메시지 "unknown error"
  7. fmt.Errorf%w를 사용하여 엔드포인트 레벨의 래핑된 에러를 생성하세요: "[method] [endpoint] failed: %w"
  8. 서비스 레벨의 래핑된 에러를 생성하세요: "[service_name] request [request_id] failed: %w"
  9. 래핑된 에러 체인에서 APIError를 추출하기 위해 errors.As를 사용하고 추출 결과를 표시하세요:
    • 추출에 성공한 경우: "API error extracted successfully"
    • 추출에 실패한 경우: "Failed to extract API error"
  10. 추출에 성공했다면, 추출된 에러 세부 정보를 표시하세요:
    • "Extracted Error Details:"
    • "Code: [code]"
    • "Field: [field]"
    • "Message: [message]"
    • "Full error: [full_error_message_from_Error_method]"
  11. 전체 에러 체인을 표시하세요:
    • "Error Chain:"
    • "Original: [original_api_error_message]"
    • "Endpoint level: [endpoint_level_error_message]"
    • "Service level: [service_level_error_message]"
  12. 최종 분석을 표시하세요:
    • "Error Analysis:"
    • "Service: [service_name]"
    • "Request ID: [request_id]"
    • "Endpoint: [method] [endpoint]"
    • "HTTP Status: [code]"
    • "Problem Field: [field]"
    • "Error Category: [error_category]" (여기서 error_category는 코드가 400-499인 경우 "Client Error", 500-599인 경우 "Server Error", 그 외의 코드는 "Unknown"입니다)

입력 문자열을 쉼표로 분리하기 위해 strings 패키지를, 에러 코드 문자열을 정수로 변환하기 위해 strconv 패키지를, errors.As를 위해 errors 패키지를, 그리고 에러 래핑을 위해 fmt 패키지를 사용하세요. 이 챌린지는 errors.As를 통해 래핑된 에러 체인 내에서 커스텀 에러 타입의 특정 필드와 메서드에 액세스하여 정교한 에러 처리 및 분석을 수행하는 방법을 보여줍니다.

치트 시트

errors.As 함수는 에러 체인에서 특정 에러 타입을 추출하여, 사용자 정의 에러 필드와 메서드에 접근할 수 있게 해줍니다.

errors.As는 검사할 에러와 대상 에러 타입의 변수에 대한 포인터라는 두 개의 매개변수를 받습니다:

var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
    fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}

단순히 일치 여부만 확인하는 errors.Is와 달리, errors.As는 실제 에러 인스턴스를 추출하여 더 정교한 에러 처리를 위해 해당 필드와 메서드에 접근할 수 있도록 합니다.

직접 해보기

package main

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

func main() {
	// 입력 읽기
	var apiDetails string
	var systemContext string
	fmt.Scanln(&apiDetails)
	fmt.Scanln(&systemContext)
	
	// 입력 파싱
	apiParts := strings.Split(apiDetails, ",")
	endpoint := apiParts[0]
	method := apiParts[1]
	errorCodeStr := apiParts[2]
	errorField := apiParts[3]
	
	contextParts := strings.Split(systemContext, ",")
	serviceName := contextParts[0]
	requestID := contextParts[1]
	
	// 에러 코드를 정수로 변환
	errorCode, _ := strconv.Atoi(errorCodeStr)
	
	// TODO: 아래에 코드를 작성하세요
	// 1. Code, Field, Message 필드를 가진 APIError 구조체 생성
	// 2. APIError를 위한 Error() 메서드 구현
	// 3. 에러 코드를 기반으로 APIError 인스턴스 생성
	// 4. 래핑된 에러 생성 (엔드포인트 레벨 및 서비스 레벨)
	// 5. errors.As를 사용하여 래핑된 에러 체인에서 APIError 추출
	// 6. 추출 결과 및 에러 상세 정보 표시
	// 7. 에러 체인 및 최종 분석 표시
	
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

로직 & 흐름의 모든 레슨