errors

package
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package errors 애플리케이션 전용 에러 처리 시스템을 제공합니다.

이 패키지는 표준 errors 패키지를 확장하여 타입 기반 에러 분류와 에러 체이닝을 지원합니다. 모든 에러는 ErrorType으로 분류되며, Wrap 함수를 통해 컨텍스트를 누적할 수 있습니다.

기본 사용법

새 에러 생성:

err := errors.New(errors.NotFound, "사용자를 찾을 수 없습니다")

에러 래핑 (컨텍스트 추가):

if err != nil {
    return errors.Wrap(err, errors.Internal, "데이터베이스 조회 실패")
}

에러 타입 검사:

if errors.Is(err, errors.NotFound) {
    // NotFound 타입 에러 처리
}

에러 체인 탐색:

rootErr := errors.RootCause(err)  // 최상위 원인 에러 반환

ErrorType 선택 가이드

각 ErrorType은 에러의 성격과 원인에 따라 구분됩니다. 적절한 타입을 선택하면 에러 처리 로직을 명확하게 구성할 수 있습니다.

Unknown:

  • 분류할 수 없는 에러 (기본값, 사용 지양)
  • 외부 라이브러리 에러를 AppError로 변환할 수 없을 때

Internal:

  • 애플리케이션 내부 로직 오류 (버그로 간주)
  • nil 포인터 참조, 예상하지 못한 상태, 로직 오류 등
  • 예: "예상치 못한 nil 값", "잘못된 상태 전이"

System:

  • 시스템 또는 인프라 수준의 장애
  • 디스크 I/O, 네트워크, 데이터베이스 연결 등
  • 예: "파일 읽기 실패", "DB 연결 실패"

Unauthorized:

  • 인증 실패 (사용자 신원 확인 실패)
  • 로그인 필요, 토큰 만료, 잘못된 자격증명 등
  • 예: "로그인이 필요합니다", "토큰이 만료되었습니다"

Forbidden:

  • 권한 부족 (인증은 성공했지만 접근 권한 없음)
  • 예: "관리자 권한이 필요합니다", "이 리소스에 접근할 수 없습니다"

InvalidInput:

  • 사용자 입력값 검증 실패
  • 유효성 검사 실패, 잘못된 형식, 필수 값 누락 등
  • 예: "이메일 형식이 올바르지 않습니다", "필수 항목이 누락되었습니다"

Conflict:

  • 리소스 충돌 또는 상태 불일치
  • 중복 생성, 동시성 문제, 버전 충돌 등
  • 예: "이미 존재하는 사용자입니다", "리소스가 이미 수정되었습니다"

NotFound:

  • 요청한 리소스를 찾을 수 없음
  • 예: "사용자를 찾을 수 없습니다", "페이지가 존재하지 않습니다"

ExecutionFailed:

  • 비즈니스 로직 또는 외부 프로세스 실행 실패
  • 웹 스크래핑 실패, 외부 API 호출 실패, 작업 실행 오류 등
  • 예: "페이지 파싱 실패", "외부 API 호출 실패"

ParsingFailed:

  • 데이터 파싱, 변환, 디코딩 실패
  • HTML/JSON 파싱 오류, 잘못된 데이터 포맷 등
  • 예: "HTML 구조 분석 실패", "JSON 디코딩 오류", "날짜 형식 변환 실패"

Timeout:

  • 작업 시간 초과
  • HTTP 요청 타임아웃, 작업 처리 시간 초과 등
  • 예: "요청 시간이 초과되었습니다"

Unavailable:

  • 서비스 일시적 사용 불가
  • 서비스 점검, 과부하, 일시적 장애 등
  • 예: "서비스가 일시적으로 사용 불가능합니다"

Wrap 시 타입 선택 원칙

1. 원인 에러가 AppError인 경우:

  • 컨텍스트만 추가하고 동일한 타입 유지 (일반적)
  • 또는 더 상위 추상화 레벨의 타입으로 변경
  • 예: NotFound를 Wrap하여 Internal로 변경 (드물게 사용)

2. 원인 에러가 외부 라이브러리 에러인 경우:

  • 에러의 성격에 맞는 적절한 타입 선택
  • 예: sql.ErrNoRows → NotFound
  • 예: context.DeadlineExceeded → Timeout
  • 예: net.Error → System
  • 예: json.UnmarshalError → InvalidInput

3. 타입 선택이 애매한 경우:

  • 에러가 발생한 계층(layer)을 고려
  • 사용자 입력 계층: InvalidInput
  • 비즈니스 로직 계층: ExecutionFailed, Conflict 등
  • 인프라 계층: System, Timeout, Unavailable

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func As

func As(err error, target any) bool

As 에러 체인에서 특정 타입의 에러를 찾아 대상 변수에 할당합니다.

func Is

func Is(err error, errType ErrorType) bool

Is 에러 체인에 특정 ErrorType이 포함되어 있는지 확인합니다.

Example
err := New(Timeout, "request timed out")
err = Wrap(err, Unavailable, "retry failed")

if Is(err, Timeout) {
	fmt.Println("Caught timeout error")
}
Output:

Caught timeout error

func New

func New(errType ErrorType, message string) error

New 새로운 에러를 생성합니다.

Example
err := New(NotFound, "user 123 not found")
fmt.Println(err)
Output:

[NotFound] user 123 not found

func Newf

func Newf(errType ErrorType, format string, args ...any) error

Newf 포맷 문자열을 사용하여 새로운 에러를 생성합니다.

func RootCause

func RootCause(err error) error

RootCause 에러가 발생한 가장 근본적인 원인 에러를 찾습니다.

func Wrap

func Wrap(err error, errType ErrorType, message string) error

Wrap 기존 에러를 감싸서 새로운 에러를 생성합니다.

Example
// Original error from lower layer
cause := New(ExecutionFailed, "db connection lost")

// Wrap with context in upper layer
err := Wrap(cause, System, "health check failed")

fmt.Printf("%s", err)
Output:

[System] health check failed: [ExecutionFailed] db connection lost

func Wrapf

func Wrapf(err error, errType ErrorType, format string, args ...any) error

Wrapf 포맷 문자열을 사용하여 기존 에러를 감쌉니다.

Types

type AppError

type AppError struct {
	// contains filtered or unexported fields
}

AppError 애플리케이션에서 발생하는 모든 에러를 표준화하여 표현하는 구조체입니다.

func (*AppError) Error

func (e *AppError) Error() string

Error 표준 errors.Error 인터페이스를 구현합니다.

func (*AppError) Format

func (e *AppError) Format(s fmt.State, verb rune)

Format fmt.Formatter 인터페이스를 구현합니다. %+v 사용 시 에러 체인과 스택 트레이스를 상세히 출력합니다.

func (*AppError) Message

func (e *AppError) Message() string

Message 에러 메시지를 반환합니다.

func (*AppError) Stack

func (e *AppError) Stack() []StackFrame

Stack 스택 트레이스를 반환합니다.

func (*AppError) Type

func (e *AppError) Type() ErrorType

Type 에러의 타입을 반환합니다.

func (*AppError) Unwrap

func (e *AppError) Unwrap() error

Unwrap 표준 errors.Unwrap 인터페이스를 구현합니다.

type ErrorType

type ErrorType int

ErrorType 에러의 종류를 나타내는 타입입니다.

const (
	// Unknown 알 수 없는 에러
	Unknown ErrorType = iota

	// Internal 내부 로직 오류 (버그 등)
	Internal

	// System 시스템 또는 인프라 오류 (디스크, 네트워크 등)
	System

	// Unauthorized 인증 실패 (로그인 필요, 토큰 만료 등)
	Unauthorized

	// Forbidden 권한 없음 (접근 권한 부족)
	Forbidden

	// InvalidInput 잘못된 입력값 (유효성 검사 실패)
	InvalidInput

	// Conflict 리소스 충돌 (중복 생성 등)
	Conflict

	// NotFound 리소스를 찾을 수 없음
	NotFound

	// ExecutionFailed 비즈니스 로직 수행 실패 (외부 프로세스 오류 등)
	ExecutionFailed

	// ParsingFailed 데이터 파싱 또는 형식 변환 실패
	ParsingFailed

	// Timeout 작업 시간 초과
	Timeout

	// Unavailable 서비스 일시적 사용 불가
	Unavailable
)

에러 타입 상수

func UnderlyingType

func UnderlyingType(err error) ErrorType

UnderlyingType 에러 체인에서 가장 안쪽에 있는 AppError의 ErrorType을 반환합니다.

이 함수는 여러 겹으로 래핑된 에러의 근본적인(underlying) 타입을 찾습니다. 에러 체인 전체를 순회하면서 가장 안쪽(Root에 가까운)에 위치한 AppError를 찾아 그 타입을 반환합니다. 외부 라이브러리 에러(sql.ErrNoRows, context.DeadlineExceeded 등)를 AppError로 래핑한 경우에도 의도한 ErrorType을 올바르게 반환합니다.

주요 사용 사례:

  • HTTP 응답 코드 결정 시 에러의 근본 성격 파악
  • 로깅 레벨 결정 시 에러의 본질적 타입 확인
  • 여러 단계로 래핑된 에러의 원래 분류 확인

반환값:

  • 체인에 AppError가 하나라도 존재하는 경우: 가장 안쪽 AppError의 ErrorType
  • 체인에 AppError가 없거나 err이 nil인 경우: Unknown

사용 예시:

// 예시 1: AppError 체인
err := Wrap(New(NotFound, "user not found"), Internal, "query failed")
underlyingType := UnderlyingType(err)  // NotFound 반환

// 예시 2: 외부 에러 래핑
err := Wrap(sql.ErrNoRows, NotFound, "user not found")
underlyingType := UnderlyingType(err)  // NotFound 반환 (외부 에러도 올바르게 분류)
Example
// Scenario: Standard library error wrapped in AppError
stdErr := io.EOF
err := Wrap(stdErr, InvalidInput, "unexpected end of stream")

// Even though the root cause is io.EOF (unknown type),
// UnderlyingType returns the deepest AppError's type.
fmt.Println(UnderlyingType(err))
Output:

InvalidInput

func (ErrorType) String

func (i ErrorType) String() string

type StackFrame

type StackFrame struct {
	File     string // 파일 이름
	Line     int    // 줄 번호
	Function string // 함수 이름
}

StackFrame 단일 함수 호출 스택의 실행 컨텍스트 정보를 캡슐화한 구조체입니다.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL