[AI로 웹서버] 02. 로컬 개발 환경을 구축해보자 (feat. 젬 대리 & 클로 과장)
본격적인 개발에 앞서 젬에게 몇 가지 서버 일을 시켜봤다
젬이 정말 쓸만한 AI 직원이라는 사실에 나는 너무 기분 좋았다.
이제 힘들고 까다로운 일은 젬이 다 할 것이다. 변수명, 데이터 하나에 전체 시스템이 멈추는 일은 이제 없을 것이다. 아니, 멈춘다고 하더라도 내가 밤 샐 필요는 없을 것이다. 이제는 젬이 그걸 대신 분석하고, 대안을 얘기해줄 테니까.
한참동안 원격 서버 쪽에서 이것 저것 만져가면서 여러가지 가능성을 테스트했다. 결과는 아주 훌륭했다. 몇 번의 주문에 뚝딱 시스템이 만들어져 나왔다.
과거 웹서버를 혼자서 구축할 때, 내게 가장 힘든 것 중 하나가 nginx 설정과 https 설정이었다.
HTTPS는 웹사이트를 SSL(Secure Sockets Layer)/TLS(Transport Layer Security) 인증서로 보호하여 서버와 브라우저 사이 전송 데이터를 암호화하는 프로토콜 방식을 말한다.
하지만 이제 젬이 nginx 환경 설정과 HTTPS 인증 절차까지 하나씩 실행만 하면 되는 명령어로 알려줬다. 나는 그것을 보고, 그대로 실행시키기만 하면 되었다. 혹시 에러가 나면 그대로 주욱~ 드래그해서 복사해서 젬에게 던져주면, 젬이 그걸 보고 무엇을 하라고 주문했다. 내가 할 일은 젬이 알려주는 내용을 귀찮아하지 않고, 그대로 따라서 하면 될 뿐이었다.
(여기까지 써 놓은 것을 보니, 내가 직원이고 젬이 사장인 거 같다. ㅎ)

가끔 젬이 문제의 원인을 제대로 파악하지 못해서, 삽질을 하는 경우도 없진 않았다. 하지만 내가 헤매던 시절보단 젬이 더 빨랐고, 무엇보다 그 삽질조차 내가 하는 것이 아니라, 우리 직원 젬이 하는 거라, 난 크게 힘들지 않았다.
그저 젬에게 격려해주면 충분했다.
더 볼 것도 없었다.
이제부터 젬은 수습 떼고, 정식 직원이 되었다.
이제 본격적으로 개발을 시작해보자
지금까지 젬의 코드가 서버에서 제대로 먹히는 지를 알아보았다. 이미 여기저기서 AI가 코딩도 잘한다는 얘길 많이 하고 있지만, 내 직원으로 고용하려는데, 내가 직접 확인하는 과정이 필요했다.
하지만, 실제 개발은 젬이 인턴 시절 했던 방식으로는 곤란하다.
아주 급한 경우나 아주 간단한 경우가 아니라면, 실제 웹 서버(리모트 서버, 배포 서버 또는 프로덕션 서버라고 부른다)에서 직접 코드를 개발하거나, 수정하는 일은 없다. 개발하는 과정에서 수없이 서버를 멈췄다가 다시 시작해야 하는데, 그때는 외부에서 웹사이트에 접속할 수 없기 때문이다. 그 뿐만 아니라, 개발과정에서 실수로 에러라도 난다면 복구에 시간이 걸리니, 정말 큰 일이 된다.
그래서 통상 로컬(개발 서버라고도 부른다)에서 개발한 후, 실제 웹서버에 올리는 방식을 취한다. 개발하는 과정에서 무수한 시행착오를 겪고, 버그 수정을 하는 과정에도 멀리 있는 웹서버는 그대로 돌아가므로, 아무런 문제가 없다.
웹 서버 개발 프로젝트는 그래서 로컬 개발 환경을 구축하는 것부터 시작한다. 내가 먼저 웹 서버에서 긴급하게 코딩해서 돌려본 것은, "AI로 이게 과연 되나?"를 먼저 살펴보고 싶어서였기 때문이다.
로컬 개발 환경을 구축하기 위해, 젬에게 물었다.
Docker를 이용하여 웹 서버를 개발하려고 해. 개발환경은 윈도우즈 11, 배포환경은 우분투야. IDE는 VS CODE를 사용하려고 하는데 ...
앞서에서도 말했듯, 나는 10년전 기술에 멈춘 사람이라, Docker를 어떻게 쓸 수 있는지는 잘 모른다. 단지 가상의 컴퓨터를 돌리는 '가상화 기술'보다 Docker는 실행환경만 분리하여, 프로세스를 격리시키는 기술이므로, 훨씬 빠르고 안정적이어서 좋다라는 사실만 알았다.
그래서 굳이 Docker를 이용해서 개발하겠다고 젬에게 선언한 것이다.
'가상화 기술'이나 Docker 등을 굳이 써야 하는 이유가 뭘까? 그냥 시스템에 패키지를 바로 설치해서 쓰면 안되나?
패키지를 바로 설치해서 써도 실행은 된다. 하지만, 웹 개발이든 서버 개발이든 로컬에서 개발해서, 배포 서버(리모트)로 옮겨야 한다는 상황을 잊어서는 안된다. 로컬(Windows 또는 Linux)과 배포 서버(대부분 Linux)가 완벽하게 같을 수는 없어서, 로컬에서는 분명히 돌아가던 애가, 리모트에서 무수한 에러를 뿜으면서 뻗어버리는 경우가 엄청 많다. 그거 잡느라, 몇날 몇일 밤이 훌쩍 간다.
또 하나 문제는 패키지를 한번 설치했다 지울 때, 깔끔하게 제거되는 법이 별로 없다는 것이다. 이런 식으로 찌꺼기들이 쌓이게 되면 원인불상의 에러가 발생할 확률이 올라간다. 또 시간이 흐를수록 패키지를 업그레이드 시켜야하는 경우도 많은데, 그렇다고 확 업그레이드 시키면 그 코드를 갖다쓰는 A 프로그램은 멀쩡한데, B 프로그램은 이유없이 멈춰버리는 경우가 있다. 그거 사람 진짜 피말리는 일이다.
그래서 아예 분리시켜버리는 기술이 필요한 거다. 그런 방식이 몇 가지가 기존에도 있었다. 그 중 하나가 '가상화' 기술로서, OS 위에서 가상의 또다른 OS를 돌리는 방식이다. 그건 속도도 느린 편이었고, 메모리 등 자원 소모가 심한 단점이 있었다.
Docker는 그와 다르게 접근한다. 프로세스와 그 실행 환경을 컨테이너라는 개념으로 외부와 격리시키는 방식이다. 마치 정원에 울타리를 쳐서, 여기는 장미를 심고, 저기는 호박을 심는 방식이라고 할 수 있다. 나중에 그 장미를 옮겨야 한다면, 뿌리부터 주변 흙까지 통째로 떠서 옮기면 될 것이다.


가장 먼저 젬은 로컬에 Docker Desktop을 설치하라고 지시한다.
(자꾸 직원이 사장에게 지시를 한다. ㅠ 하지만, 어쩔 수 없다.)
일단, docker.com에 접속하여, Windows 용 Docker를 다운받아 설치했다.


설치가 끝나면 컴퓨터를 껐다 켜라고 한다.
그렇게 했다.
그리고 젬 말로는 나중에 개발이 완료되면 Docker Hub 보다 Git으로 배포하는 것이 좋다고 하니, Git도 설치했다.

또 젬이 시키는대로, VS Code의 Extensions에서 Dev Containers 확장을 검색하여 설치했다.
Dev Containers 확장은 마치 컨테이너 속에서 코딩하는 효과를 준다고 한다. 이 말이 무슨 말인가 하면, 우리가 특정 프로그램을 작성하기 위해서는 그 프로그램이 기반하는 각종 패키지가 설치되어 있어야 하는데, 그 패키지가 설치되어 있는 환경에서 코딩할 수 있게 한다는 말이다. (말을 설명하다 보니 더 어렵지만, 어찌되었던 그 뜻이다.)

그리고 로컬에 새로운 폴더(...\sejongview)를 하나 만들었다.
이 폴더가 앞으로 로컬 개발 환경이 될 것이다.
VS Code를 열어, 왼쪽 패널의 Explore 에서 Open Folder 버튼을 눌러, 새로 만든 작업 폴더를 연결했다.
그리고 젬이 인턴 시절 뚝딱 만들었던, (리모트 서버에 있는) Docker-compose.yml, SSL 인증, nginx 설정 등등 파일과 폴더 전체를 위 작업 폴더에 다운로드했다.

한번 중간 점검해 보자.
Windows에는 Docker Desktop과 Git을 설치했다. 그리고 VS Code에는 Dev Containers 확장을 설치했다.
그리고 이쯤에서 고백하건데, 나는 젬 말고도 직원을 하나 더 고용했다. 그 유명한 클로드다. 나는 그 직원을 클로라고 부른다.
(사실 코딩은 젬 보다 클로드가 훨씬 더 잘한다고 한다)
젬의 인턴 생활 동안, 젬은 내게 많은 영감을 주고 수고를 덜어주었지만, 가끔씩 삽질을 하는 모습을 보였다고 앞에서 얘기했었다. 젬이 뛰어난 AI 직원이긴 하나, 혼자서 그 어려운 작업들을 도맡아 하는 모습이 영 안되었다. 특히 하나의 문제를 해결하기 위해 집중하는 것은 좋은데, 문제의 프레임에서 벗어나지 못하고 계속 테두리 안에서 빙빙 돌기도 했다. 젬 역시 누군가의 관리가 필요했다.
그래서 새로 고용한 것이 클로 였다. 클로는 젬이 해결하지 못한 문제의 원인을 단번에 찾았다. 그리고 확실한 해결책을 제시했다.
무엇보다 마음에 드는 것은 젬의 경우, 새로운 기능이 추가되거나, 기존의 기능을 수정할 때 변경되는 부분과 관계없는 부분들까지도 종종 모두 바꿔버리는 경우가 있었으나, 클로는 그런 경우가 거의 없었다. 외과수술을 하듯이 아주 깔끔하게 최소한의 부분만 변경/제거하고 기능이 작동하게 만들었다. 이러니, 클로드 코드, 클로드 코드 하지. 실제로 최근 미국 IT 기업들의 주가가 폭락한 적이 있었다. 그 사건의 발단이 바로 이 클로드 코드였다.
브라보.
아주 훌륭했다.
이쯤에서 자연스럽게 질문하고 싶어질 것이다.
그러면 클로만 쓰면 되지, 뭐하러 귀찮게 젬까지 쓰지?
클로는 치명적인 단점이 하나 있었다.
비쌌다.
제미나이가 주는 여러가지 혜택(2TB의 구글 드라이브 공간, 가족 5명 공유, 각종 구글 앱과의 연동 등), 그런거 클로드는 없다. 오로지 ChatGPT나 제미나이보다 조금 더 뛰어난 AI 결과물 하나 가지고 승부한다.
물론 클로드를 제대로 쓰기 위해 Pro 버전을 구독하면, 클로드 Cowork이나 클로드 코드, 클로드 인 Excel 같은 월등한 능력자들을 데리고 쓸 수 있는 장점이 있다. 하지만 아직 내겐 그런 능력자들이 필요 없다.
동네 구멍가게에서 아직은 연봉 1억짜리 MBA 보유자가 필요없다.
나는 단지 가끔씩 하는 서버 관리와 프로그래밍에 클로드를 쓰고 싶을 뿐이다. 그렇다고 제미나이가 주는 혜택을 버리고, 클로드를 쓰기에는 제미나이의 혜택이 너무나 절실하다. 또 둘 다 쓰기에는 너무 비용이 과하다.
그래서 내가 얻은 답이 이거였다.
그럼 제미나이가 집중적으로 코딩하고, 그걸 클로드가 점검하면 되잖아.
특히 클로드의 API 사용은 내가 쓴만큼 지불하는 종량제(pay as you go) 방식의 구독이었다. 그 역시 제미나이 등 다른 AI보다 상당히 비싼 편이었지만, 그래도 사용한 만큼만 내면 되니까 내겐 아주 유리했다.
API는 Application Programming Interface의 약자로, 프로그램끼리 소통하는 방식을 의미한다. 즉 일반적인 ChatGPT나 제미나이 등의 채팅은 인간이 타이핑해서 입력하지만, API는 프로그래밍을 할 때, 프로그램 안에서 해당 AI 기능을 호출하는 방식으로 사용한다.
더군다나 VS Code는 클로(클로드 코드)를 2만원짜리 정액제로도 사용할 수 있고, 종량제로도 사용할 수 있도록 되어 있었다. 이건 두 번 고민할 게 없었다. 기꺼이 결제하고, 채용했다.
젬의 실수 때문에 내가 클로의 도움을 받은 것은 무료 버전의 클로드 채팅창을 통해서였다. 내가 스크립트를 복사해서 채팅창에 넣어주면, 클로드가 수정해서 보여주었고, 나는 그것을 다시 복사해서 VS Code에 붙여넣었다. 그런데 클로드 코드는 VS Code의 확장 기능(Claude Code for VS Code)으로 자리잡고 앉아, 필요한 부분의 코드를 직접 수정한다고 한다. 어마 무시한 기능이 아닐 수 없다.
그렇게 젬과 더불어 클로가 우리 회사 직원이 되었다.
젬이 실무자라면, 클로가 그 위에서 젬의 결과물을 관리감독 내지 검수하는 역할이다. 그래서 젬은 대리, 클로는 과장이다.
이런 이유로, VS Code Extensions에서 Claude Code for VS Code를 찾아 설치했다.

VS Code의 우측 패널에 클로드 코드를 실행하면, 인증 절차가 나오고(이미 Claude Pro 이상 또는 API 구독 결제가 완료되어 있어야 한다), 인증이 정상적으로 완료되면...
짜잔! 클로의 채팅창이 나타났다.

필요한 패키지를 모두 설치한 후의 모습은 아래와 같다.

이게 제대로 작동이 되는 지 간단하게 확인해보자.
먼저 Docker Desktop을 구동한다.

그리고 VS Code 하단의 Terminal 창에서 docker 이미지를 빌드하면, 아래와 같이 필요한 패키지를 다운로드 받아가며 열심히 이미지를 만드는 모습을 볼 수 있다.
PS D:\...\sejongview> docker compose up -d --build(up은 '실행하라'는 의미, -d 는 백그라운드 실행, - -build는 Dockerfile을 읽어 새로운 이미지를 만들라는 의미다)
이것은 젬이 Dockerfile과 docker-compose.yml 을 이미 만들어 놓았기 때문에 가능한 일이다.
여기서 잠깐,
Dockerfile과 docker-compose.yml의 차이를 알아보자.


또 하나 중요한 점.
나는 web에 대해서만 Dockerfile을 작성했다. 그래서 Dockerfile이 한 개 뿐인데, 어떻게 docker-compose.yml 실행 결과 여러 개의 컨테이너가 생길 수 있을까.



참고로, sejongview 서버의 docker-compose.yml의 일부는 아래와 같다. (위 설명처럼 mysql은 'image:'으로 되어 있고, web은 'build: .'으로 되어 있다)

아하~ 그렇구나.
혹시 나처럼 헷갈리는 분들은 꼭 참고하시길.
이제 Docker 이미지 빌드가 끝났다.
(필요한 패키지를 다운로드 받아가며 열심히 설치하는 모습이 보인다)


Docker 이미지 빌드가 끝나고, 이미지가 실행되면, 바로 로컬 브라우저에서 확인 가능하다.
http://localhost
참고로 Docker 명령어 몇 가지를 적어본다.
# 모든 컨테이너 중지 및 볼륨 삭제
PS D:\...\sejongview> docker compose down -v
# Docker 컨테이너 다시 시작 (--build 옵션을 넣게 되면, 처음부터 다시 이미지 생성)
PS D:\...\sejongview> docker compose up -d
# 현재 서버에서 실행중인 Docker 컨테이너 상태 확인 (docker compose ps는 해당 프로젝트 내 컨테이너만 보여줌)
PS D:\...\sejongview> docker ps
# 특정 컨테이너 로그 기록 보기 (이 기록을 ai에게 보여주면 분석해줌)
PS D:\...\sejongview> docker logs 컨테이너이름


"결국 중요한 건 '내가 얼마나 코딩을 잘하느냐'보다, 'AI라는 유능한 직원을 얼마나 잘 부리느냐'의 시대로 접어든 것 같다.
젬 대리가 땀 흘려 기초 공사를 하면, 클로 과장이 꼼꼼하게 검수하는 우리 팀의 시스템은 상당히 만족스러웠다.
하지만 제대로 환경 구축이 완료되었는지 점검은 이제부터다.
#도커 #Docker #제미나이 #Gemini #클로드 #Claude #VSCode #개발환경 #서버관리 #AI코딩 #인공지능직원 #Nginx #HTTPS #WSL2 #웹개발 #컨테이너 #DevContainers #IT일기