이번 강의는 기능 하나를 추가하면서
“아, 이래서 이 필드가 존재하는구나”가 명확해지는 강의였다.
핵심은 세 가지다.
statusCode 필드의 존재 이유 이해public record RsData<T>(
String resultCode,
@JsonIgnore
int statusCode,
String msg,
T data
) {
public RsData(String resultCode, String msg) {
this(resultCode, msg, null);
}
public RsData(String resultCode, String msg, T data) {
this(
resultCode,
Integer.parseInt(resultCode.split("-", 2)[0]),
msg,
data
);
}
}
여기서 눈에 띄는 부분이 있다.
@JsonIgnore
int statusCode
JSON 응답으로는 절대 내려가지 않는 값이다.
그런데도 굳이 statusCode를 왜 넣었을까?
결론부터 말하면,
HTTP 응답 코드를 설정하기 위한 내부 전용 필드다.
1️⃣ 컨트롤러는 RsData를 반환
2️⃣ resultCode 예: "201-1"
3️⃣ RsData 생성자에서:
Integer.parseInt(resultCode.split("-", 2)[0])
→ 201 추출
4️⃣ 이 값이 statusCode에 저장됨
5️⃣ ResponseAspect(AOP)가 이 값을 읽어서
6️⃣ HttpServletResponse.setStatus(statusCode) 실행
📌 즉,
resultCode → 의미 + 규칙statusCode → HTTP 레벨 제어용 내부 데이터👉 필요하다. 아주 중요하다.
이유는 명확하다.
그래서 @JsonIgnore가 붙어 있는 것.
statusCode는
클라이언트를 위한 데이터 ❌
서버의 동작을 위한 데이터 ⭕
이렇게도 생각할 수 있다.
“resultCode에서 매번 파싱하면 되잖아?”
하지만 분리한 이유는 설계적으로 훨씬 깔끔하기 때문이다.
201-1, 404-1)201, 404)👉 역할 분리(SRP)
👉 AOP에서 파싱 로직을 없애기 위함
record PostModifyReqBody(
@NotBlank
@Size(min = 2, max = 100)
String title,
@NotBlank
@Size(min = 2, max = 5000)
String content
) {}
@Valid + @RequestBody 필수@PutMapping("/{id}")
@Transactional
public RsData<Void> modify(
@PathVariable int id,
@Valid @RequestBody PostModifyReqBody reqBody
) {
Post post = postService.findById(id).get();
postService.modify(post, reqBody.title, reqBody.content);
return new RsData<>(
"200-1",
"%d번 글이 수정되었습니다.".formatted(post.getId())
);
}
✔ 성공/실패만 알리므로 RsData<Void>
✔ 수정은 200 OK가 가장 자연스럽다
이전 구조에서는 특정 생성자 조합에서
msg가 제대로 전달되지 않는 문제가 있었다.
그래서 지금 구조처럼 모든 생성자가 최종 canonical constructor로 모이도록 수정했다.
this(resultCode, statusCode, msg, data);
👉 생성자 체이닝을 명확히 해서
👉 데이터 누락 가능성을 원천 차단
@JsonIgnore
int statusCode
이 한 줄의 의미는 이거다.
“이 값은 JSON 응답에는 포함되지 않지만
서버 내부 로직에서는 반드시 필요하다.”
resultCode, msg, data만 보면 됨statusCode로 HTTP 응답 제어statusCode는 보내기 위한 값이 아니라 쓰기 위한 값이번 강의에서 제일 인상 깊었던 건 이거였다.
“지금은 쓸모 없어 보이는데
나중에 보면 왜 필요한지 알게 되는 필드”
statusCode가 딱 그랬다.
처음 보면
“이거 왜 있지?” 싶은데
AOP까지 흐름을 다 이해하고 나니까
👉 없으면 구조가 무너지는 핵심 필드였다.
점점 코드가
“동작하는 코드”에서
“설계가 보이는 코드”로 바뀌는 느낌이 들었다.