클라이언트와 서버 간 데이터 전송 방식
데이터 전송 방법
JSON으로 데이터 전송 시
- @RequestBody 어노테이션 사용.
Form 데이터 전송 시
- @ModelAttribute 어노테이션 사용.
예제 코드
@AllArgsConstructor
@Getter
public static class ModifyForm {
private String title;
private String content;
}
@PutMapping("{id}")
public Map<String, Object> modify(
@PathVariable long id,
@RequestBody ModifyForm form
) {
// 로직 구현
}
record의 활용
특징
- 데이터를 저장하기 위한 객체로, 생성자, 게터, 세터, equals 등이 자동 생성됨.
- 코드가 간결해짐.
기존 클래스와 비교
@AllArgsConstructor
@Getter
public static class ModifyReqBody {
private String title;
private String content;
}
이 코드는 다음과 같이 간략화할 수 있음:
record ModifyReqBody(String title, String content) {}
값 접근 방법
- body.title() 또는 body.title 둘 다 가능.
DTO(Data Transfer Object)의 필요성
DTO를 사용하는 이유
- 서버 코드 변경 시에도 프론트엔드가 기존 데이터 형식을 유지할 수 있도록 함.
- 엔티티와 분리하여 확장성과 유지보수성을 높임.
JAVA Spring에서 DTO 예제
package com.example.rest.domain.post.post.dto;
import com.example.rest.domain.post.post.entity.Post;
import lombok.Getter;
@Getter
public class PostDto {
private long id;
private String name;
private String body;
public PostDto(Post post) {
this.id = post.getId();
this.name = post.getName();
this.body = post.getBody();
}
}
컨트롤러에서의 사용 예:
Post post = postService.getItem(id).get();
PostDto postDto = new PostDto(post);
return postDto;
@JsonProperty 사용
- DTO 대신 @JsonProperty를 사용하여 엔티티를 직접 반환 가능하지만 추천되지 않음.
- 복잡성이 증가하고 확장성이 낮아질 가능성 있음.
예:
@JsonProperty("createdAt")
private LocalDateTime createdDate;
원시 타입과 객체 타입의 차이
원시 타입의 한계
- 원시 타입은 null을 표현할 수 없음.
- 예: long id는 데이터가 없을 때 0을 반환.
객체 타입의 장점
- Long id를 사용하여 null로 데이터 없음 상태를 명확히 표현 가능.
@JsonInclude 활용
- @JsonInclude(JsonInclude.Include.NON_NULL)를 사용하면 null 필드를 JSON 응답에서 제외 가능.
제너릭 타입을 활용한 리턴값 처리
- 값이 없을 때:
ResponseData<Void> result;
HTTP 응답 처리
ResponseEntity 사용
- 상태 코드와 응답 메시지를 함께 처리 가능.
예:
return ResponseEntity.status(HttpStatus.CREATED).body(responseData);
또는:
return ResponseEntity.noContent().build(); // 상태 코드 204 반환
AOP를 이용한 전후 처리
AOP란?
- 프록시를 이용해 특정 클래스나 메서드의 실행 전후 처리를 수행.
AOP 예제
package com.example.rest.global.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ResponseAspect {
@Around("""
(
within(@org.springframework.web.bind.annotation.RestController *)
) && (
@annotation(org.springframework.web.bind.annotation.GetMapping) ||
@annotation(org.springframework.web.bind.annotation.PostMapping) ||
@annotation(org.springframework.web.bind.annotation.PutMapping) ||
@annotation(org.springframework.web.bind.annotation.DeleteMapping)
)
""")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Pre-processing");
Object result = joinPoint.proceed();
System.out.println("Post-processing");
return result;
}
}
위 코드의 joinPoint.proceed()부분에서 원래 실하려던 메서드를 호출해 실행한다.
이를 통해 값을 가로채거나 추가적인 전, 후처리가 가능하다.
'TIL' 카테고리의 다른 글
250203 월 TIL (0) | 2025.02.03 |
---|---|
250131 금 TIL (0) | 2025.01.31 |
250124 금 TIL (0) | 2025.01.24 |
250123 목 TIL (0) | 2025.01.23 |
250122 수 TIL (0) | 2025.01.22 |