에러 무시하다가 큰일난다 - 실전에서 통하는 GORM 디버깅 & 예외 처리 전략
✅ 목차
GORM 에러 핸들링의 기본 구조
RowsAffected로 실패 원인 파악하기
특정 에러 구분하기 (errors.Is, errors.As)
로그 레벨 조절로 SQL 추적하기
실전 예제: 유저 존재 확인 후 조건부 저장
디버깅 꿀팁 & 실수 피하기
1. GORM 에러 핸들링 기본 구조
GORM의 대부분 메서드는 .Error 필드에 에러를 담는다.
user := User{}
err := db.First(&user, 1).Error
if err != nil {
// 에러 처리
}
하지만 이렇게만 쓰면 에러 원인을 정확히 알기 어렵다.
2. RowsAffected로 레코드 유무 판단하기
쿼리는 성공했지만 데이터가 없을 때는 에러가 없고 RowsAffected만 0일 수 있다.
result := db.First(&user, 9999)
if result.Error != nil {
log.Println("DB error:", result.Error)
} else if result.RowsAffected == 0 {
log.Println("데이터 없음")
}
✔ Find는 에러 없이 RowsAffected만 0으로 반환함
var users []User
db.Where("age > ?", 100).Find(&users)
// 에러 없음 but users는 비어 있을 수 있음!
3. 에러 타입 분기처리 — errors.Is, errors.As
Go 1.13+에서는 에러를 구체적으로 분기할 수 있다.
❗ record not found 처리
if errors.Is(err, gorm.ErrRecordNotFound) {
log.Println("유저를 찾을 수 없습니다")
}
📌 사용자 정의 에러와의 조합도 가능
var myErr *MyCustomError
if errors.As(err, &myErr) {
log.Println("내가 정의한 에러 발생:", myErr.Code)
}
4. GORM 로그 레벨 설정하기 (쿼리 추적)
GORM은 자체 로거를 통해 실행된 SQL, 에러, 슬로우 쿼리 등을 추적할 수 있다.
import (
"gorm.io/gorm/logger"
"time"
)
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
로그 레벨 종류
- logger.Silent: 출력 안 함
- logger.Error: 에러만 출력
- logger.Warn: 경고 이상 출력
- logger.Info: 쿼리 전부 출력 (개발 시 추천)
슬로우 쿼리 추적
logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Second,
LogLevel: logger.Warn,
Colorful: true,
},
)
5. 실전 예제: 유저 있으면 업데이트, 없으면 에러
user := User{}
err := db.First(&user, "email = ?", "hi@openai.com").Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("유저가 존재하지 않습니다")
}
user.Name = "Updated Name"
if err := db.Save(&user).Error; err != nil {
return fmt.Errorf("업데이트 실패: %w", err)
}
→ 에러와 없는 케이스를 명확히 구분!
6. 디버깅 & 에러 핸들링 꿀팁 요약
상황 | 대응 방법 |
데이터 없음 | RowsAffected == 0 또는 gorm.ErrRecordNotFound |
쿼리 디버깅 | logger.Info 레벨 설정 |
슬로우 쿼리 추적 | SlowThreshold 설정 |
GORM 에러 커스터마이징 | errors.Is, errors.As 사용 |
다중 조건 복잡 로직 분기 처리 | err != nil 체크 후 로깅 or 래핑 (fmt.Errorf) |
🔚 마무리
GORM은 무조건 if err != nil만 반복하면 에러 흐름 파악이 어렵다.
RowsAffected, 에러 타입 분기, SQL 추적 설정만 잘 써도
디버깅 속도와 코드 안정성은 압도적으로 향상된다.
'개발 > Go' 카테고리의 다른 글
[Gin] GORM에서 CQRS 아키텍처 구현해보기 (85) | 2025.06.18 |
---|---|
[Gin] GORM + Redis 캐싱 전략 - DB 부하 줄이는 실전 캐싱 (75) | 2025.06.16 |
[Gin] GORM으로 단위 테스트 잘하는 법 - 테스트 환경 구성부터 Mock까지 (70) | 2025.06.11 |
[Gin] GORM에서 안전한 쿼리 작성법 - SQL 인젝션 방지와 Named Parameter 전략 (69) | 2025.06.09 |
[Gin] GORM 마이그레이션 전략 - 자동 vs 수동 관리, 안전하게 스키마 관리하기 (35) | 2025.06.06 |