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 호출 실행 결과까지 한눈에 비교한 문서
- Controller 코드
- Postman 테스트 요청/응답
- axios 호출 예시 및 브라우저 콘솔 결과
- 정리 표
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 |