내가 생각하는 AI 시대에 살아남는 개발자가 되는 법
![]()
AI 시대에 살아남는 개발자가 되는 법
나는 GPT 3.5가 나왔을 때 개발을 시작했다. 처음부터 AI로 코드를 짜는 게 익숙했고, 모르는 건 AI에게 물어보면 됐다. 하지만 곧 이대로 가면 AI에게 잡아먹힌다는 것을 깨달았다.
계기
입사 4개월차에 당근 면접을 봤다. 떨어졌지만, 그 면접은 나의 개발에 대한 관점을 바꿔버렸다.
면접을 보며 깨달았다. 나는 리액트 개발자였지, 프론트엔드 개발자가 아니었다. 리액트를 쓸 줄 안다고 프론트엔드 개발자가 되는 게 아니었다. 라이브러리 사용법을 아는 것과 웹 개발을 이해하는 건 달랐다.
면접관 분께서 원하는 건 기술의 트레이드오프를 이해하고, 원론적인 개념을 아는 사람이었다. 나는 그 어느 것도 제대로 답하지 못했다. 기본을 더 다져야 한다고 생각했다.
구현만으로는 부족하다
초반에는 AI가 주는 코드를 복사-붙여넣기만 했다. 동작하면 됐다. 하지만 점점 문제가 생겼다.
AI가 준 코드가 왜 동작하는지 몰랐다. 에러가 나면 AI에게 다시 물어봐야 했다. 조금만 요구사항이 바뀌면 코드를 처음부터 다시 받아야 했다. 나는 단순히 AI의 복사기였다.
그때 깨달았다. 구현만 치중하면 AI와 경쟁할 수 없다. AI는 나보다 빠르고 정확하게 코드를 생성한다. 내가 할 수 있는 건 AI가 할 수 없는 것이어야 했다.
원론으로 돌아가다
HTML을 파싱하고 DOM 트리를 만들고 렌더링하는 과정. 네트워크 요청이 어떻게 오가는지. HTTP 프로토콜의 구조. TCP/IP가 무엇인지 등
이벤트 루프, 콜스택, 프로토타입 체인. React가 왜 선언형인지, Virtual DOM이 왜 필요한지, 상태 관리가 왜 복잡한지
React를 러프하게 직접 만들어보며 훅이 어떻게 동작하는지 이해하려 했다. useState가 클로저로 어떻게 상태를 기억하는지, useEffect가 어떻게 의존성 배열을 비교하는지 직접 구현해보니 보였다.
이런 걸 해보니 실제 개발에서도 도움이 많이 됐다. 상태를 변경하는 타이밍이 왜 중요한지, useEffect가 언제 실행되는지 더 정확히 이해할 수 있었다. AI가 준 코드를 그냥 쓰는 게 아니라 왜 그렇게 짜야 하는지 판단할 수 있게 됐다.
네트워크도 마찬가지였다. TCP 핸드셰이크 과정을 그림으로 그려가며 공부했다. SYN, SYN-ACK, ACK가 왜 필요한지, 3-way handshake가 왜 신뢰성을 보장하는지 직접 패킷 흐름을 따라가 보니 이해됐다.
개별적으로 공부하던 개념들이 하나씩 연결되기 시작했다. 브라우저 렌더링을 이해하니 React의 Virtual DOM이 왜 필요한지 보였다. 이벤트 루프를 알게 되니 비동기 상태 관리가 왜 복잡한지 이해됐다. HTTP를 공부하니 API 설계가 프론트 코드에 어떤 영향을 주는지 보였다.
AI에게 물어보면 답은 나온다. 하지만 이런 연결고리는 알려주지 않는다. 원론을 공부하며 각 개념이 어떻게 이어지는지 깨달았고 코드를 이해하는데 도움이 많이 됐다.
설계에 시간을 쓰다
반복적인 작업은 AI가 하고, 나는 비즈니스 로직과 설계에 시간을 쓰기로 했다.
처음엔 UI 컴포넌트에 모든 걸 넣었다. API 호출, 데이터 변환, 상태 관리, 렌더링 로직이 한 파일에 300줄씩 들어가 있었다. 이러다 보니 여러 책임이 한곳에 모여 있어서 각 부분이 뭘 의미하는지 파악하기 어려웠다. 새 기능을 추가하려면 어디를 고쳐야 할지 몰라서 매번 파일 전체를 읽어야 했다.
설계를 먼저 하기 시작했다. 컴포넌트를 어떻게 나눌 것인가, 상태를 어디에 둘 것인가, 데이터 흐름을 어떻게 설계할 것인가, 추상화는 어느 레벨에서 할 것인가.
데이터 로직은 훅으로 분리하고, UI는 presentational하게 만들고, 비즈니스 로직은 별도 함수로 빼냈다. 그러니 각 부분의 책임이 명확해졌고 테스트하기도 쉬워졌다. 확장성도 올라갔다.
이런 질문들은 AI가 대신할 수 없다고 생각한다. 요구사항을 이해하고 트레이드오프를 판단하고 미래의 변경을 예측하는 건 사람만이 할 수 있다고 느낀다.
AI에게 반복 작업을 맡기려면 명확한 설계가 필요하다. 이 컴포넌트는 무엇을 책임지는가, 이 함수는 어떤 입력을 받고 어떤 출력을 내는가. 설계가 명확할수록 AI가 생성한 코드의 품질도 올라갔다.
추상화를 배우다
처음에는 모든 코드가 구체적이었다. 이 버튼을 클릭하면 이 API를 호출하고 이 상태를 업데이트한다. 하나하나 다 적었다.
하지만 추상화를 배우면서 달라졌다. 반복되는 패턴을 발견하고 공통 로직을 분리하고 인터페이스를 정의하는 법을 익혔다.
추상화는 설계의 핵심이라고 생각한다. 무엇을 숨기고 무엇을 드러낼 것인가, 어떤 책임을 어디에 둘 것인가. 이런 결정들이 코드의 유지보수성과 확장성을 결정한다고 느낀다.
AI는 추상화를 제안할 수는 있지만 적절한 수준을 판단할 수는 없다고 생각한다. 과한 추상화는 복잡도를 높이고 부족한 추상화는 중복을 만든다. 이 균형은 경험에서 나온다.
프론트를 넘어서
프론트엔드만 알아서는 부족하다는 걸 깨닫고 있다고 생각한다. 백엔드를 모르면 API 설계를 이해할 수 없고, 데이터베이스를 모르면 쿼리 최적화를 논할 수 없고, 인프라를 모르면 배포와 스케일링을 이해할 수 없다고 느낀다.
아직 프론트엔드 외의 영역을 깊이 다뤄보지는 못했다. Dockerfile과 간단한 CI 정도만 짜봤을 뿐이다. 하지만 백엔드와 인프라 전반을 이해해야 한다고 생각한다.
프론트엔드 문제의 절반은 백엔드에서 해결된다고 생각한다. API 응답 시간이 느리면 프론트에서 아무리 최적화해도 소용없고, 데이터 구조가 잘못 설계되면 프론트 코드가 복잡해진다. 전체를 이해해야만 좋은 프론트엔드 개발자가 될 수 있다고 믿는다.
시스템 디자인을 생각하다
프론트엔드, 백엔드, 데이터베이스, 캐시, 큐, CDN 이 모든 것이 어떻게 연결되고 어떻게 상호작용하는지 이해해야 한다고 생각한다.
시스템 디자인은 트레이드오프의 연속이라고 느낀다. 성능과 일관성, 가용성과 비용, 복잡도와 유지보수성. 정답은 없고 상황에 맞는 선택만 있다고 생각한다.
이런 사고방식은 프론트엔드 설계에도 필요하다고 느낀다. 컴포넌트 설계도 시스템 디자인이고, 상태 관리도 시스템 디자인이고, 데이터 흐름도 시스템 디자인이라고 생각한다.
AI는 코드를 짜지만 시스템을 설계하지는 못한다. 요구사항을 이해하고, 제약을 파악하고, 트레이드오프를 판단하는 건 사람의 몫이라고 믿는다.
AI 시대의 개발자
AI는 점점 더 좋아진다.
구현은 AI에게 맡기고 개발자는 설계를 해야 한다고 생각한다. 원론을 이해하고 추상화를 설계하고 시스템을 바라보는 것. AI가 생성한 코드를 이해하고 판단하고 개선하는 것.
AI 시대의 개발자는 코드를 짜는 사람이 아니라고 생각한다. 문제를 정의하고 솔루션을 설계하고 트레이드오프를 판단하는 사람이어야 한다고 느낀다.
역할을 하나의 영역에 가두지 말아야 한다고 생각한다. 프론트엔드 개발자이지만 백엔드를 이해하고 인프라를 배우고 싶다. 시스템을 설계할 수 있고 기술 스택을 넘나들 수 있어야 한다고 믿는다.
AI는 도구다. 강력한 도구지만, 도구일 뿐이며 도구를 잘 쓰는 사람이 살아남는다고 생각한다.
여전히 비즈니스 로직을 구현하고, 추상화하고, 설계를 하는 데 여전히 애로사항을 겪고 있다. 하지만 격동적으로 변하는 AI 시대에 이 길이 옳다고 믿는다.
설계에 더 집중하고, 회사의 요구사항과 기술의 트레이드오프를 고려하고, 현실적인 상황을 파악해서 올바른 선택을 할 수 있는 개발자가 되도록 노력하겠다.