v∞
★ FINALE · REST

데이터 흐름 디버깅 워크숍

흐름도를 거꾸로 거슬러 올라간다

학습 목표

  • 버그를 만났을 때 흐름도를 역추적하는 사고를 익힌다
  • 디버깅의 5 단계 점검(F12 → 콘솔 → SQL 로그 → DB → 응답)을 외운다
  • 실제 시나리오 5 개를 풀어본다
  • 4 주 학습의 모든 박스를 한 번에 복습한다

4 주 동안 우리가 그린 흐름도

브라우저
Tomcat
DispatcherServlet
Controller
Service
Mapper
DB

v0 부터 시작해 매 차시 박스가 하나씩 늘어났습니다. 이제 7 박스가 한 줄로 이어진 상태.

👉 오늘은 이 화살표를 거꾸로 따라가는 법.

⚠️ 가장 답답한 순간

학생들의 외침

"안 돼요... 어디가 문제인지 모르겠어요!"

버그 자체는 어렵지 않습니다. 「어디서 막혔는지」 모르는 게 어려운 부분.

7 박스가 일렬로 늘어선 흐름도를 막연히 노려본다고 답이 나오지 않습니다. 체계적인 점검이 필요합니다.

🛠️ 5 단계 역추적 사고법

화살표를 거꾸로 따라간다

화면에서 시작해 DB 쪽으로 한 박스씩 거꾸로 점검합니다. 「데이터가 어디까지 왔는가」를 한 단계씩 확인.

⑤ 응답 JSON / 화면 ←─── 여기서 시작 (눈에 보임) ④ DB SELECT 결과 ③ Mapper SQL 로그 ② 서버 콘솔 로그 ① F12 Network 탭 ←─── 마지막엔 여기 (출발점) 각 단계마다 「데이터가 여기까지 왔는가?」 확인 → 안 왔으면 그 직전 단계가 문제

① 단계 — F12 Network 탭

"내가 보낸 요청이 진짜 갔는가?"
  • 요청이 표에 보이는가?
  • 안 보이면 → 자바스크립트 오류 (Console 탭 확인)
  • 보이면 → Status Code 확인
Status의심
없음 (요청 자체 안 감)JS 오타 / fetch 호출 안 됨
200요청 잘 갔다 옴 → 다음 단계로
302리다이렉트 (보통 로그인 풀림)
404URL 오타 / 컨트롤러 매핑 잘못
500서버 코드 예외 → ② 서버 콘솔로

② 단계 — 서버 콘솔 로그

"컨트롤러가 호출됐는가? 예외는 없는가?"

Tomcat 콘솔에:

  • 스택 트레이스가 있으면 → 어느 줄에서 예외 발생했는지 확인
  • Bean 생성 실패 → 시작 시 출력
  • NullPointerException → 어떤 변수가 null 인지 확인

// 디버깅용 로그 추가
@PostMapping("/api/replies")
public Reply add(@RequestBody Reply r) {
    System.out.println("[DEBUG] 받은 댓글: " + r);  // ←
    Reply saved = service.add(r);
    System.out.println("[DEBUG] 저장됨: " + saved);  // ←
    return saved;
}

③ 단계 — Mapper SQL 로그

"실제 SQL 이 실행됐는가? 어떤 SQL?"

mybatis-config.xmllogImpl=STDOUT_LOGGING 으로 SQL 로그 켜둔 상태에서:


==>  Preparing: INSERT INTO myreply(content, boardnum, writer) VALUES(?, ?, ?)
==> Parameters: 좋은 글이네요(String), 3(Integer), hong(String)
<==    Updates: 1
  • SQL 자체가 안 보이면 → Mapper 호출 안 됨 (② 다시)
  • SQL 보이고 Parameters 가 이상하면 → 컨트롤러에서 잘못 받음
  • SQL 정상이고 Updates 가 0 이면 → WHERE 조건 의심

④ 단계 — DB 직접 SELECT

"DB 에 데이터가 진짜 들어갔는가?"

MySQL Workbench / DBeaver 등으로 직접 SELECT:


SELECT * FROM myreply ORDER BY num DESC LIMIT 5;
  • 데이터가 있으면 → ⑤ 응답 단계 의심
  • 데이터가 없으면 → ③ SQL 로그가 거짓말? Updates=0 이었을 가능성
  • 데이터가 있는데 화면에 없으면 → 직렬화/응답 문제

⑤ 단계 — 응답 JSON / 화면

"응답에 뭐가 와 있는가?"

F12 → Network → 해당 요청 → Response 탭:


// 정상 응답
{
  "num": 7,
  "content": "좋은 글이네요",
  "boardnum": 3,
  "writer": "hong",
  "createdAt": "2024-08-15T10:30:00"
}

// 비정상 — 모든 필드가 null
{
  "num": 0,
  "content": null,
  "boardnum": 0,
  "writer": null
}
  • 응답에는 정상 → JS 가 그 데이터를 화면에 못 그렸음
  • 응답이 비정상 → DB 에서 가져온 객체에 데이터 매핑 안 됨 (카멜·스네이크 함정 의심)

실전 시나리오 ① — "댓글이 화면에 안 떠요"

증상: 댓글 작성 버튼 누르면 아무 일도 일어나지 않음 역추적: ① F12 Network — POST /api/replies 요청 보임? └─ 안 보임 → JS Console 에서 fetch 오류 확인 └─ 보임 → Status Code 는? ① Status 가 200 이라면 — Response 탭 확인 └─ 응답에 데이터 정상 → JS 의 DOM 추가 코드 의심 ① Status 가 500 이라면 — ② 서버 콘솔로 └─ NullPointerException 흔적 — 어떤 변수가 null?

실전 시나리오 ② — "글 수정했는데 안 바뀌어요"

증상: 수정 폼 제출 → "수정 완료" 페이지 → 다시 봐도 그대로 역추적: ① F12 Network — POST /board/update 응답 Status? └─ 302 (리다이렉트) → 일단 정상으로 보임 └─ 다음 페이지의 GET 응답을 봐야 함 ⑤ 새로고침된 글 화면의 Response — 옛 내용 그대로? └─ 정상이면 캐시 문제. Ctrl+F5 ④ DB 직접 SELECT — 실제로 update 됐는가? └─ 옛 데이터 → ③ SQL 로그 확인 └─ 새 데이터 → 화면 캐시 문제 ③ SQL 로그 — UPDATE 문이 실행됐는가? └─ 안 됐으면 → 본인 확인에서 차단됐을 수 있음 (Service 에서 SecurityException)

실전 시나리오 ③ — "한글이 ?? 로 깨져요"

증상: 한글 입력 → 저장 → 화면에 ???? 표시 역추적: ⑤ Response — JSON 안의 글자가 ??? └─ DB 에서 이미 ??? 로 저장됨. ④ 로 ④ DB SELECT — 글자가 ??? 또는 깨진 글자? └─ ??? → 컬럼 charset 가 utf8mb4 인지 └─ 정상 → ⑤ JSP encoding 문제 ② 서버 콘솔 — 받을 때 이미 ??? └─ web.xml CharacterEncodingFilter 미설정 가장 흔한 원인: 4 곳 중 한 곳의 인코딩이 UTF-8 가 아님 ① web.xml CharacterEncodingFilter ② JSP page contentType ③ JDBC URL ?characterEncoding=UTF-8 ④ DB 테이블/컬럼 charset

실전 시나리오 ④ — "객체 필드가 모두 null"

증상: SELECT 는 성공하는데 응답 JSON 의 모든 필드가 null 역추적: ⑤ Response 의 JSON 보기 → 정말 모든 필드 null ④ DB SELECT 직접 — 데이터 있음 ③ SQL 로그 — SELECT 실행됨, 결과 1 행 문제: SELECT 결과를 객체에 매핑할 때 실패 → 카멜 ↔ 스네이크 함정! → mybatis-config.xml 의 <setting name="mapUnderscoreToCamelCase" value="true"/> 확인 해결: 옵션 추가 후 재시작 → 즉시 해결

실전 시나리오 ⑤ — "로그인 풀림"

증상: 분명 로그인 했는데 다른 페이지 가면 다시 로그인 화면 역추적: ① F12 Network — 그 페이지 요청 Status 가 302? └─ 302 → 인터셉터가 비로그인으로 판단해 리다이렉트 F12 Application — Cookies 의 JSESSIONID 가 있는가? └─ 없음 → 브라우저 쿠키 차단 또는 도메인 문제 └─ 있는데 같은 값? ② 서버 콘솔 — session.getAttribute("loginUser") 가 null? └─ session.setAttribute("loginUser", m) 가 빠짐 └─ 또는 키 이름 오타 ("loginUser" vs "loginuser") ① F12 Network — 로그인 응답에 Set-Cookie: JSESSIONID 있나? └─ 없으면 → 로그인 메서드에서 세션 저장 안 했음

핵심 도구 5 가지

도구용도
F12 Network 탭요청 갔는가 / Status / 응답 내용
F12 Console 탭JS 오류
F12 Application 탭쿠키 / 세션 ID 확인
Tomcat 콘솔스택 트레이스 / 디버깅 로그
DB 도구 (Workbench)실제 데이터 확인

👉 4 주 동안 매 차시에서 한 번씩은 본 도구들. 디버깅 시엔 동시에 5 개를 띄워둠.

버그가 안 풀릴 때의 사고법

  • 흐름도 상에서 어디까지 데이터가 갔는지 확정
  • 그 직후 박스가 의심 1순위
  • 로그를 추가해서 다시 실행 — 추측 대신 사실로
  • 한 번에 한 가지만 변경 — 동시에 여러 곳 고치면 원인 알 수 없음
  • 제일 단순한 케이스로 좁히기 — 입력값을 최소화
  • 한 시간 막히면 잠깐 쉬기 — 머리 식히면 풀리는 경우 많음

4 주 학습 정리

Part마일스톤핵심 박스 추가
1. 웹 동작v0 Hello ServletTomcat, Servlet
2. Java/Spring첫 Bean 주입Spring 컨테이너
3. MVCv0.5 종단간Controller, Service, View
4. DBv1 첫 DBMapper, DB
5. 회원/게시판v3, v4, v6인증, 인가, 인터셉터
6. RESTv8, v9, v∞RestController, Ajax

👉 7 박스가 모두 자기 자리를 가지게 된 4 주.

📊 한 그림 정리

이번 차시의 데이터 흐름 — 「역방향」

화면
응답 JSON
DB 데이터
SQL 로그
서버 콘솔
F12 Network
4 주 동안 그려온 흐름이 거꾸로 흘러갑니다 — 디버깅의 본질

마지막 메시지

코드를 짜는 능력과 안 될 때 어디를 봐야 할지 아는 능력은 다른 기술입니다.

앞으로 어떤 새 프레임워크를 만나도, 어떤 새 언어를 배워도 — 「흐름도를 그리고 거꾸로 따라가기」의 사고는 똑같이 통합니다.

4 주 동안 흐름도를 손가락으로 짚는 연습을 해온 이유가 이것이었습니다.

🔄 4 주 전 / 4 주 후

4 주 전

웹사이트가 어떻게 동작하는지 막연. 코드 안 되면 막막.

v∞ — 오늘

7 박스 흐름도를 손가락으로 짚는다. 어디서 막혀도 5 단계 역추적으로 좁혀나간다.

REST API 게시판을 끝까지 만들어봤다.

정리 — 4 주 학습의 마무리

오늘 들고 가는 것

  • 버그 = 흐름도 어디선가 데이터가 막힌 것
  • 5 단계 역추적: F12 → 콘솔 → SQL 로그 → DB → 응답
  • 핵심 도구 5 가지를 한 번에 띄우고 점검
  • 한 번에 한 가지만 변경 / 단순한 케이스로 좁히기
  • 이게 4 주 학습의 종착점이자 새 시작점

다음 학습 — 더 큰 프로젝트, Spring Boot, JPA, 클라우드 배포 ... 흐름도는 같은 방식으로 자랍니다.