What I Actually Learn When I Build With AI
AI와 만들면서 실제로 배우는 것
AI로 기능을 완성하는 일과 작동 원리를 배우는 일은 다릅니다. 글쓴이는 Slate 편집기의 저장 경쟁 조건과 로컬 AI 모델의 실행 시간을 직접 조사한 경험을 들어, 생성된 코드를 이해하고 다른 문제에 적용하는 학습 방식을 설명합니다.
- 주제
에디터 노트
이 글의 주장은 기능을 완성하는 일과 원리를 익히는 일을 구분하자는 데 있고, Slate 사례가 그 차이를 구체적으로 보여 줍니다. 댓글은 저장 revision 테스트를 확인한 데서 그치지 않고 파일 쓰기 도중 종료될 때의 손상 가능성까지 짚었습니다. 글쓴이도 설정 파일의 원자적 쓰기 구현을 인정하며 추가 조사 대상으로 받아들였습니다. 이 사례는 문제를 알아보는 학습이 실제 코드 검토에서 더 깊어질 수 있음을 보여 줍니다. 다만 원자적 교체에는 권한과 링크, fsync 조건이 따른다는 지적도 댓글에 함께 있습니다. 따라서 문서 저장에 같은 구현을 적용하면 된다고 단정할 수는 없습니다. 글의 학습 방식은 유효한 출발점이지만, 해결책은 구체적인 파일 시스템 조건까지 확인해야 합니다.
AI 요약
AI 코딩 도구로 밤새 기능을 만들고도 코드 절반을 설명하지 못한 적이 있습니다. 반대로 작은 문제 하나를 오래 파고들며 더 많이 배운 날도 있습니다. 둘 다 작동하는 결과물을 만들었지만, 결과물을 얻는 일과 작동 원리를 이해하는 일은 같지 않습니다. AI의 설명을 따라갈 때는 이해했다고 느껴도 며칠 뒤 코드를 다시 보면 낯설 수 있습니다. 글쓴이는 문법을 외우는 것보다 왜 특정 방식으로 문제를 풀었는지 아는 일이 중요하다고 말합니다.
저장 중에 문서가 바뀌는 문제
글쓴이가 만드는 텍스트 편집기 Slate에서는 저장이 진행되는 동안 사용자가 계속 입력할 수 있습니다. 저장이 시작될 때의 문서 내용은 현재 내용보다 오래됐는데, 저장이 끝났다는 이유로 편집기가 미저장 표시를 지우면 실제로는 저장되지 않은 변경 사항까지 저장됐다고 알리게 됩니다. Slate는 저장 시작 시점의 문서 revision을 기록하고, 저장 중 생긴 변경 사항은 저장 완료로 처리하지 않도록 합니다.
이 사례에서 글쓴이가 얻으려는 것은 revision 추적 코드 자체보다, 작업이 시작된 뒤 끝나기 전에 상태가 바뀔 수 있다는 문제 형태입니다. 이 관점은 다른 애플리케이션의 비동기 작업에도 적용됩니다. 사용자가 상태를 바꾼 뒤 비동기 작업이 완료되는 상황이나, 성능 문제처럼 보이는 지연이 실제로는 모델을 메모리에 불러오는 시간인지 구분하는 상황이 예입니다.
설명보다 실험으로 확인하기
로컬 AI 모델이 작업을 끝내는 데 30초가 걸렸다면, 전체 시간이 모델 로딩에 들었는지 실제 처리에 들었는지 나눠 측정할 수 있습니다. 두 번째 실행이 더 빨라지는지도 시험할 수 있습니다. 글쓴이는 AI에게 원인을 설명해 달라고 묻는 일도 유용하지만, 다시 실행하고 측정값을 나눠 보고 조건을 바꾸는 실험이 실제 동작을 파악하는 데 도움이 된다고 말합니다. 결과가 예상과 다를 때는 그 차이를 조사할 단서가 생깁니다. AI의 설명이 틀릴 수도 있으므로 설명과 관찰 결과를 구분해야 합니다.
글쓴이는 구현을 그대로 기억하지 못하더라도, 해결하려던 문제와 선택한 이유를 이해하면 그 지식을 다른 프로젝트로 가져갈 수 있다고 설명합니다. 생성된 코드를 받아들이기만 하면 비슷한 문제를 다른 맥락에서 알아보지 못할 수 있습니다. 반면 익숙하지 않은 기능이나 나중에 직접 유지보수할 코드는 질문하거나 동작을 바꿔 보며 이해하려고 합니다. 실행 전에 변경 결과를 예상하고 실제 결과와 비교하는 방법도 제안합니다.
모든 작업을 학습 과제로 만들 필요는 없습니다. 버튼 여백 조정이나 반복 작업, 이미 여러 번 해 본 일은 AI에 맡길 수 있습니다. AI 덕분에 낯선 언어나 프레임워크를 시도하기 쉬워진 점은 긍정적으로 보면서도, 기능을 계속 추가하는 일이 학습으로 착각될 수 있다고 말합니다. 글쓴이는 모든 코드를 깊이 조사하지는 않으며, 작업을 끝내고 넘어가고 싶은 순간도 있다고 솔직히 덧붙입니다.
dev.to 반응
- @pierrelaurentmedori — Slate 저장 사례를 보고 저장소를 확인했습니다. 문서 revision counter는 document.rs에 있고 edits_during_a_save_keep_the_document_dirty라는 테스트가 문제를 고정해 둡니다. 코드를 잊더라도 테스트가 문제를 기억하게 해 준다는 점이 좋습니다. 아직 하나 더 있습니다. 앱이 쓰기 도중 종료되면 디스크에는 무엇이 남을까요? write_text는 std::fs::write를 호출하고, 이 함수는 쓰기 전에 파일을 비웁니다. 적절하지 않은 순간에 충돌하거나 전원이 끊기면 파일 일부만 남을 수 있습니다. 흥미롭게도 settings JSON을 쓰는 storage.rs에는 임시 파일을 쓴 뒤 이름을 바꾸는 write_atomic이 이미 있습니다. 지금은 문서보다 설정 파일이 더 잘 보호됩니다. 그렇다고 사용자 파일에 그대로 적용하면 끝나는 것은 아닙니다. 원본을 대체하는 이름 변경은 권한, 심볼릭 링크, 하드 링크를 고려해야 하고 전원 차단 뒤에도 안전하게 남기려면 이름을 바꾸기 전에 fsync해야 합니다. Vim에 backupcopy 설정이 따로 있는 것도 이런 절충 때문입니다. 저도 비슷한 문제를 겪었습니다. API가 삭제를 확인해 놓고 바로 다음 조회에서 삭제한 항목을 반환했습니다. '쓰기가 성공했다'와 '모두가 그 결과를 볼 수 있다'는 서로 다른 시점이었고, 그 간격을 계속 살펴보게 됐습니다.
- @sizzlebop — 저장소를 직접 살펴보고 제가 생각하지 못한 점을 알려 주셔서 정말 감사합니다. 글을 읽는 것과 실제 코드를 찾아보고 놓친 부분을 짚어 주는 것은 다릅니다. 설정에 이미 원자적 쓰기 구현이 있다는 점까지 맞습니다. 또 조사할 문제가 생겼습니다. 공개적으로 프로젝트를 공유하면 실제로 코드를 이해한 사람에게 피드백을 받을 수 있다는 점이 좋습니다. API 삭제 사례도 글에서 말한 문제를 잘 보여 줍니다. 코드는 잊어도 직접 만난 작은 상황은 오래 기억에 남습니다.
- @pierrelaurentmedori — 도움이 됐다니 기쁩니다. 서로 도움이 되는 일입니다. 다른 사람들이 제가 겪는 문제를 어떻게 푸는지 궁금합니다. 풍부한 경험이고, 때로는 다른 사람도 같은 생각에 도달했다는 점에서 안심이 되기도 합니다.
- @urion — 저장 사례에서 배울 점은 코드가 아니라 문제의 형태입니다. 작업이 시작되고 끝나기 사이에 무언가 바뀔 수 있습니다. 한 번 알아차리면 사용자가 이미 다른 화면으로 이동한 뒤 fetch가 완료되거나, 첫 시도가 성공한 뒤 재시도가 도착하는 상황에서도 발견하게 됩니다. '며칠 뒤 코드를 다시 보면 처음 보는 것 같다'는 문제에는, 어떤 코드가 왜 필요한지 이해했을 때 그 이유를 자기 말로 짧게 적어 두는 방법이 도움이 됩니다. AI가 해 준 설명이 아니라 코드가 해결하는 문제를 적습니다. 다음에 파일을 열면 메모가 남아 있습니다. 그 이유를 적을 수 없다면 코드가 아니라 설명만 이해했을 가능성이 큽니다. 저는 이런 메모를 코드 줄에 남기는 IDE Reado를 만들고 있어 이 습관에 편향이 있습니다.
- @sizzlebop — 코드가 하는 일을 설명하는 대신 코드가 해결하는 문제를 적으라는 부분이 좋습니다. 저도 더 자주 해야 할 것 같습니다. 서로 다른 상황에서 같은 문제를 알아보는 일이 글에서 말하려던 학습입니다. 왜 중요한지 이해하면 생각하지 못했던 곳에서도 그 문제가 보이기 시작합니다.
- @pushpendra2011 — 코드보다 문제를 기억한다는 문장이 와닿습니다. 저는 임베딩을 사용하는 추천 앱을 만들며 배웠습니다. 각 항목에는 LLM이 쓴 설명과 벡터가 있고 둘 다 버전 번호를 가집니다. 처음에는 과하게 설계한 것처럼 보입니다. 하지만 프롬프트나 임베딩 모델을 바꾸고 나면 데이터 절반은 한 방식으로, 나머지 절반은 다른 방식으로 생성됐는데 각 행에서 무엇으로 만들었는지 알 수 없습니다. 저장 revision 문제와 비슷하게 파생 데이터가 생성 근거와 조용히 달라지는 사례입니다. 이제 생성된 데이터를 저장할 때마다 '무엇이 이 데이터를 만들었고, 그것이 바뀌었을 때 어떻게 알아차릴까?'를 먼저 묻습니다.
- @sizzlebop — 모델이나 프롬프트를 바꾸고 나서 어떤 데이터가 무엇으로 생성됐는지 모르면 versioning이 왜 필요한지 알게 된다는 점이 좋은 예입니다. 특히 AI 생성 데이터에서는 모델과 프롬프트가 시간이 지나며 바뀔 수 있으니 '무엇이 만들었고, 무엇이 바뀌었는지 어떻게 알 수 있을까?'라는 질문이 유용합니다.
- @build996 — 실행 전에 변경 결과를 예상하자는 제안에 며칠 뒤 작은 변형을 시험하는 방법을 덧붙이고 싶습니다. Slate라면 저장 두 건이 반대 순서로 완료될 때 미저장 표시가 어떻게 보여야 하는지 예측해 볼 수 있습니다. 첫 사례를 설명하는 일에는 기억이 도움을 줄 수 있지만, 변형을 예측하면 원리를 다른 상황에 적용할 수 있는지 확인하게 됩니다. 이런 확인이 학습에 도움이 될까요, 아니면 취미 프로젝트를 숙제로 만들까요?
- @sizzlebop — 배운 내용을 조금 다른 상황에 적용하는 일이 원래 사례를 설명하는 것보다 이해도를 더 잘 확인할 수 있다는 점이 좋습니다. 모든 일에 적용하지 않는다면 유용한 학습 점검이 될 것 같습니다. 다시 만날 가능성이 큰 개념이거나 전에 이해하지 못한 부분이라면 며칠 뒤 변형을 시도해 보는 방법을 써 보고 싶습니다.
원문: dev.to / 번역·요약: Trawling