Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# ASP.NET WebAPI에서 URI 기반으로 Web API 버전 관리 구현하기

Web API 버전 관리가 필요한 이유

Web API 서비스가 한 번 공개되면 다양한 클라이언트 애플리케이션이 해당 서비스를 사용하기 시작합니다. 비즈니스가 성장하고 요구 사항이 변화함에 따라 서비스도 변경해야 할 때가 있습니다. 하지만 이러한 변경은 기존 클라이언트 애플리케이션을 깨뜨리지 않는 방식으로 이루어져야 합니다.

바로 이 지점에서 Web API 버전 관리(Versioning)가 중요한 역할을 합니다. 기존 서비스는 그대로 유지하여 기존 클라이언트에 영향을 주지 않고, 새로운 클라이언트가 사용할 수 있는 새 버전의 서비스를 별도로 개발하는 것입니다.

버전 관리를 구현하는 여러 방법 중 하나가 바로 URI를 활용하는 방식입니다. URL 경로 자체에 버전 정보를 포함시키는 것으로, 가장 직관적이고 널리 사용되는 방법입니다. 아래에서 실제 구현 예제를 살펴보겠습니다.

V1(Student) 컨트롤러 구현

먼저 다음과 같은 액션 메서드를 가진 버전 1(V1)의 학생(Student) 컨트롤러가 있다고 가정해 보겠습니다.

Student 모델 V1

namespace DemoWebApplication.Models{
    public class StudentV1{
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

Student 컨트롤러 V1

using DemoWebApplication.Models;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace DemoWebApplication.Controllers{
    public class StudentV1Controller : ApiController{
        List<StudentV1> students = new List<StudentV1>{
            new StudentV1{
                Id = 1,
                Name = "Mark"
            },
            new StudentV1{
                Id = 2,
                Name = "John"
            }
        };
        [Route("api/v1/students")]
        public IEnumerable<StudentV1> Get(){
            return students;
        }
        [Route("api/v1/students/{id}")]
        public StudentV1 Get(int id){
            var studentForId = students.FirstOrDefault(x => x.Id == id);
            return studentForId;
        }
    }
}

위 예제에서는 어트리뷰트 라우팅(Attribute Routing)을 사용하여 버전 관리를 구현했습니다. 라우트 경로에 api/v1/students처럼 버전 번호(v1)를 명시적으로 포함시킨 것이 핵심입니다.

V2(Student) 컨트롤러 추가

이제 비즈니스 요구 사항에 따라 학생 컨트롤러에 새로운 변경 사항이 제안되었지만, 이 변경은 신규 사용자에게만 적용되고 기존 사용자는 계속 버전 1을 사용해야 한다고 가정해 보겠습니다. 이 경우 버전 2(V2)를 도입해야 합니다.

예를 들어 V2에서는 기존의 단일 Name 필드를 FirstNameLastName 두 필드로 분리했다고 해보겠습니다.

Student 모델 V2

namespace DemoWebApplication.Models{
    public class StudentV2{
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

Student 컨트롤러 V2

using DemoWebApplication.Models;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace DemoWebApplication.Controllers{
    public class StudentV2Controller : ApiController{
        List<StudentV2> students = new List<StudentV2>{
            new StudentV2{
                Id = 1,
                FirstName = "Roger",
                LastName = "Federer"
            },
            new StudentV2{
                Id = 2,
                FirstName = "Tom",
                LastName = "Bruce"
            }
        };
        [Route("api/v2/students")]
        public IEnumerable<StudentV2> Get(){
            return students;
        }
        [Route("api/v2/students/{id}")]
        public StudentV2 Get(int id){
            var studentForId = students.FirstOrDefault(x => x.Id == id);
            return studentForId;
        }
    }
}

실행 결과

이렇게 구성하면 /api/v1/students로 요청하는 기존 클라이언트는 여전히 Name 필드 하나만 포함된 응답을 받고, /api/v2/students로 요청하는 신규 클라이언트는 FirstNameLastName이 분리된 새로운 형식의 응답을 받게 됩니다.

  • V1 요청: GET /api/v1/students → 기존 모델(Id, Name) 반환
  • V2 요청: GET /api/v2/students → 새 모델(Id, FirstName, LastName) 반환

이처럼 URI 기반 버전 관리를 사용하면 URL 경로만으로 어떤 버전의 API를 호출할지 명확하게 구분할 수 있으며, 각 버전별로 독립적인 컨트롤러와 모델을 유지함으로써 기존 클라이언트와의 하위 호환성을 안전하게 보장할 수 있습니다.