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는 실제 에러 인스턴스를 추출하여 필드와 메서드에 접근할 수 있게 해줍니다. 이를 통해 복잡한 애플리케이션에서 에러 처리를 더욱 정교하고 유익하게 만들 수 있습니다.

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를 통해 래핑된 에러 체인 내에서 커스텀 에러 타입의 특정 필드와 메서드에 액세스하여 정교한 에러 처리 및 분석을 수행하는 방법을 보여줍니다.

직접 해보기

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실력 점검

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

로직 & 흐름의 모든 레슨