루비에서 쿠버네티스까지


2005년 6월 2일, David Heinemeier Hansson이라는 이름의 덴마크 출신 개발자가 브라질에서 열린 컨퍼런스에서 하나의 발표를 하게 됩니다. 발표 주제는 자신이 직접 개발한 프레임워크를 이용해서 블로그를 만드는 시연이었습니다. 이 발표에서 DHH는 비어있는 디렉터리에서부터 시작하여 단위 테스트코드를 포함하여 글 작성, 수정, 코멘트 기능이 완비된 블로그를 만드는 시연을 15분 만에 실수 없이 매끄럽게 끝냈습니다. 이 발표는 당시에 어마어마한 화제가 되었기 때문에 당시 업계에서 이미 일하고 계셨던 분들이나 관련 공부를 하고 계셨던 분들이라면 다들 한 번쯤 ‘How to build a blog engine in 15 minutes with Ruby on Rails’라는 영상을 보셨을 겁니다.

당시에 개발에 별로 관심이 없으셨거나, 다른 분야를 공부하고 계셨거나, 워크래프트의 세계에서 라그나로스를 때려잡고 계셨거나 해서 이 영상을 놓치신 분들을 위해 살짝 부연 설명하자면, 2005년은 닷컴 버블이 터져서 소프트웨어 산업이 상당히 가라앉고 있던 시기였고, 개발 생태계도 그렇게 활력 있게 성장하던 시기는 아니었습니다. J2EE나 PHP와 같은 프레임워크의 낮은 생산성이 문제를 일으키고 있었으나, 스프링 프레임워크와 같은 새로운 프레임워크는 아직 완전한 주류가 되지 않던 시절. 아이폰이 발표되기 이전이라 소프트웨어 시장의 파이가 폭발적으로 성장하지도 않았으며, 닷컴 버블에서 붕괴하지 않은 기업들의 특성을 끌어모아서 Web 2.0이라는 키워드로 어떻게 소프트웨어 기업들이 인터넷 비즈니스 시장에서 살아남을 수 있을지를 고민하던 시기였습니다.

이런 시기에 ‘개발을 할 때 뻔한 것들은 굳이 코드로 만들 필요가 없다’라는 가치를 ‘15분만에 블로그 만들기’로 보여준 루비 온 레일즈의 시연은 당시 개발 생태계에 엄청난 활기를 불러오게 됩니다. 학생들은 빨간 곡괭이가 그려진 두꺼운 Programming Ruby를 들고 다녔고, 기업들은 레일즈의 생산성을 이용하여 빠르게 웹 애플리케이션을 만들고 시장의 반응에 따라 지속적으로 서비스를 업데이트 해나가면서 수익을 도모하는 Software as a Service라는 형태에 집중하기 시작합니다. 아마 당시에 취업이나 이직을 고민하셨던 분들이라면 스프링노트와 같은 SaaS 서비스를 주도적으로 내놓은 NC소프트 산하의 오픈마루 스튜디오 같은 곳을 기억하시는 분들이 있으실 겁니다. 이러한 회사들은 레일즈를 기반으로 서비스를 시작하면 개발과 업데이트의 속도가 시장의 반응속도를 따라갈 수 있음을 증명했기 때문에 웹 서비스가 광고 외에도 서비스 자체로써 가치를 가질 수 있음을 증명해 보이려고 노력했습니다. 물론 초기 SaaS 기업들은 비즈니스 모델의 설계와 수익창출에 실패하고 사라진 경우가 많았지만, 결과적으로 서비스가 돈이 된다는 사실은 증명이 되었으므로 그 희생이 가치가 없지는 않았을 겁니다.

지금까지 레일즈가 개발 생태계에 미친 영향은 알게 모르게 꽤 많습니다. 그리고 그 영향력들은 지금도 여전히 여러 분야에서 살아있습니다. 영상을 보신 분들이라면 아시겠지만 레일즈는 DB에서 테이블 구조만 정의하면 관련된 백엔드와 프론트엔드를 모두 자동 생성하는 기능을 Scaffolding 기능을 가지고 있었는데, 이것은 도메인 기반 개발(Domain Driven Development)의 개념에 대한 완벽한 실증이자 동시에 설정보다 관례(Convention)에 의한 코딩(Convertion over Configuration)의 개념을 보여준 사례였습니다. 기계적이고 누구나 똑같이 만들어내는 것이면 굳이 만들지 않고 컨벤션에 맞추어서 자동으로 생성하거나 유추하는 것이 가능하다는 것입니다. 이러한 사상은 지금은 굉장히 보편적이어서, 그레이들(Gradle) 같은 경우에는 별다른 지정이 없으면 당연히 소스코드는 src/main/java 아래에 있다고 가정을 하고 찾아내며, 코틀린(Kotlin)의 경우에는 클래스 명 앞에 data를 붙이고 필드만 정의해주면 알아서 Getter와 Setter, toString, equals 등의 메소드들을 만들어줍니다. 아마도 많은 분들이 지금 즐겨 사용하는 언어나 프레임워크, 라이브러리에서 비슷한 사례를 떠올리실 수 있을 겁니다. 레일즈보다 살짝 먼저 나왔던 스프링 프레임워크가 반대로 거의 모든 것을 직접 설정하도록 만들어놔서 최근까지 많은 개발자들이 XML과 설정 파일 속에서 허우적거렸던 것을 생각하면 이러한 변화는 많은 사람에게 긍정적으로 받아들여졌을 것 같습니다.

하지만 이렇게 설정을 생략하고 컨벤션을 우선시하는 개발 방식이 절대로 기능을 단순화하는 것은 아닙니다. 예를 들어서 스프링 부트(Spring Boot)는 그냥 실행하면 서버를 8080 포트에 띄웁니다. 아주 오래전부터 웹 애플리케이션 서버의 HTTP 포트는 80포트에 8000을 더해서 8080이고, HTTPS 포트는 443에 8000을 더한 8443이다 라는 관례를 따르는 것이지요. 하지만 이것이 서버 포트의 설정 기능을 없애버린 것은 아닙니다. 개발자들이나 운영자들은 얼마든지 설정 파일의 변경 혹은 환경 변수, 실행 파라미터 등의 다양한 수단을 이용하여 다른 포트로 서버를 기동시킬 수 있습니다. 때문에 컨벤션을 많이 사용하는 지금에도 어떤 실행 환경이나 설정들은 예전보다 꽤 복잡해진 것처럼 보이기도 합니다. 하지만 이러한 컨벤션에 의해 설정이 줄어들기 시작한 이후에 등장한 복잡성들은 대체로 필요에 의해서 복잡해진 경우가 많습니다. 예를 들어서 다음 쿠버네티스 Deployment 파일은 Nginx 컨테이너를 기동시켜줍니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

도커 허브(Docker Hub)에서 Nginx의 이미지를 살펴보면 디폴트로 80 포트를 사용하도록 지정되어있기 때문에 위 파일에서 containerPort 설정은 빼버릴 수 있습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9

같은 맥락에서 Nginx 컨테이너를 하나만 배포할 것이라면 replicas를 생략할 수도 있고, 여러 개를 배포할 것이라면 설정에 추가해줄 수도 있습니다. 하지만 이러한 설정이 충분해보이지 않을 수도 있습니다. 예를 들어서 다음과 같이 배포할 수도 있습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
  spec:
    template:
      metadata:
        labels:
          app: nginx
      spec:
        containers:
        - name: nginx
          image: nginx:1.7.9
            livenessProbe:
              httpGet:
                path: /healthz
                httpHeaders:
                - name: You-Cool
                Value: Yup
            readinessProbe:
              exec:
                command:
                - cat
                - /swag

설정이 다시 복잡해졌는데, 여기에서는 livenessProbe와 readinessProbe를 추가해주었습니다. 쿠버네티스에서 이러한 설정을 추가해주면 쿠버네티스는 해당 컨테이너를 배포해서 실행할 때, Readiness Probe에 명시된 명령어를 이용해서 해당 컨테이너가 서비스 준비가 되었는지 판단하고 네트워크에 연결해주며, 이후 지속적으로 Liveness Probe에 명시된 경로를 호출하면서 컨테이너가 정상적으로 돌아가고 있는지 체크하고, 정상적이지 않을 경우 해당 컨테이너를 제거하고 다시 기동시켜줍니다. 이러한 동작은 설정을 하지 않더라도 프로세스의 실행 상태를 조회하여 자동으로 이루어지기도 하지만, 대부분의 미들웨어는 조금 더 상세한 설정을 추가해주어 예외적인 상황에 유연히 대처할 수 있도록 해줍니다.

이외에도 설정 파일에는 파일을 저장할 볼륨의 종류와 경로를 지정해주거나, 필요한 암호등을 Secret에 별도로 저장해서 불러서 쓸 수도 있으며 필요한 CPU나 메모리의 양을 명시하는 등 다양한 설정을 추가할 수 있습니다. 이렇게 설정이 늘어나는 것은 모든 것이 간소해지는 언어와 플랫폼의 추세를 거스르는 것이라고 볼 수도 있겠지만, 기존에 존재하던 미들웨어, 서비스, 애플리케이션들을 쿠버네티스라는 기존에 없던 플랫폼에 결합시키기 위해서 등장한 복잡성들이라고 볼 수도 있을 것입니다. 이 부분은 굉장히 중요하기 때문에 조금 더 깊이 생각해보겠습니다. 위에서 쿠버네티스 Deployment는 YAML이라는 규격으로 작성했습니다. 많은 분들이 아시겠지만 최근 많은 프레임워크나 플랫폼들이 YAML을 설정 파일을 작성하기 위한 규격으로 사용하고 있습니다. YAML은 철저히 컴퓨터가 해석하기 편한 규격이지만, 사람이 봐도 그럭저럭 읽을만하고, 사람이 작성하기에도 그렇게 짜증나지 않다는 점에서 많은 장점을 보여주었고, 기존의 XML 류의 마크업 언어를 빠르게 대체하였습니다.

하지만 기본적으로 YAML 파일, 특히 쿠버네티스의 설정 파일들은 쿠버네티스가 평면적으로 해석하기 편한 규격으로 맞춰서 작성해야 합니다. 쿠버네티스에 무언가를 배포해보시거나 혹은 그냥 YAML을 사용해보신 분들이라면 스페이스나 탭을 하나만 틀려도 오류가 발생하면서 실행이 안 되기도 하고, 순서가 바뀌거나 오타가 나도 오류가 나던 경험을 해보신 적이 꽤 있을겁니다. 쿠버네티스의 구동 엔진을 우리가 신경쓰지 않아도 되는 목표 시스템으로 본다면, YAML 파일은 사실 하이레벨의 언어라기 보다는 어셈블리어에 가까운 위치에 있습니다. 그렇기 때문에 그저 자신이 만든 애플리케이션과 서비스를 쿠버네티스에 띄우기를 원했던 개발자들에게는 YAML 파일의 작성이 슬슬 복잡하고 짜증나게 느껴지기도 했습니다. ‘앱을 구동한다’와 ‘YAML 파일을 규격에 맞추어 작성한다’ 사이에는 분명 쓸데없는 낭비가 있는 것 처럼 느껴지기 시작한 것입니다.

so many developers

쿠버네티스가 등장하기 이전에 LLVM의 등장을 기억하시는 분이 있을지 모르겠습니다. Low Level의 가상 머신을 만들고자 하는 목표에서 시작되어 지금 다양한 언어의 중간 컴파일러로 사용되고 있는 LLVM은 . java 파일을 컴파일 하여 .class 파일의 중간 언어 형태로 바꾸고 이를 실행해주는 자바 가상 머신의 개념과 유사하게, 다양한 아키텍처의 실행파일로 변환될 수 있는 중간 언어의 규격을 정의하고, 어떤 언어라도 LLVM 중간 언어 규격에 맞추어서 변환하면 이를 최적화하여 ARM이나 x86등 다양한 아키텍처에서 실행할 수 있는 바이너리로 변환시켜줍니다. C나 C++, 포트란 등의 과거 언어에서부터 Swift 같은 최신 언어들까지 다양한 언어들이 LLVM을 이용하여 바이너리를 생성하고 있으며, 심지어 JVM에서 구동되는 Kotlin 같은 언어도 LLVM을 써서 바이너리를 바로 생성하는 Kotlin/Native 같은 프로젝트를 지원하고 있습니다.

이러한 LLVM의 스택은 다양한 언어들로 표현되는 프론트엔드(Frontend - 일반적으로 UI 개발 레이어를 의미하는 프론트엔드와는 구분됩니다)와 이를 중간 언어로 변환하고 최적화하는 Optimizer, 그리고 실제 목표로 하는 CPU 아키텍처에 맞게 바이너리를 실행하는 백엔드로 구분할 수 있습니다. 꼭 LLVM이 아니더라도 뭔가 다양한 것들을 지원하는 플랫폼이라면 다양한 것들을 해석 가능한 형태로 변환시켜서 이를 하나의 엔진에서 기동 하는 형태의 스택을 많이 사용하곤 합니다. 그리고 다양한 애플리케이션과 미들웨어를 지원해야 하는 쿠버네티스 역시 비슷한 컨셉을 가지고 있습니다.

내가 만든 애플리케이션을 9080 포트에 띄우고, 5초에 한 번씩 체크해서 죽으면 다시 살려내라!라는 의도는 무언가를 거쳐서 쿠버네티스에 전달되어 실행됩니다. 설정이 올바르게 이루어지면 쿠버네티스는 원하는 포트에 앱을 노출시켜주고, 지속적으로 체크해서 앱이 정상이 아닐 경우 종료시키고 다시 기동시켜줍니다. 여기서 ‘무언가’는 저희가 흔히 생각하는 CI/CD 파이프라인이기도 하고 쿠버네티스 배포를 돕기 위해서 사용하는 이런저런 도구들이 되기도 하고 클라우드 개발환경이 될 수도 있습니다. 그리고 쿠버네티스는 이러한 의도에 맞게 앱을 실행하고 관리하도록 다양한 API와 기능들을 지원하고 계속 추가하고 있습니다.

kubecon whiteboard

위에서 기존에 없던 쿠버네티스라는 플랫폼에 기존에 존재하던 애플리케이션과 서비스들을 구동시키는 과정에서 복잡성이 증가하고 있다고 했는데, 이러한 복잡성을 줄이기 위해서 쿠버네티스와 여기에 부속된 컨트롤러, 서비스, 애플리케이션, 라이브러리들의 생태계는 쿠버네티스 엔진을 최적화 시키고 있고, 각 기업들은 쿠버네티스를 기동시키는 환경과 이를 지원하는 서비스들을 최적화시켜나가고 있습니다. 전자의 예를 들자면 Prometheus와 같은 모니터링 도구들이나 Fluentd와 같은 로깅 도구들, gRPC같은 통신 프로토콜에서 Helm과 같은 쿠버네티스용 배포 도구들을 생각해볼 수 있을 겁니다. 그리고 후자의 예를 들자면 아마존의 EKS나 구글의 GKE와 같은 클라우드 기반 쿠버네티스 환경이나 다양한 클라우드 서비스들을 생각해볼 수 있습니다. 이러한 환경에서 쿠버네티스 클러스터를 생성하고, 앱을 배포해보신 경험이 있거나 구경해보신 분들이라면 각 기업들이 복잡한 쿠버네티스를 사용하기 쉽게 만들기 위해서 무진 애를 쓰고 있다는 사실을 쉽게 짐작하실 수 있을 겁니다.

이러한 쿠버네티스 생태계의 발전에서 14년 전 루비 온 레일즈의 등장을 다시 생각해본다는 것은, 양적으로도 질적으로도 엄청나게 빠르게 성장하고 있는 개발 생태계에서 항상 기능적인 성장 외에도 ‘좋은 관례’에서 비롯되는 ‘좋은 Default값’을 제공해줄 의무가 있음을 의미합니다. 기능을 마구마구 추가해서 가능성을 넓혀나가는 것은 물론 좋은 일이지만, 여기에 좋은 Default 값이 무엇인가에 대해서 고려하지 않는다면 시스템의 복잡성은 순식간에 증가하게 되고 개발자들의 환영을 받기 어려워 질 것입니다. 쿠버네티스는 지금 그 아슬아슬한 지점에 위치해있다고 봐도 될 것 같습니다. 뭔가 엄청 발전했는데 배우기는 점점 어려워지고 있고, 많은 가이드들이 이제 튜토리얼을 항상 EKS나 GKE와 같은 클라우드 환경에서 시작할 것을 권고하고 있는 것을 봐도 알 수 있습니다. 그냥 시작하기에는 너무 복잡해진 것이지요. 루비 온 레일즈는 빈 디렉토리에서 명령어 한 줄로 개발을 바로 시작할 수 있었던 것을 생각해보면, 굳이 쿠버네티스가 아니더라도 프론트엔드 개발, 미들웨어 설정, 로깅 서비스, 백엔드 개발, AI 환경 구성 등등 많은 플랫폼과 프레임워크들이 놓치고 있는 지점이 있을지도 모르겠다는 생각을 할 수 있습니다.

사실 루비 온 레일즈의 등장이 개발 생태계에 미친 영향을 몇 가지 더 있습니다. 예를 들어서 웹 애플리케이션이 반드시 MVC 패턴에 얽힌 필요도 없고, 꼭 화면을 제공해야 하는 것이 아니라 단순하게 리퀘스트와 리스폰스의 매핑으로 처리해도 된다는 개념은 Sinatra 프로젝트를 거쳐서 Heroku와 같은 클라우드 플랫폼으로 발전했고, Heroku의 소스코드를 자동으로 클라우드 플랫폼에 배포한다는 이 개념은 현재 Helm이라는 쿠버네티스 기반의 패키지 매니저 형태로 진화하게 되었습니다. Helm이 레일즈의 유산이라고 보는 것은 다소 억측인 것 같지만, 레일즈가 지향하던 방향이 현재 개발 생태계에 미치고 있는 영향을 부정하기도 어려울 것 같습니다.

위 15분 만에 블로그 만들기 영상에서 DHH가 사용한 텍스트 에디터는 TextMate라는 맥 전용 텍스트 에디터였는데, 이 영상이 센세이셔널하게 퍼지면서 동시에 TextMate의 인기도 엄청나게 올라갔습니다. 일단 루비 개발을 할 때는 거의 표준 에디터에 가까웠고, TextMate를 쓰기 위해 맥을 구입하거나, 한글과 같은 2바이트 문자가 제대로 표시되지 않는다는 치명적인 단점이 있었음에도 한글을 쓰지 않거나 폰트를 이리저리 개조해서 사용하는 등의 사용자들이 나왔을 정도였습니다. 특히나 번들이라는 플러그인 개념의 확장은 TextMate의 인기 요소였습니다. 이후 등장한 Sublime Text가 TextMate의 번들을 그대로 사용할 수 있도록 만들어서야 TextMate를 대체하기 시작했고, 이러한 편의성과 확장성은 결국 최근 가장 많이 쓰이는 비주얼 스튜디오 코드와 같은 텍스트 에디터에도 그대로 이어지게 됩니다.

또 루비는 패키지와 의존성 관리를 위해서 Gem이라는 패키지 관리 도구를 사용하였는데, 레일즈 혹은 기타 루비 라이브러리를 사용하기 위해서는 gem install <라이브러리명>과 같은 방식으로 해당 라이브러리와 해당 라이브러리를 사용하기 위해 먼저 깔려있어야 하는 의존 관계에 있는 라이브러리를 모두 한 번에 설치할 수 있었습니다. 이런 개념 자체는 apt-get과 같은 도구들이 일찍부터 사용하던 개념이지만, 코딩을 위해 필요한 라이브러리들을 명령어 한 줄로 인터넷에서 쉽게 받아서 사용한다는 개념은 당시에 엄청나게 보편적인 개념은 아니었습니다. 하지만 레일즈 이후로 이러한 사상은 지금은 너무나 보편적이어서, 맥 개발자들은 homebrew를 이용해서 필요한 개발 도구와 라이브러리들을 설치하고, 윈도우 개발자들은 chocolately 등을 이용해서 비슷한 작업을 합니다. 그리고 Node, Python, Go 등의 요즘 빠르게 발전하고 있는 대부분의 언어들이 npm, pip, go get 등의 동일한 개념의 도구를 같이 배포하는 게 당연한 시대가 되었습니다.

사실 레일즈가 지금의 개발 생태계의 모습을 혼자 다 만들었다고 주장하는 것은 무리가 많습니다. 다만 레일즈의 등장이 당시 개발자들에게 어떤 영감을 주었음은 분명합니다. 특히나 기존의 개발 방향에서 뭔가 다른 방향으로 생각하도록 만들어줬고, 그 다른 방향이라는 것이 더 단순하고 더 편리한 방향을 지향하고 있다는 점을 알 수 있습니다. 프레임워크나 플랫폼이 개발자에게서 복잡한 것들을 생각하지 않게 해 주고 더 편하게 개발할 수 있도록 만들어준다는 것은 바꿔 말하면 개발자가 훨씬 더 중요한 것들, 그러니까 도메인이나 비즈니스 로직 같은 것에 집중할 수 있도록 만들어준다는 것을 의미합니다.

쿠버네티스 역시 하나의 플랫폼으로써 비슷한 지향점을 가지고 있습니다. 쿠버네티스는 이제 하나의 소프트웨어라기 보다는 굉장히 많은 소프트웨어들을 포함하고 있고, 또 새로운 소프트웨어와 서비스들이 계속 추가되는 하나의 생태계에 가까워졌는데 이러한 생태계의 발전 방향 역시 개발자들이 좀 더 본질적인 것에 집중할 수 있도록 해주기 위함이라고 기대하는 것이 좋을 것 같습니다. 그렇기 때문에 쿠버네티스 생태계에 속한 다양한 기업들과 개발자, 커뮤니티들은 쿠버네티스가 ‘레일즈 한’ 순간을 찾을 수 있도록, 그러니까 다시 한 번 개발자들의 인식과 관습을 바꿔나갈 수 있도록 노력할 것이다 - 라는 것이 제 생각은 아니고 올해 샌디에고에서 열린 KubeCon + Cloud Native Con 2019의 마지막 날 아침에 있었던 키노트 세션 In Search of the Kubernetes “Rails” Moment의 발표 내용이었습니다.

kubecon keynote

클라우드 네이티브를 계속 품위 있게 - Keep Cloud Native Classy라는 주제로 열린 올해 KubeCon에서 며칠 동안 이런저런 세션을 들으면서 제가 가장 많이 느꼈던 것은, 쿠버네티스의 위치 혹은 태도 같은 것이 많이 달라졌다는 것입니다. 컨퍼런스는 ‘이런 이런 좋은 것들이 있어’ ‘이런 방식으로도 생각할 수 있어’ ‘이런 것도 해보며 좋지 않을까?‘류의 도전적이고 탐험적인 발표들 보다는 이미 완성된 프로젝트들, 성공적인 적용 사례들, 놀라운 성과들과 고차원적인 논의들이 가득해서 어떻게 보면 지난 몇 년사이에 복잡하고 다양했던 개발 생태계의 플랫폼 경쟁에서 완승한 쿠버네티스의 세리머니 같은 느낌이 들었습니다.

몇 년 전까지만 해도 쿠버네티스는 다소 도전적인 위치에 있었습니다. 그래서 많은 사람들이 쿠버네티스의 장점을 전파하며 쿠버네티스 도입을 설득하기 위해 고생하기도 했고, 제발 만드시는 앱들이 쿠버네티스에서 잘 돌아가도록 개발을 해달라고, 클라우드 환경에 대비해서 코딩을 해야한다고 말하고 다니기도 했습니다. 하지만 최근 쿠버네티스 도입은 모든 업종에 걸쳐서 매우 광범위하게 이루어지고 있고, 새롭게 개발되는 애플리케이션들은 쿠버네티스와 클라우드 환경에서도 아무 문제 없이 구동되도록 개발하는 것은 물론이고, 어떻게 하면 쿠버네티스와 클라우드 환경의 장점들을 더 적극적으로 수용할 수 있을까를 고민하는 단계에 있습니다.

kubecon session

그래서 이렇게 위상이 바뀐 쿠버네티스와 클라우드 네이티브 생태계는 이제 어떻게 사람들에게 이걸 쓰게 할까? 라는 고민을 넘어서서 어떻게 하면 이 지배적인 생태계를 더 좋은 방향으로, 실수하거나 망치지 않고, 더 품위있게 발전할 수 있을까를 고민하기 시작했고 그 나름의 결론이 다양한 세션으로 표현되었습니다. 에를 들어서 몇 년 전에는 쿠버네티스 위에서 DB를 돌리는 것이 엄청나게 도전적인 일이었는데, 이번 KubeCon에서는 MySQL 기반의 클라우드 네이티브 데이터베이스인 Vitess 프로젝트가 인큐베이팅 단계를 끝내고 졸업(Graduate)했음을 키노트에서 자축하고, 슬랙(Slack)이 어떻게 Vitess를 운영 환경에 구성하고 기존 DB를 마이그레이션하고 있는지 설명하는 세션으로 이어나가기도 했습니다. 반면에 도커(Docker)에 대한 언급은 윈도우즈 컨테이너에 대한 세션에서나 간신히 나올 정도로 관심사에서 벗어나기도 했구요. 여러 가지로 격세지감이라는 말이 어울리는 컨퍼런스였습니다.

저는 루비 온 레일즈가 지금은 점유율이 많이 줄기는 했지만 그래도 다양한 형태로 지금의 개발환경과 개발자들에게 영향을 주고 있는 것과 마찬가지로, 쿠버네티스로 대표되는 클라우드 네이티브 프로그래밍 역시 ‘당연한 것’이 되는 순간을 지나쳐서 자연스럽게 미래 개발 생태계에 다양한 영향을 미칠 것이라고 생각하고 있습니다. 그래서 소싯적에 루비와 레일즈를 써보거나 관심을 가졌던 분들이 요즘 유행하는 모던한 개발 환경에도 무리 없이 잘 적응하시는 것처럼, 지금 클라우드 네이티브 생태계가 어디까지 왔고 어떤 방향으로 나가고 있는지 관심을 가지는 것도 14년쯤 뒤의 개발환경에 적응하는데 도움이 되지 않을까 하는 생각이 들었습니다.