이 글은 개발 강의라기보다 제가 실제로 헷갈렸던 부분 → AI에게 다시 물어본 내용 → 제가 이해한 방식 순서로 적어두는 기록에 가깝습니다.

일단 문제의 코드

예시로 AI에게 “주소를 받아서 JSON 데이터를 가져오는 함수”를 만들어달라고 했더니 대충 이런 구조를 줬다고 해보겠습니다.

JAVASCRIPT / SAMPLE
async function loadJson(url) {
  if (!url) {
    throw new Error("URL is required");
  }

  try {
    const response = await fetch(url);

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error("Failed to load JSON:", error);
    throw error;
  }
}

처음 보면 이런 생각부터 듭니다.

그냥 fetch(url) 하고 JSON으로 바꾸면 되는 거 아닌가? 왜 검사하고, 에러 만들고, 잡았다가 다시 던지는 걸까?

제가 이해한 바로는, 대부분 ‘망했을 때 어디서 망했는지 알려주는 장치’였습니다

01 · INPUT CHECK

if (!url)

제가 이해한 바로는 문지기입니다. 주소도 안 줬는데 인터넷에 나가려고 하면 여기서 먼저 막습니다.

02 · WAIT

await fetch(url)

인터넷 응답이 올 때까지 이 함수 안에서 결과를 기다립니다. 결과가 오기 전에 다음 줄로 달려가지 않게 합니다.

03 · HTTP CHECK

response.ok

서버가 답장을 했다고 무조건 성공은 아니라서, 404나 500 같은 실패 답장인지 한 번 더 확인합니다.

04 · ERROR HANDLING

try / catch

중간에 사고가 나면 조용히 죽는 대신 어디서 실패했는지 흔적을 남길 수 있게 하는 구간으로 이해했습니다.

그런데 하나는 다시 물어봤습니다

catch에서 에러를 잡았는데 마지막에 다시 throw error를 합니다. 이게 제일 이상했습니다.

제가 이해한 답은 이렇습니다. 여기서는 로그만 남기고, 이 함수를 호출한 바깥쪽에도 ‘실패했다’는 사실을 전달해야 할 수 있기 때문입니다. 여기서 에러를 먹어버리면 바깥에서는 성공한 줄 착각할 수도 있습니다.

다만 console.error만 찍고 그대로 다시 던지는 코드가 정말 필요한지는 프로젝트 구조에 따라 다릅니다. 바깥에서도 같은 에러를 기록한다면 로그가 두 번 찍힐 수도 있습니다.

AI가 넣었다고 다 필요한 건 아니었습니다

AI가 안전하게 짜달라는 의도를 알아서 추측하다 보면 방어 코드를 많이 넣을 수 있습니다. 문제는 그걸 이해하지 못한 채 복사하면, 나중에 에러가 났을 때 어느 부분을 지워도 되는지도 모른다는 겁니다.

그래서 코드 하나를 받을 때 최소한 아래 정도는 확인해보려고 합니다.

  1. 이 부분이 없으면 실제로 뭐가 망하는가?
  2. 정상 상황이 아니라 실패 상황에서는 어떻게 움직이는가?
  3. AI가 습관적으로 과하게 넣은 코드가 있는가?
  4. 직접 실패를 만들어서 확인할 수 있는가?

직접 실패시켜보니까 제일 빨리 이해됐습니다

  • 빈 문자열을 넣어 입력 검사가 진짜 먼저 막는지 확인
  • 없는 주소를 넣어 네트워크 실패가 어디로 들어오는지 확인
  • 404가 나는 주소를 넣어 response.ok가 왜 필요한지 확인
  • throw error를 잠깐 빼보고 호출한 쪽에서 차이가 나는지 확인

코드를 외우는 것보다 “이 줄은 어떤 사고를 막으려고 있는 놈인가?”라고 생각하니까 훨씬 이해하기 편했습니다. 다음에는 실제 프로젝트 코드 하나를 이런 식으로 다시 뜯어볼 생각입니다.