Spring MVC에서 jQuery AJAX를 활용한 서버 데이터 전송 패턴

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 설계 규칙에 따라 혼합 사용하는 경우가 일반적입니다.

태그: Spring MVC jQuery AJAX PathVariable RequestParam RequestBody

6월 6일 17:09에 게시됨