Spring MVC 환경에서 클라이언트와 서버 간 데이터 교환을 구현할 때, 다양한 AJAX 전송 방식을 선택할 수 있습니다. 각 방식은 특정 상황에 최적화되어 있으며, 적절한 어노테이션과 조합하여 사용합니다.
환경 구성
jQuery 기반 AJAX 통신을 위해 Maven 의존성을 추가합니다.
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.6.4</version>
</dependency>
JSP 페이지에서 라이브러리를 로드합니다.
<script src="/프로젝트명/webjars/jquery/3.6.4/jquery.min.js"></script>
방식 1: URL 경로 변수 + @PathVariable
RESTful 스타일의 엔드포인트 설계에 적합합니다. 식별자나 필수 값을 경로에 포함시킬 때 사용합니다.
클라이언트 측 JavaScript:
<script>
function sendViaPath() {
var userAlias = "honggildong";
var userYears = 28;
$.ajax({
type: 'POST',
url: '/api/members/register/' + userAlias + '/' + userYears,
success: function(response) {
console.log("처리 완료: " + response);
},
error: function(xhr) {
console.error("오류 발생: " + xhr.status);
}
});
}
</script>
서버 측 컨트롤러:
@RestController
@RequestMapping("/api/members")
public class MemberController {
@PostMapping("/register/{alias}/{years}")
public ResponseEntity<String> enrollMember(
@PathVariable("alias") String alias,
@PathVariable("years") int years) {
MemberDto dto = new MemberDto();
dto.setNickname(alias);
dto.setAge(years);
memberService.save(dto);
return ResponseEntity.ok("등록 성공");
}
}
방식 2: 폼 데이터 전송 + @RequestParam
일반적인 폼 제출이나 쿼리 파라미터 방식에 적합합니다. 선택적 파라미터나 복수 값 처리가 용이합니다.
클라이언트 측 JavaScript:
<script>
function sendViaFormData() {
var payload = {
"nickname": "kimcoding",
"years": 32,
"interests": ["java", "spring", "cloud"]
};
$.ajax({
type: 'POST',
url: '/api/members/enroll',
data: payload,
traditional: true,
success: function(result) {
alert("응답: " + result);
}
});
}
</script>
서버 측 컨트롤러 (명시적 어노테이션):
@PostMapping("/enroll")
public ResponseEntity<Void> createMember(
@RequestParam("nickname") String nickname,
@RequestParam("years") Integer years,
@RequestParam("interests") List<String> interests) {
log.info("닉네임: {}, 이: {}, 관심사: {}", nickname, years, interests);
return ResponseEntity.ok().build();
}
서버 측 컨트롤러 (암시적 바인딩):
@PostMapping("/enroll")
public ResponseEntity<Void> createMemberSimple(
String nickname,
Integer years,
List<String> interests) {
return ResponseEntity.ok().build();
}
방식 3: JSON 페이로드 + @RequestBody
복잡한 객체 구조를 전송할 때 권장됩니다. Jackson 라이브러리가 필요합니다.
필수 의존성:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
클라이언트 측 JavaScript:
<script>
function sendViaJson() {
var memberInfo = {
nickname: "leedev",
years: 25,
skills: [
{ name: "Java", level: "advanced" },
{ name: "Python", level: "intermediate" }
]
};
$.ajax({
type: 'POST',
url: '/api/members',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(memberInfo),
success: function(data) {
console.log("서버 응답:", data);
}
});
}
</script>
도메인 클래스:
public class Skill {
private String name;
private String level;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getLevel() { return level; }
public void setLevel(String level) { this.level = level; }
}
public class MemberCommand {
private String nickname;
private int years;
private List<Skill> skills;
public String getNickname() { return nickname; }
public void setNickname(String nickname) { this.nickname = nickname; }
public int getYears() { return years; }
public void setYears(int years) { this.years = years; }
public List<Skill> getSkills() { return skills; }
public void setSkills(List<Skill> skills) { this.skills = skills; }
}
서버 측 컨트롤러 (객체 매핑):
@PostMapping
public ResponseEntity<String> registerMember(@RequestBody MemberCommand command) {
log.info("수신된 데이터: {}", command);
memberService.create(command);
return ResponseEntity.status(HttpStatus.CREATED).body("생성 완료");
}
서버 측 컨트롤러 (동적 맵 처리):
@PostMapping("/dynamic")
public ResponseEntity<String> handleFlexibleInput(
@RequestBody Map<String, Object> dynamicData) {
String nick = (String) dynamicData.get("nickname");
Integer age = (Integer) dynamicData.get("years");
List<?> abilities = (List<?>) dynamicData.get("skills");
log.info("동적 파싱 결과: {}, {}, {}", nick, age, abilities.size());
return ResponseEntity.ok("처리 완료");
}
방식 선택 가이드
| 상황 | 권장 방식 | 주요 특징 |
|---|---|---|
| 단일 리소스 식별 | @PathVariable | 캐싱 친화적, URL 가독성 |
| 검색 필터, 페이징 | @RequestParam | 선택적 파라미터, 복수 값 |
| 중첩 객체, 복잡 구조 | @RequestBody | 타입 안전성, 검증 가능 |
실제 프로젝트에서는 REST API 설계 규칙에 따라 혼합 사용하는 경우가 일반적입니다.