비개발자가 함수를 읽기 시작하는 순간 , 기능 단위가 처음 보인다 — 바이브 코딩 시즌 2 #2

1편에서 폴더 구조를 처음으로 구역별로 나눠봤다.

그 다음 자연스럽게 생기는 궁금증이 있다. "폴더는 알겠는데, 파일 안에 있는 코드는 어떻게 읽지?"

처음 page.tsx 같은 파일을 열어보면 코드가 수십 줄, 길게는 수백 줄까지 이어진다. 익숙하지 않은 사람 눈에는 전부 하나의 거대한 덩어리처럼 보인다. 어디서부터 어디까지가 하나의 기능인지, 어떤 부분이 중요한지 경계가 잘 보이지 않는다.

사실 비개발자에게 코드는 익숙한 문서 형식이 아니다. 글이라면 제목과 문단이 있고, 책이라면 목차가 있지만 코드는 처음 보면 그런 구조가 한눈에 들어오지 않는다.

특히 async로 시작하는 블록이나 function이라는 단어가 보이면 더 복잡해 보이기 마련이다. 처음에는 그저 알 수 없는 코드 묶음처럼 느껴질 수 있다.

그런데 코드를 읽는 가장 쉬운 방법이 있다.

바로 함수(Function)를 기준으로 보는 것이다.


함수가 뭔지 먼저 감을 잡자

함수는 "기능을 담은 상자"다.

버튼 하나를 누르면 뭔가 일어난다. 그 "뭔가"가 함수 안에 들어 있다. 버튼을 누르면 함수가 실행되고, 함수 안의 코드가 순서대로 돌아간다.

생김새는 이렇다.

function saveMemo(content) {
  // 메모를 저장하는 코드
}

function이라는 단어가 보이면 "여기서 기능 하나가 시작되는구나"라고 읽으면 된다. 괄호 안 content는 이 기능이 필요로 하는 재료다. 중괄호 {} 안에 실제 작업 내용이 들어간다.

지금 단계에서 중괄호 안을 다 이해하려 하지 않아도 된다. 처음 코드를 볼 때는 함수 이름만 훑어봐도 된다. 그것만으로도 어떤 역할을 하는지 생각보다 빠르게 파악할 수 있다.


함수 이름만 봐도 역할이 보인다

개발 세계에서 함수 이름은 대체로 정직하다.

"동사 + 명사" 구조로 짓는 게 관례다. 뭘 하는지(동사) + 무엇을(명사). 그래서 이름만 봐도 역할이 보이기 시작한다.

함수 이름 읽는 법
saveMemo() 메모를 저장한다
getMemos() 메모들을 가져온다
deleteMemo() 메모를 삭제한다
getUserById() ID로 유저를 찾는다
sendEmail() 이메일을 보낸다
formatDate() 날짜 형식을 바꾼다
handleSubmit() 제출을 처리한다

예를 들어 saveMemosave(저장) + Memo(메모). 두 단어를 읽는 것만으로 이 함수가 뭘 하는지 알 수 있다. 중괄호 안의 코드가 열 줄이든 백 줄이든 상관없다.

처음 코드를 열었을 때 이 함수 이름들이 눈에 들어오기 시작하면, 파일 전체를 안 읽어도 "이 파일은 메모 저장, 불러오기, 삭제를 담당하는구나"가 보인다. 여기서 많은 사람이 처음으로 "아, 코드가 대충 읽히네"를 경험한다.


함수인데 function처럼 안 생긴 경우

여기서 많은 사람이 혼란을 겪는다.

분명히 함수를 찾으라고 했는데, 파일을 열어보면 function이라는 단어가 보이지 않는 경우가 있다. 특히 Next.js 프로젝트에서 자주 나오는 패턴이다.

export async function POST(request) {
  // ...
}
const saveMemo = async (content) => {
  // ...
}

첫 번째는 앞에 export가 붙어있고, 두 번째는 아예 생김새가 다르다. 화살표(=>)가 나오는 두 번째 형태를 화살표 함수라고 부른다.

둘 다 함수다. 하는 일도 같다. 표기 방식만 다를 뿐이다.

지금 단계에서 둘의 차이를 이해하려 할 필요 없다. function이 보이거나, = async ( 같은 패턴이 보이거나, => {가 보이면 "여기 함수가 있구나" 정도만 인식하면 된다. 이름을 찾는 것도 같은 방식이다. POST, saveMemo — 함수 이름은 여전히 보인다.


async/await — "기다렸다가 결과 받기"

함수를 읽다 보면 앞에 async가 붙은 것들이 나온다.

async function saveMemo(content) {
  const result = await supabase.from('memos').insert({ content });
  return result;
}

asyncawait이 처음엔 낯설다. 이걸 보고 멈추는 경우가 꽤 있다. "이게 뭔지 이해해야 다음으로 넘어갈 수 있는 건가" 싶어지는 것.

카페에서 주문하는 상황을 떠올려보자. 주문을 넣고(요청을 보내고), 음료가 나올 때까지 기다렸다가(await), 음료가 나오면 받아서 마신다(결과를 받아서 처리한다). async function은 "이 함수 안에 기다리는 순간이 있다"는 표시고, await은 "여기서 결과가 올 때까지 기다린다"는 표시다.

내부 동작까지 이해할 필요 없다. async가 보이면 "기다리는 과정이 있는 함수구나" 정도만 알면 충분하다. Supabase에서 데이터를 불러올 때, 서버에서 응답이 올 때 — 기다림이 필요한 상황에서 붙는다는 것만 기억하면 된다.


실제 코드에서 함수 목록 뽑아보기

이제 시즌 1에서 만든 프로젝트의 파일을 하나 열어보자.

app/api/memos/route.tslib/supabase.ts처럼 데이터를 처리하는 파일을 선택한다.

열고 나서 AI에게 이렇게 요청한다.

이 파일에 있는 함수 목록을 뽑아줘.
각 함수가 하는 일을 한 줄로 설명해줘.
함수 이름과 설명만 표로 정리해줘.

그러면 AI가 이런 식으로 정리해준다.

| 함수 이름  | 하는 일                     |
|------------|-----------------------------|
| GET        | 저장된 메모 목록을 불러온다 |
| POST       | 새 메모를 저장한다          |
| DELETE     | 특정 메모를 삭제한다        |

파일 전체를 읽지 않아도 이 파일이 뭘 하는 곳인지 한 번에 보인다.


"이 함수가 하는 일을 한 줄로" — AI 활용 패턴

코드를 읽다가 모르는 함수가 나오면 통째로 AI에게 넘기는 경우가 많다.

더 좋은 방법이 있다. 함수 하나만 복사해서 이렇게 물어보는 것이다.

이 함수가 하는 일을 딱 한 줄로 설명해줘.
기술 용어 없이 설명해줘.

시즌 1에서는 "코드 만들어줘"로 요청했다면, 시즌 2에서는 "이 코드가 뭔지 설명해줘"로 활용 방향이 넓어지는 것이다.


함수 이름이 정직하지 않은 경우

AI가 생성한 코드에는 대부분 명확한 이름이 붙어 있다.

근데 오래된 프로젝트나 급하게 만든 코드를 열면 이런 이름들이 나온다.

function handleData() { ... }
function processThing() { ... }
function doWork() { ... }

이름만 봐서는 뭘 하는지 전혀 모른다. saveMemo는 두 단어로 역할이 보였는데, handleData는 "데이터를 처리한다"는 것 이상을 알 수 없다. 어떤 데이터를 어떻게 처리하는지가 없다.

이럴 때 당황하지 않아도 된다. AI에게 이렇게 요청하면 된다.

이 함수 이름이 모호한데, 하는 일을 명확하게 알 수 있는 이름으로 바꿔줘.

이름을 바꾸면서 동시에 이 함수가 뭘 하는지도 파악된다. 코드를 읽는 능력만큼, 모호한 코드를 더 읽기 좋게 만드는 것도 시즌 2에서 익혀가는 감각이다.


파일 안이 코드 덩어리로만 보이던 게, 함수 경계가 보이기 시작하면 달라진다.

전부 읽는 게 아니라, 함수 이름을 훑는 것. 그게 "코드를 읽는다"의 시즌 2 버전이다.

→ [3편: 컴포넌트 개념 입문 — 화면이 조각조각 나뉘어 보이기 시작한다](준비 중)

← 이전 글:  Next.js 폴더 구조, 처음으로 눈에 들어오기 시작한 순간


바이브 코딩 시리즈는 비개발자가 AI와 협업해 실제 서비스를 만들어가는 과정을 기록합니다.

0 댓글

댓글 쓰기

Post a Comment (0)

다음 이전