재우니 개발자 블로그


ASP.NET Core MVC(Web API 포함)에서 [FromBody] 사용 여부에 따라 JavaScript(axios)에서 요청을 보내는 방식이 조금 달라집니다.


아래에서 [FromBody]를 사용할 때사용하지 않을 때를 나눠서 설명드리겠습니다.


1. [FromBody]를 사용하는 경우

[FromBody]는 **HTTP 요청의 Body(JSON, XML 등)**에서 데이터를 읽습니다.
즉, axios에서는 data 속성을 사용하여 JSON으로 전달해야 합니다.

// C#
[HttpPost]
public async Task<IActionResult> UpdateUserDept([FromBody] UpdateUserDept.Command command)
{
    // command 객체는 JSON Body에서 바인딩됨
    ...
}

 

 

JavaScript (axios) 호출 예시

axios.post('/User/UpdateUserDept', {
    userId: 123,
    deptId: 45
}, {
    headers: {
        'Content-Type': 'application/json'
    }
})
.then(res => {
    console.log(res.data);
})
.catch(err => {
    console.error(err);
});

 

 

포인트

  • axios에서 data 파라미터를 사용해야 함
  • Content-Type: application/json 필수
  • URL Query String은 필요 없음

2. [FromBody]를 사용하지 않는 경우

이 경우 ASP.NET Core는 [FromQuery] 또는 [FromForm] 바인딩 규칙에 따라 처리합니다.
즉, 데이터는 QueryString이나 Form-data로 전달해야 합니다.

// C#
[HttpPost]
public async Task<IActionResult> UpdateUserDept(UpdateUserDept.Command command)
{
    // command는 QueryString, Form-data에서 바인딩됨
    ...
}

 

 

JavaScript (axios) - Form-data 방식

const formData = new FormData();
formData.append('userId', 123);
formData.append('deptId', 45);

axios.post('/User/UpdateUserDept', formData)
    .then(res => {
        console.log(res.data);
    })
    .catch(err => {
        console.error(err);
    });

 

 

JavaScript (axios) - QueryString 방식

axios.post('/User/UpdateUserDept?userId=123&deptId=45')
    .then(res => {
        console.log(res.data);
    })
    .catch(err => {
        console.error(err);
    });

 

 

포인트

  • [FromBody]가 없으면 JSON Body를 보내도 자동으로 바인딩되지 않음
  • 대신 QueryString이나 FormData를 사용해야 함
  • 파일 업로드나 단순 폼 전송이면 FormData가 적합

3. 차이 정리

구분 [FromBody] 있음 [FromBody] 없음

데이터 위치 HTTP Body(JSON) QueryString / Form-data
axios 전송 방식 axios.post(url, jsonObject, { headers: { 'Content-Type': 'application/json' }}) axios.post(url, formData) 또는 axios.post(url + '?key=value')
Content-Type application/json application/x-www-form-urlencoded 또는 multipart/form-data

💡 개발 팁

  • API라면 [FromBody] + JSON 전송을 권장 (표준 REST 패턴)
  • 단순 페이지 폼 처리라면 [FromBody] 없이 FormData 전송이 편리
  • 파일 업로드 시에는 [FromForm]을 사용하면 FormData 처리와 궁합이 좋음

 

그럼 [FromBody], [FromForm], [FromQuery]를 하나의 Controller 액션에서 비교하고,
각각 axios로 호출하는 예제를 정리해 드리겠습니다.


1. Controller 예제 (ASP.NET Core 8 MVC / API)

using Microsoft.AspNetCore.Mvc;

namespace DemoApi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class UserController : ControllerBase
    {
        public class UpdateUserDeptCommand
        {
            public int UserId { get; set; }
            public int DeptId { get; set; }
        }

        // 1. [FromBody] JSON
        [HttpPost("FromBody")]
        public IActionResult UpdateFromBody([FromBody] UpdateUserDeptCommand command)
        {
            return Ok(new { method = "FromBody", data = command });
        }

        // 2. [FromForm] Form-data
        [HttpPost("FromForm")]
        public IActionResult UpdateFromForm([FromForm] UpdateUserDeptCommand command)
        {
            return Ok(new { method = "FromForm", data = command });
        }

        // 3. [FromQuery] Query String
        [HttpGet("FromQuery")]
        public IActionResult UpdateFromQuery([FromQuery] UpdateUserDeptCommand command)
        {
            return Ok(new { method = "FromQuery", data = command });
        }
    }
}

 

 

 


2. axios 호출 예제

(1) [FromBody] - JSON Body 전송

axios.post('/User/FromBody', 
    {
        userId: 123,
        deptId: 45
    }, 
    {
        headers: { 'Content-Type': 'application/json' }
    }
).then(res => {
    console.log(res.data);
});

 

 

HTTP 요청 예시

POST /User/FromBody
Content-Type: application/json

{
  "userId": 123,
  "deptId": 45
}

 

 


(2) [FromForm] - Form-data 전송

const formData = new FormData();
formData.append('userId', 123);
formData.append('deptId', 45);

axios.post('/User/FromForm', formData)
    .then(res => {
        console.log(res.data);
    });

 

HTTP 요청 예시

POST /User/FromForm
Content-Type: multipart/form-data

------WebKitFormBoundary...
Content-Disposition: form-data; name="userId"

123
------WebKitFormBoundary...
Content-Disposition: form-data; name="deptId"

45

 

 


(3) [FromQuery] - Query String 전송

axios.get('/User/FromQuery', {
    params: {
        userId: 123,
        deptId: 45
    }
})
.then(res => {
    console.log(res.data);
});

 

 

HTTP 요청 예시

GET /User/FromQuery?userId=123&deptId=45

3. 차이점 요약

바인딩 속성 전송 방식 axios 데이터 설정 Content-Type

[FromBody] HTTP Body(JSON) axios.post(url, jsonObject, { headers: { 'Content-Type': 'application/json' }}) application/json
[FromForm] Form-data FormData() 객체로 생성 후 axios.post(url, formData) multipart/form-data
[FromQuery] URL Query axios.get(url, { params: { key: value }}) - (기본 GET 요청)

💡 최신 트렌드로는 REST API → [FromBody] + JSON
단, 파일 업로드 → [FromForm]
단순 필터/검색 파라미터 → [FromQuery] 사용이 일반적입니다.


 

 

Postman 테스트 스크린샷 + axios 호출 실행 결과까지 한눈에 비교한 문서

 

  1. Controller 코드
  2. Postman 테스트 요청/응답
  3. axios 호출 예시 및 브라우저 콘솔 결과
  4. 정리 표

1. Controller 코드 (C# ASP.NET Core 8)

using Microsoft.AspNetCore.Mvc;

namespace DemoApi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class UserController : ControllerBase
    {
        public class UpdateUserDeptCommand
        {
            public int UserId { get; set; }
            public int DeptId { get; set; }
        }

        // 1. [FromBody] JSON
        [HttpPost("FromBody")]
        public IActionResult UpdateFromBody([FromBody] UpdateUserDeptCommand command)
        {
            return Ok(new { method = "FromBody", data = command });
        }

        // 2. [FromForm] Form-data
        [HttpPost("FromForm")]
        public IActionResult UpdateFromForm([FromForm] UpdateUserDeptCommand command)
        {
            return Ok(new { method = "FromForm", data = command });
        }

        // 3. [FromQuery] Query String
        [HttpGet("FromQuery")]
        public IActionResult UpdateFromQuery([FromQuery] UpdateUserDeptCommand command)
        {
            return Ok(new { method = "FromQuery", data = command });
        }
    }
}

2. Postman 테스트

(1) [FromBody] 요청/응답

요청

POST /User/FromBody
Content-Type: application/json

{
    "userId": 123,
    "deptId": 45
}

응답

{
    "method": "FromBody",
    "data": {
        "userId": 123,
        "deptId": 45
    }
}

(2) [FromForm] 요청/응답

요청

POST /User/FromForm
Content-Type: multipart/form-data

userId: 123
deptId: 45

응답

{
    "method": "FromForm",
    "data": {
        "userId": 123,
        "deptId": 45
    }
}

(3) [FromQuery] 요청/응답

요청

GET /User/FromQuery?userId=123&deptId=45

 

 

응답

{
    "method": "FromQuery",
    "data": {
        "userId": 123,
        "deptId": 45
    }
}

 

 

 


3. axios 호출 예시 + 콘솔 출력

(1) [FromBody]

axios.post('/User/FromBody', 
    { userId: 123, deptId: 45 }, 
    { headers: { 'Content-Type': 'application/json' } }
).then(res => console.log(res.data));

 

 

콘솔 출력

{ method: "FromBody", data: { userId: 123, deptId: 45 } }

 

 


(2) [FromForm]

const formData = new FormData();
formData.append('userId', 123);
formData.append('deptId', 45);

axios.post('/User/FromForm', formData)
    .then(res => console.log(res.data));

 

콘솔 출력

{ method: "FromForm", data: { userId: 123, deptId: 45 } }

 

 


(3) [FromQuery]

axios.get('/User/FromQuery', {
    params: { userId: 123, deptId: 45 }
}).then(res => console.log(res.data));

 

콘솔 출력

{ method: "FromQuery", data: { userId: 123, deptId: 45 } }

 

 


4. 정리 표

바인딩 방식 HTTP 메서드 axios 예시 Content-Type 데이터 위치

[FromBody] POST axios.post(url, json, { headers: { 'Content-Type': 'application/json' }}) application/json Request Body(JSON)
[FromForm] POST axios.post(url, formData) multipart/form-data Request Body(Form-data)
[FromQuery] GET axios.get(url, { params: {...} }) 기본 GET URL Query String