[입개발] Cloud Native 와 Spring Cloud

Cloud Native 와 Spring Cloud

이 글은 Josh Long 의 Spring Cloud 강연을 들은 거의 후기와 평소에 제가 생각하는 것들을… 섞어서
제 마음대로 써볼려고 합니다. 일단 제가 이분야 꼬꼬마이니… 틀리시면 조용히 욕만… T.T 그리고 많은
지적질 감사하겠습니다.

참고: 관련 코드는 https://github.com/joshlong/cloud-native-workshop 에서 보실 수 있습니다.

먼저 고백하자면, 전 Java 도 잘 모르고, Spring은 더더욱 잘 모르고, Spring Cloud는 정말 세미나 두 번 들은게 다입니다.

아직 저도 잘 못읽어본…(솔직히 목차만 본…) Cloud Native Java 를 한번 보시는 것도 꽤 도움이 될듯합니다. 재미있는건 제가 Spring Cloud에 대해서 들었던 두 번이 각각 이 책의 저자인 Kenny 와 Josh 입니다.(영어도 잘하고, 심지어 기술도 좋은… 아, 얘들 미국인이지…)

그렇다면 먼저 Spring Cloud 야… 이번에 Spring 에서 미는 기술이고…(정확히는 컴포넌트의 연합?)
그 전에 Cloud Native는 무엇일까요?

한국어 해석은 매우 분분할 수 있는데… 클라우드에서 태어난, 클라우드향?, 클라우드에 적합한?
일단 이 개념을 전도하는(그 전도 맞습니다.) Pivotal 에서는 다음과 같이 정의하고 있습니다.

“Cloud Native describes the patterns of high performing organizations delivering software faster, consistently and reliably at scale. Continuous delivery, DevOps, and microservices label the why, how and what of the cloud natives.”

간단하게 해석하자면…(저 영어 못해요.) 소프트웨어를 빨리 개발하고 릴리즈하면서도, 확장성도 있고 안전성이 높게 만드는 패턴이라고 합니다.(이런 구라를… 그러나 현실에도 장동건처럼 잘생긴데, 돈도 잘벌고, 성격까지 좋은 사람들도…)

이런 기사도 있습니다. “http://www.informationweek.com/cloud/platform-as-a-service/cloud-native-what-it-means-why-it-matters/d/d-id/1321539”

실제 세미나도 Spring Boot를 소개하는 것으로 시작합니다. 큰 설정 없이 endpoint에 대한 핸들러만
설정해주고 구현해주는 것만으로 쉽게 비지니스 로직의 구현이 가능합니다.

예를 들어, @Get(“/profiles/me”) 이런 annotation을 이용하고 해당 핸들러를 구현하면… 바로
profiles/me 에 대한 url에 대한 처리가 가능해지는 겁니다. 그런데 Play나 뭐, 다른 쉬운 프레임워크
들을 사용해도 이런식의 개발은 쉽게 가능합니다.

일단 제가 Spring Boot 부터 잘 모르니… 자세한 부분은 넘기겠습니다.(그렇다면 내가 아는 것은 뭐지?)

이제 한번 서비스를 하나 만든다고 생각해보겠습니다. 서비스 포트는 8080번 이고, db 서버는 어디에 접속하고… 이런 정보들을 보통 설정 파일을 만들어서 넣어두고, 구동시 해당 값을 읽어서 서비스가 실행되게 됩니다. (그것도 아니면… 보통… 아예 고정으로 소스코드에 넣어둘수도…)

그런데 이러면… 사실… 각각의 서버들의 설정이 서로 다를 수 있습니다. 어디는 새로운 설정을 쓴다거나… 이럴 때의 좋은 방안은 설정 서버를 두는 것입니다. 그래서 서비스가 최초 구동시에 설정 서버에서 자신의 설정을 읽어서 이걸로 서비스를 시작하는 거죠. 이제 모든 서버들이 같은 설정으로 구동할 수 있습니다.

이런 걸 구축할려면… 사실… 여러가지를 알아야 합니다. 일반적으로 zookeeper 나, consul, etcd 같은 곳에 이런 설정을 저장하거나, DB나 다른 스토리지에 저장하기도 합니다. 그런데 이런걸 config-server 란 녀석이 해주는 겁니다.(세상 참 많이 좋아졌습니다.)

이제 설정은 config server에서 가져와서 실행이 되도록 했습니다. 그런데 실제로 서비스를 운영하다 보면… endpoint를 설정에 의해서 바꿔준다든지… 아니면 살짝 로직을 더 추가한다든지가 필요할 경우가 생기는…(두 개의 API를 묶는다든지..) 이렬 경우 뭔가 라우팅을 바꿔준다거나, 실제로 해당 API들을 통해서 뭔가 다른 작업을 할수 있는 API Gateway 를 만들어 주는 것이, 여러가지 방면에서 편리합니다. 여기서 Zuul 이라는 것을 이용해서 아주 쉽게 추가가 가능합니다.(API Gateway 는 사실 여러가지 녀석들이 있습니다.)

그런데 서비스를 운영하다보면, 당장 DB라든지, 아니면 다른 서드파티 서버들과 통신해야 하는 경우가 생깁니다. 예를 들어, 서비스가 분리되어 있는데, 계정 서비스를 호출해서 해당 사용자가 유효한 사용자인지를 체크한다고 합시다.  이럴 경우 일단 계정 서비스의 주소를 알아야 합니다. 서버 IP가 1.2.3.4 라고 하면, 우리는 1.2.3.4 서버의 주소를 가지고 여기로 리퀘스트를 보내게 됩니다.

그런데 이런 ip가 바뀌어야 한다면? 그렇다면 도메인을 쓰는 건 어떨가요? 도메인을 쓰면, 서버 주소가 바뀌더라도 도메인은 그대로이니… 이제 account.server.com 이라고 가정한다면, 이 도메인 주소를 이용하면서 좀 더 유연성이 증가했습니다. 그런데, 도메인의 경우는 클라이언트가 해당 주소를 바꿀 경우, 클라이언트가 해당 주소를 캐시하고 있을 수도 있습니다. 분산 시스템에서는 이런 문제를 위해서 Service Registery 라는 것을 정의하는데 여기서 Spring Cloud는 Eureka 라는 것을 제공합니다.

즉, 서비스가 뜰때, Eureka 에 자기는 A 서비스라고 등록합니다. 그리고 누군가 A 서비스의 목록을 주세요 라고 요청하면 Eureka 서버는 그 서버의 목록을 전달합니다. 심지어 서버가 죽으면 자동으로 해당 서버를 서비스 목록에서 제거합니다. 이런것을 보통 클러스터 멤버쉽이라고 부릅니다. (사실 꼭 이런게 아니더라도, IDC 라면 L4 라든지, VIP를 이용해 VVRP 를 이용한 ip 의 변경등을 할 수 있지만, cloud 환경에서는 이런것들이 쉽지만은 않습니다.)

거기다가 일반적으로 멤버쉽을 독립적으로 관리하면, 서버 목록 가져와서 거기서 라운드 로빈이든 랜덤하게든 선택한 다음 해당 주소로 접속하는 코드를 쫘야 하는데, feign 과 ribbon을 이용해서 해당 서비스에 좀더 동일한 방법으로 Eureka에 myservice 라는 이름으로 등록이 되어있으면, 호스트 이름이 account1.service.com 일때,
http://myservice/profiles/me” 라는 형태로 연결을 시도하면 내부적으로
http://account1.service.com/profiles/me” 로 알아서 도메인을 바꾸어줍니다.

그리고 CircuitBreaker 라는 개념을 손쉽게 적용할 수 있도록 해줍니다. hystrix 라는 것을 이용하는데, 예를 들어, 특정 서비스에서 A,B,C,D 라는 서비스의 결과를 가져와서 보여준다고 합니다. A,B,C,D가 독립적이라서 A,B,C는 잘 동작하는데 D서비스가 서비스 불능 상태에 빠져있다면… (Eureka 등에 등록된 서버가 하나도 없다면?)  로직에 따라서는 해당 서비스 때문에, 전체 서비스 결과가 안나올수도 있고, D 서비스의 결과가 Timeout 이 나야만 그제서야 결과가 보여질 수도 있습니다.(깨진 내용이나 등등등) circuitbreaker 를 이용하게 되면, 몇번 시도해서 해당 서비스가 장애라는 판단이 내부적으로 서게 되면, 미리 등록된 failback을 실행시켜줍니다. 그리고 백그라운드에서 해당 서비스가 살아나는지 체크해서 살아나게 되면, 원래 호출을 하도록 해주는 것이 CircuitBreaker 입니다.

사실 위에 설명한 Zuul, Eureka, Feign, Ribbon, Hystrix 등은 전부 Netflix에서 이미 오래전 부터
공개했던 컴포넌트들입니다. 그런데 Spring Cloud의 대단한 점은 이런것들을 아주 쓰기 쉽게 Integration 시켰다는 점입니다. 원래는 개별적으로 사용하기에 조금 어려운 것들을 간단한 설정이나 annotation 만으로 아주 손쉽게 사용할 수 있게 만들었습니다.

결론적으로 Spring Cloud는 여러가지 분산 시스템 개발에 필요한 개념들을 아주 사용하기 쉽게 만들었습니다. 사실 이런 개념들을 알고 적용하는가가… 대규모 서비스에서 개발할 때 필요하는 노하우이기도합니다.(클라우드 나올때도 이제 뭐먹고 살지 고민했는데, Spring Cloud 보니… 이제 나는 굶어죽겠다는 생각만…)

다만, 아주 쉽게 사용하도록 해두었지만… 사실 이걸 제대로 운영할 수준으로 적용하는 것은 쉬운 일이 아닙니다. 왜왜왜? 라고 물어보신다면, 결국 서비스라는 것은 운영에 대한 이슈가 생기기 때문입니다. 그래서 반대로 이 Cloud Native라는 형태가 cloud service 와 결합하면서, 상당히 큰 강점이 생기기도 합니다.(뭔가 모순적이지만… 이게 사실인…)

다시 정리하자면, Spring Cloud는 Cloud Native라는 개념을 효과적으로 풀어낸 구현체입니다. 굉장히 쉽게 만들어둔… 다만… Spring Cloud에서 사용하는 컴포넌트들의 의미를 잘 파악하면, Cloud Native라는 개념을 다른 언어, 다른 컴포넌트로도 풀어낼 수 있습니다.(그러면 저 같은 입개발자는 설 곳이 없어지는…)

클라우드라는 개념이 나왔을때도, 충격을 받았지만…(SE분들이랑 우린 이제 뭐 먹고 사나 했었는데…) Spring Cloud가 나온걸 보니… 또 한번… 굶어죽을 듯한 두려움과, 세상이 또 뭔가 재밌게 변하겠구나라는 생각이 듭니다.