에러, 찾지 말고 일부러 만드세요!
요약
- 책이나 강의에서는 잘 되는 경우만 알려주지만, 자주 발생하는 에러, 실수를 해결하는 것도 중요한 능력입니다.
- 새로운 걸 공부하는 일부러 오타를 내거나, 빼먹거나, 바꿔보면서 에러를 내는 연습을 해봅시다.
- 어떤 경우에 어떤 에러가 발생하는지 보고, 생각하고 찾아보면 많은 걸 배울 수 있습니다.
에러 찾기는 왜 힘들까?
한 98년도 연구에 따르면, 개발자들은 21%의 시간을 디버깅에 쓴다고도 합니다.
체계적 훈련을 거친 고수들은 금방 에러를 찾아내지만. 초보자들은 그렇지 않습니다. 에러 하나 때문에 3일 넘게 고민하시는 경우도 많이 보았습니다. 저도 에러 하나 때문에 1주일 동안 삽질한 기억도 있습니다.
왜 에러 찾기는 어려울까요? 그 이유 중 하나는 잘못된 관점에 고착되기 때문입니다. 전에 고착에서 빠져나와 창의적 통찰을 얻는 법이라는 글을 쓰면서, 이런 창의적 절망을 탈출하는 법을 다뤘습니다.
하지만 이번에는 다른 방향으로 이야기를 해보려 합니다. 바로 잘 되는 경우만 배웠지, 실수하고 잘못되는 경우에 대해서는 배우지 못해서 그렇다는 것입니다.
오타는 멍청한 실수가 아닙니다.
코칭을 하다보면, 디버깅을 해드리는 일이 많습니다. 3일 동안 고생한 문제를 "15분 안에 원인을 찾겠다"고 호언장담을 하고, 해결해드린 적이 여러 번입니다.
왜 그렇냐면, 보통 에러의 원인이 그렇게 거창하지 않기 때문입니다.
- 문자열이나 변수명에 오타를 냈다거나.
response
를respose
로 쓴다거나.form
이랑from
을 헷갈린다거나.user
를uesr
으로,name
을nama
로'http://localhost:3000/test'
인데 -'http://localhost:3000//test'
로 된다거나.
number
타입 자리에string
type인 값을 넣었다거나. e.target.value 같은.- return을 빼먹었다거나.
(v) => (v*2)
로 쓸 것을() => {v*2}
로 써서 return이 안 된다거나. - 버전 실수. 책에서는 6버전을 쓰는데, 나는 최신 7버전을 설치했다거나.
- (책에 6버전을 설치하라고 굵은 글씨에 빨간색으로 적혀 있는데도!)
- 괄호를 엉뚱한 곳에서 닫았다거나.
- HMR이나 서버 재시작이 제대로 이뤄지지 않는데, 착각하고 있다거나.
- 개발 서버가 아니라, 배포 서버에 접속한 상태에서 코드 변경 사항이 왜 반영되지 않지? 한다거나.
문제는, 똑같이 실수라고 해도 에러의 종류는 매번 다르다는 것입니다.
- url의 path를 잘못 치면
404 NOT FOUND
- 변수명에 오타를 내거나, import를 빼먹으면
Uncaught ReferenceError: a is not defined
- 리액트에서 컴포넌트의 return 문을 빼먹으면 화면에 컴포넌트가 보이지 않습니다.
- 최신버전에서 구버전의 함수를 import하려 하면...
Module '"react-router-dom"' has no exported member 'Switch'
처럼 에러가 뜹니다.
- 모듈을 import하는 경로를 잘못 쓰면
Cannot find module 'src/createDataList' or its corresponding type declarations.
- 테스팅 라이브러리에서 Element를 찾지 못하면
Unable to find an accessible element with the role "button" and name "어둠"
책, 강의, 블로그를 똑같이 따라 했는데 안 돼요!
이런 에러를 처음보면 'module'이나 'export', 'reference', '404' 같은 단어들에 주눅 들고 겁을 먹기 쉽습니다.
코칭을 하다보면 "똑같이 따라했는데 안 된다!"고 말하는 분이 많습니다. 최선을 다해 노력했다고 입증하지 않으면 누가 혼을 내는 모양입니다. (정말 그렇긴 하죠) 전에 보니 "제발 에러 메세지 좀 읽으세요" 훈계하는 영상을 올리신 분도 보았어요.
책이나 강의에서는 잘 되는 경우만 보여줍니다. 강사나 저자는 척척 문제를 해결하고. 흔히 하는 실수나 오개념은 넘어가고는 합니다.
그러다보니 초보자는 똑같이 따라한다고 해도 잘 되지 않습니다. 오타를 내고, 해야하는 걸 빼먹고, 에러 메세지를 보면 겁부터 먹고 잘 읽지 않는 것은... 게을러서도 멍청해서도 아닙니다. 아주 자연스러운 반응입니다.
에러에 대처하는 법을 배운 적이 없으니까요!
그러면 에러가 났을 때 검색해보는 것보다 나은 방법이 없을까요?
에러를 내보면서 실험을 하자
제가 예전에 데이터 분석을 공부하던 시절에, 파이썬 책들을 여럿 보았습니다. 그 중에 [Think Python]이라는 책에서는, 각 장이 끝날 때마다 디버깅 연습을 시켰습니다.
예를 들어 변수 선언하는 법을 처음 배웠다고 해봅시다. 초보자는 변수명에 띄어쓰기를 넣거나, 문자열을 따옴표로 감싸주는 걸 까먹고는 합니다. bad name = Hello world
처럼요. 이러면 python에서는 SyntaxError: invalid syntax
가 뜹니다. javascript에서는 어떨까요?
Uncaught SyntaxError: Unexpected identifier 'name'
라고 더 자세히 뜨네요. 변수나 함수의 이름을 말하는 식별자(identifier) 개념을 모르면 왜 name
이 unexpected라고 하는지 잘 모를 겁니다. 책에서는 친절하게 띄어쓰기를 넣으면 두 개를 별도의 변수로 취급한다고 설명해줍니다. bad
라는 이름과 name
이라는 이름이 따로 있는 거라고 생각하는 거죠.
이렇게 디버깅을 하다 보면 자연스럽게, 그 언어의 중요한 개념을 더 깊이 있게 알게 됩니다. 이해하기도 쉽습니다. 원인을 초래한 게 나 자신이니까요. 물론 책이나 강의에서 이렇게 설명해준다면 더 좋겠지요.
또 [Python과 Pygame으로 게임 만들기]이라는 책도 봤었는데요. 이 책은 예시 코드 뿐만 아니라, 에러가 있는 코드도 주고 버그를 찾는 연습을 시켰습니다. 그리고 두 코드의 차이를 보여주는 diff 툴을 이용해서, 예시 코드와 자신의 코드에 어떤 차이가 있는지 비교해보라고도 했지요.
이런 연습은 누구랑도 할 수 있습니다. 두 명이 짝을 지어서, 일부러 에러를 심어놓고 제한 시간 동안 서로 찾아보게 하는 거지요. (너무 오래 삽질하는 걸 예방하기 위하여)
자기가 한 번 구현한 코드를 지워놓고, 빠르게 다시 구현해보는 것도 방법입니다. 그 뒤에 git diff를 보면 내가 어느 부분을 다르게 구현했고 실수했는지 쉽게 알 수 있겠죠.
diffr처럼 온라인에서 사용하실 수 있는 diff 도구도 있습니다.
실험 제안
에러 내보기 실험은, 여러모로 좋은 학습 도구입니다. 특히 어떤 문법이나 프레임워크라도 배우고 나면 실수할 가능성을 생각해보세요! 구체적으로 상상이 안 가시는 분들을 위해, 뭉텅이로 아이디어를 늘어놓아 볼게요.
- 곳곳에
console.log
나print
를 찍어놓고, 망가트려보세요. []{}()
같은 괄호를 만나면, 다른 괄호를 치면 무슨 일이 일어나는지 살펴보세요.- 괄호를 두 번 쳐보거나, 지우거나, 혼합해보세요.
[1,2,3,4].map((n) => n*n)
[1,2,3,4].map((n) => {square: n*n})
[1,2,3,4].map((n) => ({square: n*n}))
- 브라우저에서 F12를 치면 나오는 콘솔에 이것저것 적어보세요
- 글자를 지웠을 때 syntax highlighting, 그러니까 코드의 색이 어떻게 변하는지 살펴보세요.
- 헷갈리는 다른 값을 넣어보세요.
- "authorId" 자리에 "userId"를 넣는다거나.
- 똑같은 이름을 가진 다른 라이브러리의 함수를 잘못 import해보세요.
- 순서나 대소문자를 바꿔보세요.
domain.User.nick
을Domain.User.nick
으로 쓴다거나. - 매개변수 개수를 일부러 틀려보세요.
- 코드를 망가트렸는데, type도 test도 runtime error도 안 나고 그저 이상한 값만 나오는 경우를 만나 보세요!
- 이런 로직 에러를 미리 예방할 방법을 찾아보세요
- 예를 들어 typescript를 쓴다면
literal union
이나string template
을 알아보세요. - tiny-invariant나 assert, 단언에 대해 알아보세요.
- typescript를 사용한다면, type을 배신하는 값을 받아보세요.
- 예를 들어 as 쓰는 곳에 잘못된 타입의 값을 넣어보세요.
- zod나 ajv, typia 같은 도구를 알아보세요
- 자동화 도구도 좋지만 [탐험적 테스팅] 같은 책을 보면서, 체계적으로 수동 테스트 하는 방법을 배워보세요.