생성형 AI는 개발 문화를 어떻게 바꾸는가?

김희섬

Is it okay to let AI review my code?

ChatGPT에게 “난수를 생성해줘”라고 요청하면, “42”라는 숫자를 반환해주던 때가 있었다. 기본적으로 거대언어모델(LLM, Large Language Model)은 입력 문장에 대해 다음 단어를 예측하는 방식으로 학습되었고, 숫자 “42”는 많은 인터넷 커뮤니티의 다양한 맥락에서 등장했기 때문에1 어쩌면 이 대답은 배운대로 성실히 작성한 답안일지도 모른다. 같은 질문을 최근 모델에게 던지면 이제는 제법 그럴듯한 난수를 만들어서 응답한다. 아마도 내부적으로 유사 난수 생성 함수를 실행하여 답하는 것일 수도 있다. 챗GPT의 초기 버전이 2022년 11월에 출시 되었으니, 사용자의 질의 의도를 꽤 정확히 이해하고 실행하는데 까지 3년도 걸리지 않은셈이다. 대중들은 마치 사람과 대화하는 것처럼 생성형 AI(generative AI)를 사용하기 시작했고, 개발자들의 일하는 방식도 대화형 인터페이스에 따라 크게 변하기 시작했다. 간단하게는 코드의 주석을 작성하거나 변수 이름을 지을 때 생성형 AI를 이용했고, 좀 더 나아가서는 단위 테스트 작성 또는 일부 비즈니스 로직까지도 생성형 AI로 작성하는 사례를 찾을 수 있게 되었다. 

이런 시도는 “코드 리뷰 자동화”에 까지 이르게 되었는데, 이는 그동안 개발자들이 “코드 리뷰”에 대해 양가감정을 느끼고 있었기 때문이다. 어떤 개발자는 같은 프로젝트에 참여하는 개발자 간의 코드 리뷰가 좋은 개발 문화를 만들기 위해 꼭 필요한 절차라고 얘기한다. 이들은 서로의 코드를 읽어가면서 전체 프로젝트를 더 깊이 이해하고 더 좋은 코드를 작성할 수 있게 된다고 믿는다. 반면, 코드 리뷰의 필요성에는 동의하면서도, 심도 깊은 리뷰는 데드라인이 정해져 있는 실무 환경에서 사실상 하기 어렵고 너무 이상적인 요구라고 주장하는 사람들도 있다. 양 쪽 모두 코드 리뷰가 “제대로” 이루어 진다면 좋은 소프트웨어를 만드는 데에 큰 도움이 된다는 점에서는 이견이 없다. 그래서 업계에서는 종종 코드 리뷰가 얼마나 잘 수행되고 있는지가 그 팀 또는 회사의 “개발 문화”를 측정하는 척도가 되기도 한다. 

그렇다면, 좋은 개발 문화는 어떻게 정의할 수 있을까? 코드 리뷰가 잘 된다면 좋은 개발 문화일까? 이 글에서는 코드 리뷰로 대표되는 “좋은 개발 문화”의 특성을 짚어보고, 결국 좋은 소프트웨어를 개발하려면 개발자들의 소통 방식이 중요하다는 전제를 다시 발견한다. 이어서 생성형 AI가 이 전제를 어떻게 강화하는지 살펴 보면서, 소프트웨어 업계에도 시대의 변화에 상관없이 본질로 추구할 수 있는 가치가 있는지 고민해 본다.

Q: “개발 문화”는 어떻게 정의할 수 있을까? A: 소프트웨어는 그것을 만드는 사람들을 닮는다

혹자는 종종 소프트웨어를 건축에 빗대어 설명한다. 이런 비유는 오랫동안 개발자들의 일하는 방식에도 영향을 미쳤고 “워터폴(waterfall)” 방식이라는 훌륭하지만 철지난 방법론이 표준으로 자리잡는데 일조했다. 워터폴은 설계, 구현, 테스트 등의 개발 단계를 순차적으로 완성하는 선형적인 개발 방식인데, 확실히 설계에서 시공에 이르는 건축의 과정과 비슷한 면이 있다. 건축물의 완성도가 설계도에 크게 의존하듯이 워터폴 방식으로 소프트웨어를 만들때는 초기 설계와 작업의 난이도 추정(건축에서 공기[工期] 를 추정하는 것과 유사하다)이 굉장히 중요하다.

시대가 변하면서 소프트웨어의 복잡도 역시 과거와는 비교하기 어려울 정도로 크게 올라갔고, 워터폴 방법론을 비판하는 새로운 방법론이 등장했다. 이 방법론을 주장한 사람들이 모여서 “애자일 매니페스토”(agile manifesto)라고 부르는 선언문을 작성해서 발표했는데, 거기에 따르면 애자일 방법론은 좁은 의미의 “일하는 방식”이 아니라 좋은 소프트웨어를 만들기 위해 지켜야 하는 “준칙”에 가깝다. 애자일 방법론에 따르면, 작은 단위의 완결된 프로그램을 개발하고 고객 또는 사용자로부터 오는 의견을 빠르게 반영하여 지속적으로 개선할 때 비로소 좋은 소프트웨어가 만들어진다. 

두가지 개발 방법론 모두 성공 사례와 실패 사례를 충분히 나열할 수 있다. 흥미로운 점은 반대되는 성격의 두 개발 방법론의 성공 조건을 이야기 할 때 중요하게 언급되는 내용이 유사하다는 점이다. 두 방법론 모두 요구사항의 정의와 소통방식을 중요하게 다룬다. 워터폴에서는 흔히 WBS(Work Breakdown Structure)라고 부르는 차트를 통해 프로젝트의 진척도를 관리하는데, 이 WBS 차트에 나열되는 세부 항목들이 요구사항을 빠짐없이 반영하고 있어야 한다. 잘못 작성된 WBS 차트는 마치 결함 있는 설계도처럼 소프트웨어의 완성도에 치명적인 영향을 미친다. 그래서 워터폴 방식의 프로젝트에서는 WBS 차트를 구체화 하는 초기 설계 단계에서 프로젝트 참여자들 사이의 밀도 있는 소통이 이루어지고, 이 때 소프트웨어의 꽤 많은 것들이 결정된다.

반면, 애자일에서는 “스프린트(sprint)” 라는 작업 기간을 단위로 일을 나눈다. 보통 2주가 하나의 스프린트에 해당하고, 각 스프린트 마다 완성되어야 하는 “작지만 완결된” 작업 단위를 미리 정의한다. 애자일 팀에서는 “스크럼(scrum)”을 통해서 스프린트의 진척도와 완성도 등을 공유한다. 통상 스크럼은 프로젝트 실무자들이 참여하는 가벼운 회의(10분~15분 정도 소요)를 의미하고, 프로젝트의 의사결정권자가 참석하지 않거나 참석하더라도 발언권이 없는 경우가 많다. 의사결정의 병목을 줄이고 빠르게 실행한다는 애자일 방법론의 철학이 드러나는 대목이다. 서로 다른 전제에서 출발하는 두 방법론이 비슷한 성공 요건을 제시하는 것을 보면, 개발자들이 소통하는 방식은 소프트웨어 개발에서 굉장히 중요한 요소로 다뤄진다고 볼 수 있다.

“소프트웨어는 그것을 만드는 사람들을 닮는다.” 업계의 이 오랜된 격언을 처음 얘기했던 사람은 뛰어난 해커이자 프로그래머였던 멜빈 콘웨이(Melvin Conway)였다. 그가 “콘웨이의 법칙”으로 불리는 이 격언을  제시했던 배경에는 “소프트웨어 구조가 조직 구조를 반영한다”는 생각이 있었다. 조직 구조는 일하는 사람들의 소통 구조와 같은 의미이므로, 달리 표현한다면 “개발자들의 소통 구조가 소프트웨어에 반영된다”고 할 수 있다. 최근에는 “소통 구조”의 외연이 더 확장되어, 일하는 방식을 전부 포괄하는 의미로서 “개발 문화”라는 개념이 통용되고 있다. 

어떤 팀이나 회사의 개발 문화가 좋은지 판단 하는 기준이 명시적으로 정해져 있지는 않다. 테스트 파이프라인이 자동화 되어있는지, 얼마나 자주 새로 작성된 코드가 제품에 반영되는지 등 기술적인 측면에서 개발 문화를 가늠하는 사람도 있고, 일관된 코딩 규칙(코딩 컨벤션; coding convention)이 있는지, 코드 리뷰가 어떻게 이루어지는지 등 좀 더 정성적인 측면에서 개발 문화를 판단하는 사람도 있다. 개발 문화를 어떤 기준으로 정의할 수 있을지는 모호하게 열려 있는 주제다. 다만, 업계에서는 다양한 관점에서 개발 문화를 평가하고 개선하려는 시도를 하고 있다. 코드 리뷰의 원칙을 정하고 잘 적용시키는 것도 그런 시도들 중에 하나로 볼 수 있고, 잘 정착된 코드 리뷰 원칙들은 의심의 여지 없이 좋은 개발 문화를 만든다. 

생성형 AI 이전의 사례 – 코드리뷰 원칙들과 좋은 리뷰, 나쁜 리뷰

개발 문화를 구성하는 여러 요소들 중에 특히 “코드 리뷰”는 개발자들의 소통 구조를 그대로 반영한다. 소프트웨어 개발 과정은 설계, 구현, 수정의 반복으로 단순화 할 수 있는데, 보통 코드 리뷰는 구현 단계에서 프로젝트에 참여하고 있는 여러 개발자들이 같은 수준으로 전체 구조를 이해할 수 있도록 돕는 역할을 한다. 다른 사람의 글을 첨삭하는 일이 고통스러운 것처럼, 코드 리뷰도 다른 사람이 쓴 코드의 맥락과 의도를 잘 파악해야 한다는 점에서 마찬가지로 고통스러울 수 있다. 간혹 감정적인 리뷰는 코드 리뷰의 원래 목적에서 크게 벗어나 협업을 방해하기도 한다. 업계에서는 코드 리뷰가 생산성을 해치지 않도록 여러 기준들을 만들어서 다듬어 왔고, 중요한 기준들은 경험적으로 확정되어 여러 팀들이 공유하고 있다. 

잘 알려진 리뷰 원칙을 열거해본다면, “코드의 구조에 대한 리뷰와 구체적인 로직에 대한 리뷰는 분리할 것”, “컨벤션에서 합의한 적 없는 스타일을 강요하지 말 것”, “완벽한 수정이 아니더라도 개선이 되었다면 변경 사항을 승인하는 방향으로”, “지적할 내용이 없다면 칭찬할 것” 등을 꼽아볼 수 있다. 많은 코드 리뷰 원칙들은 공통적으로 코드 리뷰 자체가 다른 개발자와의 “소통” 과정의 일부라고 전제하기 때문에, 마치 “신사적인 TV토론을 위해 지켜야 할 것들” 처럼 일반적이고 모호한 기준처럼 느껴지기도 한다. 이런 코드 리뷰 원칙들은 정량적인 지표를 수반하지 않으므로 리뷰어의 개성과 취향이 많이 반영될 수 밖에 없다. 간혹 나쁜 코드 리뷰의 예시로 “코드 작성자의 인격을 리뷰하는 경우”, “줄간격과 같은 지엽적인 변경 사항에 집중하는 경우”, “단정적으로 명령하는 어조를 사용하는 경우” 등을 볼 수 있는데, 이 또한 리뷰어의 성격과 소통 방식이 그대로 드러나기 때문이다. 

소모적인 논쟁을 피하고 더 나은 코드 구조와 세부 로직에 집중할 수 있도록 리뷰하려면 어떻게 해야할까? 업계에서 통용되는 해결책 중에 하나는, 미리 합의한 코딩 컨벤션 중 “스타일”에 관한 규칙을 별도의 도구를 통해 자동화 하는 것이다. “코드 스타일”은 프로그래밍 언어의 특성에 따라 다르고 개발자 개인의 취향이 크게 반영되므로, 프로젝트의 규모가 커질수록 일관된 스타일을 유지해야 코드의 가독성을 해치지 않을 수 있다.

예를 들면, 개발자들이 사용하는 통합개발환경(IDE; Integrated Development Environment) 소프트웨어에는 미리 정의한 코딩 스타일을 일괄 적용할 수 있는 기능이 있다. 이를 잘 활용하면 여러 개발자가 참여 하는 프로젝트의 코드 스타일을 일관되게 관리할 수 있고, 지엽적인 변경 사항을 코드 리뷰에서 다루지 않아도 된다. 코딩 컨벤션을 강제하는 것 외에도 테스트 자동화를 통해 변경 사항이 기존의 테스트 코드를 통과하는지 검사하는 등, 코드 리뷰 절차를 간소화 하거나 소모적인 리뷰가 되지 않도록 방지하는 방법들이 많이 제시되었다.

생성형 AI가 개발 과정에 미치는 영향 – 코드 리뷰를 대신할 수 있을까

보통의 코드 리뷰는 2단계로 나눌 수 있다. 기존 코드를 변경해야 하거나 새로운 기능을 추가해야 할 때, 첫째로, 그 기능이 어떻게 기존 구조에 편입 되어야 하는지 큰 틀에서 협의한다. 둘째로, 이후에 기능을 모두 구현하면 세부 로직이 오류 없이 잘 구현되었는지 리뷰한다. 이 때 1단계는 간단한 회의로 대체되거나 생략되기도 한다. 대부분의 개발자는 2단계에 꽤 많은 시간을 할애 하는데, 이 시간이 길어지면 자신이 맡고 있는 다른 업무에 지장을 주게 되므로 코드 리뷰의 “필요성은 공감하지만 현실적으로는 하기 힘든” 상태가 된다. 이 상태가 오래 지속되면 자연스럽게 코드 리뷰 자체에 대한 “양가감정”을 갖게 되고, 책임감과 귀찮음이 공존하는 상태에서 “LGTM; Looks Good To Me(변경 사항에 이견이 없다는 의미)”이라는 평가를 남발하기도 한다.

보다 효율적인 코드 리뷰를 하기 위한 노력은 생성형 AI를 본격적으로 활용하기 시작하면서 더 탄력을 받게 되었는데, 급기야는 코드 리뷰 자체를 생성형 AI에게 맡겨 보는 시도에까지 이르게 된다. 양가감정에 매몰된 개발자들에게 생성형 AI는 정말로 구원과 같았다. 일정에 쫓기는 상황에서 귀찮은 리뷰를 대신해주다니! 심지어 어떤 경우는 사람이 놓치는 오류를 먼저 찾아서 지적해주기도 한다. 게다가 예의바르다. 가끔 만날 수 있는 무례한 리뷰어의 댓글은 생성형 AI의 리뷰에서 찾을 수 없다. 확실히, 생산성이 올라가는 것 같기도 하다.

생성형 AI가 코드 리뷰 전부를 대신할 수 있을까? 이 질문에 답하려면 코드 리뷰를 왜 하는지 다시 짚어보아야 한다. 코드 리뷰의 목적은 어디에 있는가? 앞서 언급한 코드 리뷰의 2단계 중에서 첫번째 단계의 구체적인 예시를 생각해보면 코드 리뷰의 목적이 무엇인지 발견하게 된다. 리뷰의 첫번째 단계에서는 보통 구현해야 할 함수의 입/출력을 정의하고 그 함수가 어디서 호출될 예정인지, 기대하는 입력 데이터의 형태와 발생할 수 있는 예외를 어떻게 처리할 것인지 등을 협의한다. 구현의 단위가 작거나 명백한 경우 이 과정을 생략할 수 있지만 충분히 논의하지 않은 상태에서 세부로직을 구현하면 나중에 반드시 문제가 생긴다. 한 명의 개발자가 전체 프로젝트의 코드를 전부 작성하지 않는 한, 여러 개발자가 작성한 기능이 유기적으로 영향을 주고 받기 때문이다. 

결국 코드 리뷰는 개발자들이 서로의 코드를 더 잘 이해하고 더 좋은 코드를 작성하기 위해 하는 것이다. 생성형 AI는 어떤가? 현재 생성형 AI는 위 과정 전부에 관여할 수 있다. 추가/변경되는 세부 로직의 오류를 검사할 수 있고, 나아가 변경 사항이 전체 프로젝트를 기준으로 일관성이 있는지 판단할 수도 있다. 당연히 AI의 이런 판단을 전부 믿을 수는 없지만, 마치 또다른 개발자가 리뷰어로 참여한것처럼 의견을 주고 받을 수 있다.

우리는 누구와 협업하는가? – 사람이 소프트웨어를 만든다.

“계산하는 기계는 생각하는 기계가 될 수 있을까?”2 사람들은 옛날부터 막연하게 “일반 인공지능(AGI; Artificial General Intelligence)”이 보편화된 시대를 상상해왔다. 어떤 이들은 AGI라는 용어를 “인공지능 거품”이 만들어낸 마케팅 용어일 뿐이라고 일축하기도 한다. 그러나 AGI를 “사람이 할 수 있는 지식 노동을 상당부분 대체할 수 있는 장치”로 정의한다면, 어쩌면 우리는 AGI를 눈 앞에 두고 있을지도 모른다. 사람이 하는 지식 노동에서 AI가 차지하는 비중이 점점 늘어가는 지금, AI가 소프트웨어 개발 주기에 더 많이 관여하게 된다면 개발자들의 역할은 어떻게 변할까? 미래를 예측하는 질문에는 정답이 없겠지만, 프로그래밍 언어의 발전 과정을 돌아보면 그럴듯한 가설을 제시할 수 있다.

프로그래밍 언어는 사람이(프로그래머가) 통제하는 “추상화 계층(abstraction layers)”이 많아지는 방향으로 발전해왔다. 어셈블리어를 가지고 하드웨어를 직접 조작하던 시대부터 클릭 몇 번으로 거대 언어 모델을 클라우드에 배포할 수 있게 된 지금까지. 이런 흐름을 달리 표현한다면 프로그래밍 언어는 “사람이 이해하기 쉽게” 변화해왔다고 할 수 있다. 소프트웨어 개발 과정에도 다양한 층위의 “추상화”가 있다. 데이터베이스를 조회하는 함수를 어떻게 구현할 것인지 고민하는 비교적 단순한 수준의 추상화 계층이 있는 반면, 수 만건의 동시 접속 시도를 어떻게 분산시킬 것인지 정하는 더 복잡한 수준의 계층도 존재한다. 이런 추상화 계층들은 기술이 발전하면서 서로 합쳐지고 단순화 되어 더 복잡한 수준의 계층을 만들어낸다. 

AI가 감당할 수 있는 추상화 계층이 점점 많아지면서 소프트웨어 엔지니어들이 일하는 방식도 그에 맞춰 변하고 있다. 앞서 살펴본 AI가 코드리뷰에 개입하는 과정도 그 예시로 볼 수 있고, AI 코딩 도구가 보급되면서 이전에는 지금보다 더 엄격하게 구분되었던 전문 개발 영역의 경계가 흐려지고 있는 상황도 많은 것을 시사한다.3 개발자 한 명의 생산성이 크게 증가했지만, 개발자 한 명이 해결 해야 하는 문제의 복잡도 역시 비슷한 비율로 증가했다. 일하는 방식이 변해온만큼 좋은 소프트웨어를 만드는 조건도 달라졌을까? 이 질문은 AI 도구가 범람하고 있는 지금에도 “소프트웨어는 그것을 만드는 사람들을 닮는다” 라는 명제가 얼마나 의미 있는지 묻는 것과 닿아있다. 한 명이 소프트웨어를 전부 만들지 않는 한 개발자들의 소통 구조는 소프트웨어에 큰 영향을 끼친다.

우리는 누구와 협업하는가? 생성형 AI의 추론 능력이 하루가 다르게 발전하고 있지만 다행히도(!) 아직까지 소프트웨어를 만드는 주체는 사람이다. 코드 리뷰에서 생성형 AI가 제시하는 관점이 도움되는 경우가 많지만 코드 리뷰의 목적을 되돌아 볼 때 우리가 이해해야 할 대상이 “다른 개발자”라는 점은 변하지 않았다. 코드 리뷰의 상당 부분을 AI가 대신하게 되더라도 다른 개발자가 작성한 코드를 읽고 의견을 내야 한다. 

맺으며

ChatGPT가 공개된 후로 적지 않은 시간이 지났지만 아직 LLM은 환각(hallucination) 현상을 완벽하게 해결하지 못했다. 여전히 생성형 AI가 뱉어내는 말들은 오류를 포함할 수 있고 사실 관계가 맞지 않을 수도 있다. 이렇게 온전히 신뢰할 수 없는 시스템에게 내 코드를 검토하도록 할 수 있을까? 개발자로서 선뜻 동의하기 어려운 대목이다. 그런데 재미있는 지점은, 정확히 같은 문제가 사람 리뷰어에게도 나타난다는 점이다. 사람도 오류에 빠지거나 틀린 사실을 말할 수 있다.

우리가 AI에게 코드 리뷰를 맡길때, 어떤 것을 기대하는가? 코드 리뷰를 단순히 코드 작성자의 오류를 짚어내고 코딩 컨벤션을 잘 지켰는지 검사하는 절차로 이해한다면, 그리고 그 검사를 사람 대신 AI가 수행하는 것을 목표로 한다면 현재의 생성형 AI로는 전체적인 개발 생산성을 향상 시키기 어렵다. 오류 검사기로서의 AI는 아직 완전히 신뢰할 수 없기 때문이다.

반면, 코드 리뷰를 오류 검사 절차보다 더 고차원적인 개발 과정으로 받아들이는 관점에서는 생성형 AI를 사용해서 더 건설적으로 소통할 수 있다. “소프트웨어는 그것을 만드는 사람을 닮는다”는 말은 “소프트웨어 구조는 그 소프트웨어를 개발한 조직의 소통 구조를 닮는다”는 의미이다. 개발자라면 프로젝트의 크기가 커질수록, 참여하는 개발자가 많아질수록 필요없어 보이는 추상화 계층이 늘어나는 경험을 해본적이 있을 것이다. 오랫동안 코드 리뷰는 이런 현상을 완화시킬 수 있는 수단으로 여겨져 왔다. 코드 작성자가 빠질 수 있는 오류를 교정하는 것을 넘어서 더 좋은 디자인과 구현에 대해 깊이 대화하는 것 – 이것이 좋은 코드 리뷰이고 생성형 AI는 이 과정에서 논의의 관점을 더 풍부하게 만들어 줄 수 있다. 

환각을 해결한 AI가 등장한다면 소프트웨어 개발은 어떻게 변할까? 그런 시절이 온다면 대부분의 개발자는 더이상 직접 세부 로직을 구현하지 않게 될 수도 있다. 그러나 시대가 변해도 소프트웨어의 구조는 그것을 만드는 주체의 소통 구조에 크게 의존할 것이다. 좋은 소프트웨어를 만드는 열쇠는 여전히 그 주체들이 어떻게 소통하는지에 달려있다. 소통의 주제와 층위가 달라질 뿐 본질은 그대로일테니 좋은 개발 문화에 대한 고민 역시 계속해야만 한다. 


참고문헌

잭 코플랜드 저, 박영대 역, 김재인 감수(2020),  『계산하는 기계는 생각하는 기계가 될 수 있을까』, 에디토리얼. [Jack Copeland, (1993), Artificial Intelligence: A Philosophical Introduction, Wiley-Blackwell.]

더글러스 애덤스, 김선형, 권진아 번역 (2005),  『은하수를 여행하는 히치하이커를 위한 안내서』, 책세상. [Adams, D. (1979), The Hitchhiker’s Guide to the Galaxy, Pan Books.]


Notes

1 ”은하수를 여행하는 히치하이커를 위한 안내서”에 등장한 숫자로, 밈(meme)으로 자주 활용됨. 이 작품에 등장하는 슈퍼컴퓨터가 “삶, 우주, 그리고 모든것에 대한 궁극적인 질문”의 답으로 내놓은 결과가 “42” 였음.

2 90년대에 출판된 잭 코플랜드의 책 Artificial Intelligence, A philosophical introduction.의 한국어판 제목이기도 하다.

3 머신러닝 엔지니어의 직무 기술서를 예로 들면, 불과 2~3년 전에는 “인공지능 모델 학습 및 평가”를 주 업무로 표시하는 경우가 많았다. 최근에는 머신러닝 엔지니어에게 기존 웹 백엔드 개발자가 담당하는 영역 일부를 요구하거나, 반대로 백엔드 개발자에게 머신러닝 엔지니어의 역할 일부를 요구하는 경우가 등장하기 시작했다. 일정 경력 이상의 개발자들이 AI 도구를 활용해서 익숙하지 않은 영역에 더 쉽게 접근할 수 있게 되었기 때문이다. 

댓글 남기기

Powered by 워드프레스닷컴.

Up ↑

과학뒤켠에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기