23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
해당 글에서는 Oms를 Cloud-Native 로 전환 개발하면서 내렸던 의사판단 중 Gateway 를 사용하며 겪은 이야기가 정리되어 있습니다. 해당 챕터 이후로는 사용했던 Backend library나 Frontend, 혹은 Cloud base로 Service 를 짜며 겪은 시행착오와 근거들을 같이 연재할 예정입니다. 질문 및 의문점에 대해서는 댓글로 주시면 성심성의껏 답변 드리겠습니다.
서론: OMS Project의 시작
Smart OMS 는 2006년 경 Open 된 외주 생산 관리 전반을 담당하는 MES System 이며, 현재 제조업의 Smart Factory 에서 이루어지는 일반적인 장비 Online 을 통한 MES 연계 구조와 달리, 협력사의 생산이 올바르게 진행되는지 한번 더 검사하는 Gateway 성격이 강하며 이로 인해 장비와 직접적으로 연계되는 부분이 없는 Pure한 Web Service 이기도 합니다.
(시스템의 기능에 대한 이해도를 높이기 위해 동작 원리를 추가적으로 설명하자면, OMS의 실행형 WebClient 서비스를 협력사 Local에서 다운 받아 설치 후, 특정 규칙 하에 데이터를 DB에 넣습니다. 이후 설치된 Client는 협력사의 데이터를 가져와 OMS 쪽 API를 호출하여 Validation 을 수행하고, 해당 생산 이력을 동기화 하거나 외주사 쪽에 에러 메시지를 공유해주는 형식입니다.)
협력사는 Oms Web Client 설치를 통해 자신이 진행하고 있는 하이닉스 생산분에 대해 좀 더 안전하게 생산을 진행 할 수 있습니다. 생산 진행 이력에 대한 Validation 을 협력사의 내부 시스템과 OMS 가 이중으로 해주기 때문입니다. 나아가 외주사의 역량에 따라 특정 Data의 공유를 통해 외주사 장비에 Auto hold를 수행하는 등과 같은 심화 작업을 가능케 하는, 외주사를 관리하는 진보된 기반이라고 요약할 수 있겠습니다.
다만 거창한 시스템 소개와는 다르게, 현실은 시스템이 10년 넘게 큰 변화 없이 동일한 기반으로 유지보수되어 왔습니다. 4.0 버전대의 .NET과 C언어(?!)로 된 두개의 거대한 백엔드와 Miplatform 이라는 구식 JavaScript 만 지원하는 Frontend framework 로 개발을 하고 있는 상태였죠. (심지어 이 Miplatform 이라는 녀석은 XOR 같은 연산자도 지원하지 않았습니다!)
이에 현 Hynix Digital Transformation(DT) 의 목표인 Service Modernization의 일환으로, OMS 의 하드코딩과 Query 범벅인 기존 외주 관리 시스템을 정돈하고, Modern web으로 전환하는것이 해당 프로젝트의 시작 계기자 목표였습니다.
이를 통해 관리자와 개발자는 조금더 빠른 속도로 서비스를 유지보수 해 나갈수 있게 될 것을 기대하였죠.
사실 저는 단순히 Modern web에 맞추어 난잡한 비즈니스 로직을 Query 에서 JPA(ORM)로, 구식 Web에서 Modern Web(React)로 Migration을 목표로 할 뿐, Cloud 전환을 위한 주변 요소에 대한 관심은 전혀 없었습니다. 해당 프로젝트를 시작하는 2019년 초입경, Hynix 사내 Cloud는 Workplace(DC/OS)와 HCP(K8S) 라는 이름으로 나뉘어 각각 구축중에 있었습니다. 이 시점에서는 어느것도 온전하게 구성원에게 서비스가 제공되고 있지 않았으며, 사내에서 Cloud base로 Application을 만든다는 것은 환경상 불가능에 가까웠거든요.
프로젝트 기간으로 주어진 1년동안, 10넘게 무분별하게 누적되어온 비즈니스 로직을 모던 웹으로 전환하는것만 해도 벅찬데 Cloud base 까지 구축해라? 그러던 4월경 같이 OMS를 유지보수하던 사수에게 전화가 한 통화 옵니다. 내부적으로 Cloud에 대한 관심도도 높아지는 상황에서, OMS 만큼 Web 베이스로 전환하기 적절한 서비스가 없는 상황이였기에, 나온 의사결정이였겠지요.
"우리는 Cloud-ready로 가기로 보고하였다"
위 말을 듣고 정말로 Cloud-ready로 가야하는지 한 4번정도 되물었던 기억이 아직도 생생합니다. Cloud-Ready 로 가려면 마이그레이션 수준이 아니라 소프트웨어 아키텍처부터 다시 짜야만 했으며, 가진 인적 자원의 역량까지 생각해본다면 불가능에 가까운 일이라고 생각 되었습니다. 당장 ORM(JPA) 과 React 만해도 다루는데 급급해하는 실정이였습니다.
어쩌랴, 침착을 되찾고 Cloud ready 가 가져야 할 팩터들에 대해 찾아보기 시작합니다. 요약하자면 Cloud-ready란 Application에 관한 이야기이며, IBM 혹은 K8S 진영등에서 각각 이야기하는 핀트는 조금씩 다르지만 공통적으로 이야기하는 바는 아래와 같았죠.
"언제든지 Cloud로 전환할 수 있는 어플리케이션(소프트웨어)"
자.. 서론이 길었지만, 위 목적을 달성하기 위해 1년동안 프로젝트를 진행하며 Skill-up 이 필요한 제한된 맨파워와, 완성되지 않은 사내 Cloud Infra 에서 어떤 논리들로 아이템을 선택해 시스템을 오픈해 나갔는지 본격적으로 시작 해보겠습니다.
(이글에서 MSA에 관한 이야기는 크게 다루지 않습니다. MSA로 쪼개는 이야기는 다른 챕터에서 다룰겁니다.)
본론1: Zuul Gateway 의 도입
앞에서 이미 말했듯 언제든지 Cloud로 전환할 수 있는 Application 이 Cloud-ready 가 된 어플리케이션입니다. Cloud-ready 어플리케이션이 가져야할 요소들에 대해 IBM에서는 아래와 같이 정의합니다. 9 가지 정도되는데, 자세한건 링크를 참조 부탁드리며 OMS 기준으로 중요 팩터들을 뽑아보았습니다.(IBM: Cloud-Ready app 이 가져야할 특성)
위 6가지를 요약하자면 파일시스템에 직접적으로 파일을 생성하지 말것이며, 서비스는 무상태일것이며, 인프라에 대한 의존성을 가져서는 안된다 정도가 되겠습니다.
다음으로 OMS Project가 가진 상황을 정리해 보겠습니다.
결국 개발자들은 생소한 도구들을 학습해 나가며, 이전에 마음대로 생성하던 파일 처리 조차 함부로 다루지 못하며, 완전히 달라진 인증 체계와 함께 구현된 공통 모듈도 하나 없이 완전히 야생에 놓인 상태로 각 서비스를 짜내야 하는데, 그 역량조차 많이 부족한 상태에서, DMZ Base 로 public / private 망에 안정적으로 서비스를 제공해야만 하는 상황에 놓여 있었습니다.
여기서 무작정 개발을 시작하라고 하면, OMS 의 하드코딩과 Query 범벅인 기존 외주 관리 시스템을 정돈하고, Modern web으로 전환하자는 초기 목표고 뭐고 소스는 중구 남방에 Project의 완성 조차도 위험한 상황에 놓여 있었습니다. 이렇게 명확한 목표 없이 개발된 Project 를 추후 Cloud 에 올릴 수 있는 가능성도 매우 희박했죠.
개발자들은 각자 맡은 서비스를 짜낼때 인증/권한 처리도 별도로 해야 했으며, 신규로 서비스가 생성해야 하면 그때마다 IP와 PORT 방화벽처리를 하고, DMZ Layer 에서 Nginx, Apache 든 별도 프록시의 설정을 변경하고, 이를 또 Failover 시켜야 하고, 개발서버는 또 별도로 고민해야하는, 서비스 하나를 만들어낼 때마다 겪어야 하는 고통과 시간 낭비가 이만저만이 아니였습니다.
해당 문제를 해결하기 위한 해결책을 강구하고자 하나.. 시간은 하염없이 지나가 버리고, 2주가 지난 시점, 갈피를 잡지 못한채 쿠팡에 다니던 한 친구에게 지금의 문제를 하소연하는 도중 친구는 Netflix Zuul 과 KONG 이라는 API gateway 라는 키워드를 던져줍니다. 부랴부랴 집에가서 구글링을 해보니, KONG은 사용법이 단순하면서 강력하고, Zuul 은 더 자유로운 커스터마이징이 가능하단 특징이 있었지만, 적용사례가 KONG에 비해 Zuul이 압도적인터라 저는 결국 Netflix Zuul을 채택하고 API(Service gateway)를 직접 만드는 일을 시작하게 됩니다.
물론, 이 Zuul 과 관련된 문서에는 현재 제가 당면한 개발자들이 각자 도맡은 서비스를 짜낼때 고민 해야하는 인증/권한 처리(Stateless) 와, 신규로 서비스가 생성될때 마다 기존 Oms 에 어떻게 포함시킬것에 대한 매우 좋은 해결책을 담고 있었죠.
"Netflix : Netflix OSS - Zuul with Eureka"
Zuul Gateway/Eureka Discovery 는 Netflix 에서 대용량 Traffic 의 동영상 서비스를 제공하기 위해 본인들이 만든 라이브러리 였고, 이를 Netflix OSS 라는 이름으로 대중들에게 Open 합니다.
우선, 우리는 위 이미지를 통해 Netflix 가 제공하는 Zuul Gateway 라는 녀석이 `어떤` 역할을 `어떻게` 수행해주나 알아볼 필요가 있습니다.
1. Zuul Gateway(API Gateway) 는 하나의 단일 도메인에 대한 요청을 (ex>www.naver.com) 특정 path(ex>www.naver.com/mail, /mail 이 path 에 해당) 에 따라 지정된 특정 서비스, 혹은 다른 도메인으로 분기시켜줄 수 있는 기능을 가지고 있습니다.
2. 이 때, Gateway 가 Service 를 성공적으로 분기 시키기 위해 각 서비스 포인트에 어떤 Application 이 살아있는지를 알아야만 하는데, 이 역할을 바로 Service Registry인 Eureka가 수행해주게 됩니다.
▶ Zuul 은 각 서비스의 목록을 가지고 있는 Eureka 와 한쌍을 이루어 동작하게 되며, 각 엔드포인트를 담당하는 Web Service 들은 Spring-cloud 에서 지원하는 간단한 어노테이션을 붙이고 Eureka의 주소를 설정해 주는 것만으로 간단하게 자신의 주소(IP)를 Registry에 공유해 줍니다.
무려 3달간의 다양한 스트레스 테스트와 커스터마이징을 통해, 우리는 외부(public 망)에 api.oms.skhynix.com 같은 하나의 공통 Domain 을 통해 여러 서비스들로 자유롭게 분기할 수 있는 기반을 갖추게 되었습니다.
Gateway 가 가지는 의미는 이뿐만이 아니였습니다. 서비스 권역의 모든 사용자들이 OMS 의 컨텐츠를 이용하기 위해 각 Service 로 진입하기 위해서는 꼭 Gateway를 거쳐야 한다는 원칙이 생기게 되었고, 모든 권한과 인증에 대한 체크 역시 Gateway에서 수행해주면 될뿐이였습니다. 결과적으로, 각 개발자들은 서비스를 만들어내기 위한 기반 설정에는 관심을 끄고, 본인이 구현해야할 비즈니스 로직만 코드적으로 집중하면 될 뿐이였죠. 이는 Gateway 가 다 해결해줄테니까요!
비즈니스 로직적으로 가장 큰 변화가 일어난 부분은 특히, 외주관리 시스템은 각 외주사간의 비밀을 보장해야 한다는 부분을 처리하면서 나타났습니다. 각 회사의 고유 직원 목록, 각 회사의 데이터는 각각의 회사에만 보여야 하는데, 이전 System 에서는 각 개발자가 주의를 기울여 비즈니스 로직에 각 권한처리 코드를 넣는 수밖에 없었습니다. 하지만 Gateway 쪽에 모든 Request 를 한번씩 정규표현식으로 검사하는 권한 검증 코드를 넣은 덕에, 개발자들은 권한관련 변수의 네이밍 룰만 지키면 될 뿐 그 외의 별도로 처리 할 부분은 아얘 사라지게 되었죠.
신규로 서비스가 추가될때마다 반복되는 귀찮은 설정은 Gateway 에 단 네줄의 설정 코드만으로 해결되었고, DMZ에 해당 Gateway 를 실행시킨 뒤, 필요한 방화벽만 사내로 Open 하면 된다고 생각하는 찰라...
본론2: Cloud-ready 에서 Cloud-native 로
마냥 잘돌아가는 줄로만 알았던 만능 Netflix Zuul Gateway인 줄 알았더니만, 무중단(HA: High available) 서비스를 위한 FailOver가 생각보다 민감도가 좋지 않다는 것을 발견합니다. 이는 Eureka에서 Service 가 죽으면 자동으로 제외가 되어야 하는데, 관련속성들을 조정해보더라도 꽤나 Request lost가 일어난 뒤에야 Eureka가 해당 Service 로 요청을 보내지 않게 되었으며, Eureka 의 인스턴스 확인 Page 에서 해당 Instance 가 사라지지 않는 Bug 로 보이는 현상도 존재하여 유지보수시에 혼란을 가져올 여지가 여실히 많았습니다.
결국 저는 위 문제를 해결하지 못하였습니다.(문제에 대한 해결책을 아시는 분은 연락 혹은 댓글 부탁드립니다)
하지만 하늘이 무너져도 살길은 있다고, Service gateway 의 남은 문제와 씨름하던 도중...
"DC/OS 기반으로 구축된 사내 Private Cloud Workplace가 구축 되었다는 소리가 들려옵니다."
현재 HA 특성을 만족시키지 못하는 Service gateway 구성이였지만, Cloud 가 지원하는 대표 장점 중 하나는 바로 이 HA 입니다. 저는 그래서 냅다 이 Zuul+Eureka를 들고 Cloud 내의 서비스와 연동할 수 있냐는 질문과 함께 사내의 Cloud team 과 컨택하게 됩니다.
구축 완료된 사내 Private Cloud는 하나의 서비스(HA 지원을 위한 Multi Container Instance base)당 하나의 포트가 붙어서 제공되는 형태였습니다(ex>www.naver.com:1910). 문제는, 우리가 여태 만들었던 서비스를 Workplace 상에 올린채로 Eureka를 구동 시키면, 정상적으로 각 서비스의 IP를 가져오지 못한다는 문제가 있었다는 것이죠. 이는 Docker Container 위에 올라간 서비스가 Container 에 의해 설정된 내부 IP와 Port를 Eureka 에 던져주지, Docker Container 자체가 가지고있는 주소를 줄 수 있는 방법은 서비스단에서는 알 방법이 없었기 때문입니다.
결국 저는 Cloud team 쪽에 OMS 라는 프로젝트가 가진 각 도메인 리스트를 모두 가져올 수 있는 API Open 을 요청하게 되며, 감사하게도 Cloud team 쪽에서는 이 요구사항을 흔쾌히 들어주었습니다. 이 목록을 받아, Eureka 에 Programmatic 하게 등록하고 나니, Gateway 도 Cloud 쪽으로 정상적으로 Routing 을 하기 시작했죠.
무작정 Cloud-ready 를 목표로 시작했던 서비스 구축이 너무도 간단하게 Cloud Platform와 연동되어 버리고 말았습니다.
사실 위 작업을 개인적으로 평가해보자면 시스템이 온전한 Cloud-native 로 나아가기 위한 첫걸음을 뗀 부분이라고 생각합니다. 기존 시스템에서는 상상할수 없었던, 고도의 유연성으로 타 플랫픔과 연동하는 작업을 수행할 수 있었죠. 추후 Infra 변경이나 Cloud 를 변경 해야 하더라도 OMS 관리자 입장에서는 각 서비스들을 단순히 옮긴 후, Gateway 가 라우팅해주는 Logic 처리만 변경하면 되는 상태인 겁니다. 최종적으로 서비스는 아래와 같이 구성됩니다. Eureka는 사내 Cloud 상에서 Multi Instance로 돌아가며, 그 데이터를 DMZ의 Gateway 가 받아와 내부 서비스 목록을 인지하고, 외부로부터 온 요청을 라우팅 해주는 구조로 완성된 것입니다.
(구체적인 인프라 구조는 보안상 첨부하지 않습니다)
결론
초기 Cloud-Ready 로 시작했던 시스템 구축이 프로젝트 진행 도중 Cloud platform 이 완성되었을 뿐인데, 그 덕에 맥이 빠질정도로 간단한 방법으로 Cloud 로 전환시켜 버릴 수 있었습니다. 이렇게 간단한 방법으로 전환이 가능한 이유에는 Service gateway 가 중심에 있습니다.
(물론, 여기에 다 적지는 않았으나, 개발자분들이 파일 / 메일 관련 처리를 별도 서비스로 분리하자는 원칙들을 충실히 지켜주며,
로깅은 ELK Stack 으로 Cloud team에서 자동으로 지원되는 덕분에 다른 부분들에 대해 신경을 쓸 부분들이 많이 없었기 때문이기도 합니다.
이것이 구축이 끝난 Cloud Infra가 가지는 힘중 하나입니다.)
우리는 여기서 Service(API) Gateway 와 Service Registry 가 유연한 Service 제공에 얼마나 큰 영향을 끼치는지를 인지해야만 합니다. 초기 거대한 Legacy를 단순히 마이그레이션 하는 목표에서 Cloud-ready로, Cloud-ready 목표에서 완전히 Native 로 전환하기 까지, 각 엔드 포인트 서비스 개발자는 주변 환경이 변하더라도 본인이 수행하는 Job 의 처리 방식에 변화가 생기지 않았습니다. 이는 서비스의 진입점과 모든 통제를 Gateway에서 수행했기 때문이였으며, 주변 환경이 기존의 Server 환경에서 Cloud 로 변경되더라도 코드 변경을 통해 커스터마이징 할 수 있는 Netflix OSS(Zuul/Eureka) 도입의 강점이기도 합니다.
"API Gateway 는 비즈니스 로직을 위한 개발자의 관심사는 좁히며, 개발 논리에만 충실하게 만든다."
그 외에도, 새로운 데이터베이스와 연동된 새로운 서비스를 만들고 싶다면 자유롭게 만들어 Oms 에 붙이기만 하면 되는 등, 개발에서 가지는 자유로움은 이전 시스템과 비교할수 조차 없습니다.
여러분들이 추후 사내에서 사외에 서비스를 할 기회나 이유, 혹은 사내에서 엄격하게 추가적으로 권한/인증 검사를 가져가면서 MSA를 구성하고 싶을때 꼭 Service Gateway는 선택이 아닌 필수로 가져가시길 바랍니다. 그 편이 추후 사외/사내의 Infra 환경변화가 생길지라도, 변경점을 비약적으로 줄이고 관심사를 집중할 수 있는 유일한 해결책이 될 것이니까요.
첫 포스팅이라 부족한 부분이 많을텐데, 긴글 읽어주셔서 감사합니다.
P.S. 저는 소프트웨어 코딩을 통해 직접 Customize 한 Gateway 라 , Cloud Team 쪽에서 실질적으로 제공해주는 API Gateway와는 거리감이 있습니다. 왜 Cloud 쪽 Gateway 쓰면 되지 별도로 Gateway를 또 만들었냐? 라고 질문하실 수 있습니다. 이는 Gateway 의 성격 차이 인데, 거대한 시스템에서 Gateway는 여러 Layer로 구성되며 Netflix는 Cloud Infra Gateway 외에 각 서비스가 가진 고유한 로직을 공유하는 방법론을 Zuul과 Eureka로 제시한 것입니다. Cloud Infra의 Gateway는 각 전체적인 권한 혹은 라우팅을 컨트롤 해줄뿐 서비스자체의 고유 권한 로직을 구현해줄순 없으니까요.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.