센로그

5. Model Binding (+Validation) 본문

게임/ASP.NET Core

5. Model Binding (+Validation)

seeyoun 2024. 4. 15. 23:14

◆ Model Binding

MVC에서 M, 즉 데이터 모델에 관해 알아볼 것임.

 

 

데이터 모델도 종류가 다양함.

  • Binding Model
    • 클라에서 보낸 Request를 파싱하기 위한 데이터 모델
    • 유효성 검증 필수
  • Application Model
    • 서버의 각종 서비스들이 사용하는 데이터 모델
    • ex) 랭킹 서비스라면 랭킹 데이터같이 서비스쪽으로 넘길 데이터가 필요할 것
  • View Model
    • 뷰, 즉 Response UI를 만들기 위한 데이터 모델
  • API Model
    • WebAPI Controller에서 JSON/XML 포맷으로 응답할 때 필요한 데이터 모델

 

 

오늘은 그중  Binding Model에 대해 알아볼 것.

 


MVC - 요청 및 처리 순서

MVC 로 설계된 웹에서, 일반적인 요청 처리 순서는 다음과 같다. (feat. 바인딩 모델)

  1. HTTP Request이 온다
  2. Routing에 의해 Controller 및 Action이 결정된다
  3. Model Binding으로 Request에 있는 데이터를 파싱 및 유효성 검증
  4. 파싱된 데이터를 담당 서비스로 전달 (Application Model)
  5. 담당 서비스가 처리한 결과물을 다시 Action에 돌려주면
  6. Action에서 View로 전달 (View Model)
  7. View에서 HTLM 생성
  8. Response로 HTML 결과물을 전송

 


Model Binding이란?

액션 함수를 만들 때, 파라미터 없이 만들 수도 있지만, (처리할 내용이나 요청에 관련된) 파라미터가 있을 수도 있음!!

이 경우, 파라미터를 누가 만들어서 넘겨주냐? 에 관한 내용이 Model Binding임.

 

Model Binding을 이용할 때는 다음 세 가지가 순차적으로 적용된다.

  1. Form Values
    • Request의 Body에서 보낸 값.
    • HTTP POST 방식의 요청이 왔을 때 사용하는 방법
      • POST 방식은 Body에다 숨겨서 전송하기 때문에 GET 보다 안전함
  2. Routes Values
    • 라우트할 때 넘겨받은 값.
    • URL을 통해 전달된 값 또는 라우트 파라미터의 기본값
  3. Query String Values
    • URL 끝에 데이터를 붙이는 방법을 통해 받은 값
      • ?name=seeyoun 이런 식으로 url 끝에 물음표 넣고 데이터 넣어서 전달된 경우.
    • HTTP GET 방식의 요청이 왔을 때 사용하는 방법

 


우선 가장 간단한 방법(Query String Values)으로 데이터가 잘 전달되는지 테스트해보자.

 

컨트롤러에 다음과같은 액션 함수를 만든다.

public IActionResult Test(int id, string value)
{
    return null;
}

 

 

PostMan으로 다음과 같이 GET 요청을 하면!!

 

 

이러케 value가 쏙 들어감. (id는 라우팅 패턴에서 설정해놓은 값임)

 

이렇듯, 일일이 URL에서 특정 값을 추출할 필요 없이 편리하게 사용할 수 있다!

 


Collections 

데이터를 하나만 받는 게 아니라, 여러 개 받아서 List나 Dictionary 등으로 매핑할 수도 있다.

 

다음은 string형 List 값을 받는 액션 함수이다.

public IActionResult Test3(List<string> names)
{
    return null;
}

 

 

GET방식: Url로는 다음과 같이 값을 전달해줄 수 있다.

  • names[0]=Seeyoun&names[1]=Hoochu
  • [0]=Seeyoun&[1]=Hoochu
  • names=Seeyoun&names=Hoochu

 

POST방식: Body에 넣어서 전달할 수 있다.

이런식으로 보내주면

리스트에 쏙 들어감.

 


Complex Type (중요)

만약 요청에서 넘길 데이터들이 많아지는 경우, 액션 함수의 파라미터를 무한정 늘리는 게 최선일까?

=> ㄴㄴ. 넘겨받을 인자가 너무 많아지면 부담스러우니까, 별도의 데이터 모델링 클래스(DTO)를 만들어주도록 한다.

 

 

직접 해보자.

 

1. 데이터를 받을 클래스(DTO)를 만들어준다.

 

 

2. 컨트롤러에 다음과 같이 데이터 모델을 파라미터로 받는 액션 함수를 만든다.

public IActionResult Test2(TestModel testModel)
{
    return null;
}
  • 요청에서 데이터를 받을 때 TestModel 클래스의 형태로 받을 것이다.

 

3. 이제 POST요청의 바디에다 넣어서 요청해보자!

 

실행해주면

 

넣은 값대로 Name이 잘 들어간다~ (id는 라우팅 패턴에서 설정해놓은 값임)

 


Binding Source 직접 지정 (애트리뷰트 사용)

기본적으로 우리가 사용하는 binding 모델은 form, route, query string 이렇게 세가지를 순서대로 적용한다고 했었다.

 

그런데 경우에 따라서 이들을 순서대로 적용 하는 게 아니라,
셋 중 하나로 파싱하도록 명시적으로 지정할 수도 있다! (셋 중 하나가 아닌 다른 방법으로 파싱하도록 지정하는 것도 가능)

  • 대표적으로, Body에서 JSON 형태로 데이터를 보내주고 싶을 때 사용

 

애트리뷰트를 통해 (어디서 데이터를 찾을지) 힌트를 주는 방식으로 사용한다.

  • [FromHeader] : 요청의 헤더에서 찾아라
  • [FromQuery] : QueryString에서 찾아라
  • [FromRoute] : Route Parameter에서 찾아라
  • [FromForm] : POST Body에서 찾아라
  • [FromBody] : 그냥 Body에서 찾아라
    • 디폴트는 JSON을 이용해서 값을 추출하려고 하는데, 다른 형태로 세팅해줄 수도 있음 ㅇㅇ

 

사용법은 간단한데, 함수 파라미터 앞에다가 애트리뷰트를 붙여주면 된다.

public IActionResult Test(int id, [FromHeader] string value)
{
    return null;
}

 

쿼리에는 value=queryVal을 넣고, 헤더에는 value=headerVal을 넣어서 POST 요청을 보냈다.

 

[FromHeader] 애트리뷰트를 사용했으므로, 헤더에 포함된 value가 들어간다.

 


Validation (애트리뷰트 사용)

데이터 Validation도 중요하다.

클라-서버 구조에서는, 늘 그렇지만, 서버는 클라를 신용할 수 없다.

웹에서 보내는 정보는 언제나 조작될 우려가 있기 때문에 그 정보를 곧이곧대로 믿을 수는 없다.

  • 전화번호를 보내랬더니 abcde 문자열로 보낸다거나,
  • 신분증 사진을 보내랬더니 10GB 파일을 보낸다거나,
  • 구매 수량을 음수로 보낸다거나... 하는 등 다양한 문제 발생 가능

 

따라서 항상 validation을 통해서 파싱된 값이 적절한 정보가 맞는지 체크해줘야 한다.

 

근데 이런 validation 작업을 액션 안에서 직접 하기에는, 너무 복잡하고 불편해 질 것임

따라서 ASP.NET Core에서는 validation을 편하게 하기 위해, Data Annotation을 제공해준다.

using System.ComponentModel.DataAnnotations;

 

 

Data Annotation이란, 데이터가 유효한 데이터인지 강제적으로 검증할 수 있도록 하는 것임.

애트리뷰트를 통해 데이터에 대한 힌트를 주는 방법으로 구현한다.

  • 다만 세부적인 검사까지 하기는 힘들다!

 

관련하여 다음과 같은 애트리뷰트들이 있다.

  • [Required] : 이 값은 무조건 있어야 한다!!
  • [CreditCard] : 올바른 결제카드 번호인지 체크
  • [EmailAddress] : 올바른 이메일 주소 형식인지 체크
  • [StringLength(max)] : String 길이가 최대 max개 이하인지 체크
  • [MinLength(min)] : 데이터 Collection의 크기가 최소 min개 이상인지 체크
  • [Phone] : 올바른 전화번호 형식인지 체크
  • [Range(min, max)] : min, max 사이의 값인지 체크
  • [Url] : 올바른 URL인지 체크
  • [Compare] : 2개의 프로퍼티 비교시 사용
    • Password, ConfirmPassword와 같이 두 프로퍼티 값이 같은지 체크 (이건 보통 클라쪽에서 하긴 함)

 

실제 사용 예제를 보자.

public class TestModel
{
    [Required]
    public int Id { get; set; }

    [Required]
    [StringLength(20)]
    public string Name { get; set; }
}
  • Id가 있는지 검증한다.
  • Name이 있는지, 있다면 20자 이하인지 검증한다.

 

 

※ 단 유의할 점은, 검증을 통과하지 못했다고 하더라도 크래쉬가 나거나 에러가 나오는 건 아님.

Validation 결과에 따라 어떻게 처리할지는 개발자가Action에서 직접 구현해야 함.

 

 

위 TestModel을 통해 전달받은 데이터가 다음 액션으로 매핑되는 경우를 보자.

public IActionResult Test2(TestModel testModel)
{
    return null;
}
  • 만약 Id나 Name이 없거나, Name이 20자를 초과한다면 Validation은 실패할 것임.
  • ModelState.IsValid 를 통해 Validation 성공여부 체크 가능. (ControllerBase의 멤버 변수 - bool형)
if(!ModelState.IsValid){
	return RedirectToAction("Error");
}
  • 데이터가 Valid하지 않은 경우, Error 액션으로 Redirect해주는 코드

 

 

※ 참고로 WebAPI의 경우, 컨트롤러에 [ApiController] 어트리뷰트를 붙이면!

  • IsValid인 경우 알아서 HTTP Bad Request (400) 응답을 보낸다.

'게임 > ASP.NET Core' 카테고리의 다른 글

7. TagHelper  (0) 2024.04.15
6. View  (0) 2024.04.15
4. Routing  (0) 2024.04.15
3. MVC 철학  (0) 2024.04.15
2. Middleware 기초  (0) 2024.04.15
Comments