티스토리 뷰

프로그래밍

ASP.NET Web API 시작하기

야라바 2016. 12. 7. 15:56


ASP.NET Web API는 닷넷 프레임워크 위에 HTTP 기반의 Web API를 구축하도록 돕는 프레임워크입니다. 사용자 인터페이스와는 직접적인 연관이 없기 때문에 단순히 Web API 서비스 만을 제공할 수도 있고, ASP.NET Web Pages, Web Forms, MVC등과 함께 사용할 수도 있습니다. SPA(Single Page Application) 응용이나 페이지 갱신 없이 동적인 페이지 구성을 원하는 경우 Web API는 반드시 검토 해야하는 기술 요소입니다. 데스크탑의 웹 브라우저를 넘어서 스마트폰이나 태브릿등 다양한 기기를 대상으로 서비스한다면 ASP.NET Web API는 효용성이 더욱 높아질 것입니다. ASP.NET Web API는 클라이언트가 AJAX 프레임워크나 기타 방법을 통해서 요청한 정보를 JSON이나 XML 등의 형태로 내려보내고 개별 클라이언트에서 응답 받은 정보를 적절하게 가공해서 출력하는 형태로 동작합니다.

ASP.NET Web API를 시작하려면 새 프로젝트에서 템플릿으로 Visual C#>웹을 클릭하여 "ASP.NET 웹 응용 프로그램"을 선택하고 프로젝트 이름을 입력하여 프로젝트를 생성하는 것으로 시작합니다.

다음 단계에서 어떤 형태의 ASP.NET 응용을 만들것인지를 선택해야 하는데 템플릿 중에서 "Web API"를 선택합니다. Web API 템플릿을 선택하면 하단에 자동 참조하는 요소들이 있는데 Web API와 함께 MVC가 선택되는 것을 인식할 필요가 있습니다. 앞서 언급한 것처럼 Web API는 다른 요소와 조합 형태로 사용하는데 Web API와 SPA는 Web API 요소와 함께 MVC를 사용합니다. 

ASP.NET 응용의 여러 템플릿은 위의 그림과 같이 프로젝트 생성과 동시에 그대로 실행시켜도 정상 동작할 만큼 모든 요소가 준비되어 있으므로 개발자는 필요한 부분만 수정 및 추가해서 개발하면 됩니다.

상단의 [시작] 아이콘을 클릭하면 위의 그림과 같이 내장 웹서버를 가동시키고 웹 브라우저를 통해서 준비된 응용을 실행시켜 볼 수 있습니다.

상단 "API" 메뉴를 클릭하면 위의 그림과 같이 현재 Web API 기본 템플릿에서 제공하고 있는 API들을 확인할 수 있습니다.

namespace webapi.Controllers
{
    [Authorize]
    [RoutePrefix("api/Account")]
    public class AccountController : ApiController
    {
        private const string LocalLoginProvider = "Local";
        private ApplicationUserManager _userManager;

        public AccountController()
        {
        }

        public AccountController(ApplicationUserManager userManager,
            ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
        {
            UserManager = userManager;
            AccessTokenFormat = accessTokenFormat;
        }

        public ApplicationUserManager UserManager
        {
            get
            {
                return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                _userManager = value;
            }
        }

        public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; private set; }

        // GET api/Account/UserInfo
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("UserInfo")]
        public UserInfoViewModel GetUserInfo()
        {
            ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

            return new UserInfoViewModel
            {
                Email = User.Identity.GetUserName(),
                HasRegistered = externalLogin == null,
                LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
            };
        }

        // POST api/Account/Logout
        [Route("Logout")]
        public IHttpActionResult Logout()
        {
            Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
            return Ok();
        }

위의 코드는 "Controllers" 폴더에 있는 AccountController.cs로 계정관련 API 서비스를 수행하는 부분입니다. 주목할 부분은 RoutePrefix로 기술한 기본 경로와 Route로 기술한 경로로 API 도움말에 나온 API 경로 정보와 부합하고 있고 관련 코드를 그 하단에 기술하고 있음을 참고할 수 있겠습니다.

다음에서 다룰 예제는 웹브라우저에 [이전][다음] 버튼을 배치하고 특정 버튼을 클릭하면 서버에 저장되어 있는 사용자 아이디 리스트를 차례로 조회합니다. 아이디 조회와 동시에 아이디가 숫자로 시작하면 적색 깃발을 숫자로 시작하지 않으면 녹색 깃발을 표시하는 예제 입니다.

앞서 프로젝트 생성 시점에 Web API 연관 자료 뿐만아니라 MVC자료도 참조되었는데 이와 관련하여 위의 그림처럼 M(Models), V(Views), C(Controllers) 요소별로 코드를 추가하거나 수정합니다.

namespace webapi.Models
{
    public class UseridsModel
    {
        public int Idval { get; set; }
        public string Idstr { get; set; }
    }
}

모델(M - Models)은 서버에서 웹 브라우저로 자료를 내려보낼때 사용할 데이터 구조 입니다. 서버에서 C#으로 클래스를 작성하지만 웹브라우저로 결과를 내려보내면 JSON 형태로 전달받은 결과 데이터를 클래스 인스턴스처럼 data.Idval과 같이 사용할 수 있습니다. Models 폴더에 webapi.Models 네임스페이스를 가지는 클래스를 추가합니다.

<script>
    var uri = '/api/Userids';

    function previd() {
        var idx = $('#curidx').val();
        getid(idx - 1);
    }

    function nextid() {
        var idx = $('#curidx').val();
        getid(Number(idx) + 1);
    }

    function getid(getidx) {
        $.getJSON(uri + '/' + getidx)
          .done(function (data) {
              $('#curid').text(data.Idstr);
              $('#curidx').val(data.Idval);
              if (data.Idstr.substr(0,1).match(/^[0-9]+$/) != null)
                  $('#curimg').html("<img src='/Content/flag-red.png' border=0>");
              else
                  $('#curimg').html("<img src='/Content/flag-green.png' border=0>");
          })
          .fail(function (jqXHR, textStatus, err) {
              $('#curid').text('Error: ' + err);
              $('#curidx').val(0);
              $('#curimg').html("");
          });
    }
</script>
<div class="jumbotron">
    <h1>Web API Test</h1>
    <p class="lead">[이전][다음] 버튼을 클릭하면 서버에 저장되어 있는 사용자 아이디 리스트를 차례로 조회합니다.</p>
    <p>아이디가 숫자로 시작하면 적색 깃발을 숫자로 시작하지 않으면 녹색 깃발을 표시합니다.</p>
</div>
<div class="row">
    <div class="col-md-6">
        <h2>현재 아이디 : </h2>
        <p><span id="curid">버튼을 누르세요!</span></p>
        <p id="curimg"></p>
    </div>
    <div class="col-md-6">
        <input type="hidden" name="curidx" id="curidx" value="0" />
        <p><input type="button" value="이전" onclick="previd();" /></p>
        <p><input type="button" value="다음" onclick="nextid();" /></p>
    </div>
</div>

두번째는 V(Views)로 실제 화면에 보여지는 내용을 다룹니다. 웹 인터페이스이므로 화면의 다양한 요소를 기술하는 HTML코드와 버튼 클릭에 따라 서버의 API를 요구하고 그 결과를 처리하는 jQuery 기반으로 자바스크립트로 이루어집니다. 주목할 점은 자바 스크립트에서 서버에 요청하는 API 주소로 위의 예제에서는 /api/Userids/아이디 형식으로 요청합니다. getJSON()은 jQuery 함수로 AJAX HTTP GET형식으로 서버에 요청하고 JSON 형태의 결과를 받습니다. 서버로부터 JSON 형태의 결과를 받기 때문에 웹 브라우저에서도 서버 오브젝트를 다루는 것처럼 편리하게 처리를 수행할 수 있습니다. 결과를 정상적으로 수신하면(done) HTML 각 요소를 참조해서 적절한 위치에 아이디 스트링과 값을 text(), val()로 설정하고 아이디의 첫 문자를 기준으로 숫자/문자를 판단하여 해당하는 이미지를 출력하도록 html()함수로 이미지 태그를 설정하는 작업을 수행합니다. 결과적으로 일반적인 웹 페이지와는 다르게 페이지를 다시 로딩하지 않고 동적으로 정보를 갱신하게 됩니다.

뷰 관련 코드 까지 작성한 상태에서는 버튼 클릭을 통한 API 호출은 정상적으로 수행할 수 없지만 위의 그림과 같이 화면 로딩까지는 정상적으로 동작하는지를 확인할 수 있습니다. 뷰 관련 코드를 작성했으면 솔루션의 Content 폴더에 깃발 표시로 사용할 이미지를 탐색기에서 복사하여 붙여넣기 합니다.

using System.Web.Http;
using webapi.Models;

namespace webapi.Controllers
{
    [RoutePrefix("api/Userids")]
    public class UseridsController : ApiController
    {
        UseridsModel[] ids = new UseridsModel[] {
            new UseridsModel { Idval = 1, Idstr = "admin"},
            new UseridsModel { Idval = 2, Idstr = "user1"},
            new UseridsModel { Idval = 3, Idstr = "123user"},
            new UseridsModel { Idval = 4, Idstr = "guser2"},
            new UseridsModel { Idval = 5, Idstr = "9staff"} };

        public IHttpActionResult Get(int id)
        {
            var idx = id;
            if (idx < 1) idx = 1;
            else if (idx > ids.Length) idx = ids.Length;
            return Ok(ids[idx - 1]); //return NotFound();
        }
    }
}

Web API 구현을 위한 MVC 요소중 마지막은 컨트롤(C - Controllers)입니다.  위의 예제와 같이 webapi.Controllers 네임스페이스를 갖도록 ApiController를 상속하는 컨트롤러 클래스를 작성합니다. RoutePrefix는 자바스크립트에서 getJSON()에 적용했던 URI와 일치하도록 지정합니다. "id"를 파라미터로 하는 Get 메소드를 작성하면 클라이언트의 API 요청에 대응할 수 있습니다. Ok() 함수에 앞서 작성한 모델 클래스의 오브젝트를 넘겨주면 JSON 형태로 결과를 전달하여 자바스크립트에서도 마치 로컬 변수 오브젝트를 활용할 수 있습니다.

[이전][다음] 버튼을 클릭하여 작성한 API를 호출하면 위의 두가지 화면처럼 해당하는 아이디를 조회하면서 아이디에 대한 숫자/문자 결과에 따라 적절한 깃발이 표시되는 것을 확인할 수 있습니다.

이번 예제를 통해서 Web API와 MVC모델을 적절하게 사용하면 여러 페이지를 작성할 필요없이 하나의 웹 페이지 내에서 모든 기능을 수행하는 SPA(Single Page Application) 응용을 효과적으로 개발할 수 있음을 확인할 수 있었습니다. 비주얼스튜디오에서 웹 프로젝트에 필요한 jQuery, Bootstrap등의 유용한 프레임워크를 자동적으로 배치해 주므로 개발자가 부수적인 코딩 노력을 최소화할 수 있는 장점이 있었습니다. ASP.NET Web API와 MVC는 앞으로 더욱 주목할 필요가 있는 요소입니다.


댓글
댓글쓰기 폼