-
728x90
서론
여러 프로젝트를 하며, 여러 서버개발자들과 작업을 하면 모두다 다른 응답타입을 전송한다. 그에 따라 프론트는 에러를 핸들링하는 방식도 달라지고, 디버깅하는 과정도 달라진다. 예를들어 form을 제출하는 과정에서 에러가 발생했을때, 잘못된 form 형식입니다. 를 반환 할 수도있고, xx필드의 형식이 올바르지 않습니다. 를 응답할 수 있다. 그리고 프론트는 이 응답을 유저의 입력값을 받을 떄부터 관리할지, 제출직전에 확인할지, 서버의 응답을 받고 확인할지로 갈라지고 또 이후에 에러메시지를 어떻게 띄울지로 나누어지는 경우의 수에 마주하게 된다. 약속은 있지만 정답은 없다. 프로젝트의 방향과 선택의 기준에 맞는 에러타입을 설계하는 것이 중요하다. 프로젝트가 장기적인지 단기적인지, 프로젝트가 실행되는 곳이 어느 환경인지 등등 다양한 근거가 필요해진다.
RFC가 무엇인가요
RFC(Request for Comments)는 인터넷 기술 표준을 정의하는 공식 문서 시리즈이다. 직역하면 "의견을 구하는 요청서" 정도가 된다. 1969년부터 시작된 이 문서들은 인터넷이 어떻게 작동해야 하는지에 대한 세세한 규칙들을 담고 있다.
RFC를 만드는 과정은 민주적이다. 누군가 "이런 방식으로 하면 어떨까?"라고 제안하면, 전 세계 개발자들과 연구자들이 토론하고 검토한다. 좋은 아이디어라고 판단되면 공식 표준이 되어 RFC 번호를 받게 되고 이렇게 발행된 RFC는 절대 바뀌지 않습니다. 수정이 필요하면 새로운 RFC를 만드는 방식이다. 그리고 1969년부터 시작되어 현재까지 약 9,000개가 넘는 RFC가 발행되었다. 그리고 이글의 핵심 주제인 RFC7807은 그 순서이다.
우리가 아는 유명한 RFC들
- RFC 2616: HTTP/1.1 (웹의 기반)
- RFC 7231: HTTP/1.1 Semantics (HTTP 메소드, 상태코드)
- RFC 6749: OAuth 2.0 (인증/인가)
- RFC 7519: JSON Web Token (JWT)
불편해지기
// 개발자 A의 에러 응답 {"error": "validation failed"} // 개발자 B의 에러 응답 {"message": "Invalid input", "code": 400} // 개발자 C의 에러 응답 {"errors": [{"field": "email", "msg": "wrong format"}]}
(이 서로다른 극단적인 에러응답타입이 한 프로젝트 내에 있는 경우는 없다.) 그러나 만약 같은 프로젝트 내에 존재하거나 혹은 응답타입이 약간씩 다르다면 관리하는 차원에선 코드의 전체가 바뀌는 것 같다. 에러파싱로직을 어떻게 설계할지, 사용자의 form값에서 무엇이 잘못되었는지, 에러메시지 상수를 어떻게 관리할지 등등이 있다. 만약 이를 불편하게 여겨, 개발 기간 중 에러타입을 수정하게 된다 하더라도, 기존 개발 유지보수 및 버그 증가 예상의 압박을 마주하게 될 것이다.
RFC 7807의 핵심필드
RFC 7807은 2016년 3월에 발행된 "Problem Details for HTTP APIs" 표준이다.
{ "type": "https://example.com/probs/out-of-credit", "title": "You do not have enough credit.", "detail": "Your current balance is 30, but that costs 50.", "instance": "/account/12345/msgs/abc", "status": 403 }
이 5가지의 핵심 필드들의 설명은 다음과 같다.
type 필드: 에러의 정체성
type 필드는 에러의 "DNA"와 같다. URI 형태로 작성되며, 기계가 읽을 수 있는 고유 식별자 역할을 한다.
{ "type": "https://api.company.com/problems/validation/invalid-email", "type": "https://api.company.com/problems/auth/token-expired", "type": "https://api.company.com/problems/payment/insufficient-funds" }
프론트엔드에서는 이 type을 기준으로 에러 처리 로직을 분기할 수 있다:
// 깔끔하고 명확한 에러 처리 switch (error.type) { case 'https://api.company.com/problems/validation/invalid-email': showEmailFormatError(); break; case 'https://api.company.com/problems/auth/token-expired': refreshTokenAndRetry(); break; case 'https://api.company.com/problems/payment/insufficient-funds': redirectToPaymentPage(); break; }
title과 detail: 사람을 위한 정보
title은 에러의 한 줄 요약, detail은 구체적인 상황 설명이다.
{ "title": "Email Validation Failed", "detail": "The email address 'user@invalid' is missing a valid domain. Please use format like 'user@example.com'" }
이 구조를 통해 개발자는 디버깅할 때 detail을 보고, 사용자에게는 title을 기반으로 친화적인 메시지를 만들 수 있다.
instance: 문제의 정확한 위치
instance는 에러가 발생한 구체적인 API 엔드포인트나 리소스를 가리킨다.
{ "instance": "/users/12345/profile/update", "instance": "/orders/abc123/payment", "instance": "/api/v2/auth/login" }
이를 통해 같은 에러 타입이라도 어디서 발생했는지 정확히 추적할 수 있다.
표로 정리하면 다음과 같다.
필드 목적 type 에러 유형 식별 (URI) title 사람이 읽을 수 있는 짧은 제목 detail 구체적인 에러 설명 instance 에러가 발생한 구체적 위치 status HTTP 상태 코드 필드 확장은 자유
프로젝트 상황에 맞게 추가적으로 필요한 필드들 을 추가할 수 도있고 커스텀도 가능하게 된다.
맺는말
RFC 7807은 API 에러 응답에서 겪었던 혼돈에 질서를 가져다주는 하나의 선택지이다. 개발자마다 다양하게 만들어내던 에러 형식 대신, 전 세계가 합의한 표준화된 구조를 제공한다. type으로 에러를 명확히 분류하고, title과 detail로 사람이 이해하기 쉬운 정보를 제공하며, instance로 정확한 발생 위치를 추적할 수 있게 해준다.
하지만 RFC 7807도 만능 해결책은 아니다. 여전히 약속은 있지만 정답은 없다는 원칙이 적용된다. 빠른 MVP 개발에서는 과도한 표준화가 오히려 부담이 될 수 있고, 레거시 시스템과의 호환성을 고려해야 하는 경우도 있다. 팀의 역량, 프로젝트의 규모와 성격, 클라이언트의 다양성 등을 종합적으로 고려해서 적절한 수준의 표준화를 도입하는 것이 현명할 것 같다. 중요한 것은 RFC 7807을 초기부터 인식하는 것이다. 단순하게 시작하되 확장 가능한 구조로 설계하고, 프로젝트가 성장하면서 점진적으로 표준화를 적용해나가는 것이 좋아보인다.
728x90