MSA란 무엇일까?


MSAMicroService Architecture의 줄임말이다 즉 아주 작은 마이크로 단위의 서비스로 구성된 프레임워크라고 볼 수 있다.

기존에는 하나의 프로젝트에 모든 기능들을 구현해두었다면 여러 개의 작은 프로젝트를 조합하여 하나이 큰 프로젝트와 같이 구성하는 것이다.

MSA의 등장 배경

  • MSA는 언제부터 사용된 개념일까?
  • Monolithic Architecture라는 개념이 있다 쉽게말해 MSA가 등장하기 전 모든 서비스들은 Monolithic Architecture로 구성되어 제공했고 위 설명과 같이 모든 서비스들이 하나의 프로젝트에 통합되어있는 형태를 뜻한다.
  • 당연히 하나의 프로젝트에 모든 서비스가 포함되어있을 경우에 문제점도 존재하며 다음과 같다
    1. 프로젝트가 커지면 커질수록, 영향도 파악 및 전체 시스템구조 파악에 어려움이 있다.
    2. 각 서비스들을 부분적으로 scale-out 하기 힘들어진다.
    3. 부분의 오류가 서비스 전체의 오류로 이어지는 경우가 발생할 수 있다.
    4. 프로젝트 빌드 및 테스트 시간이 길어지고 배포파일 자체의 절대적인 시간이 늘어난다(당연히 용량이 커지기때문이라 생각한다)

이 두가지 Microservices Architecture와 Monolithic Architecture를 그림으로 보자면 아래와 같다.

Figure 1: Architecture differences between traditional monolithic applications and microservices

[이미지출처] (https://www.suse.com/c/rancher_blog/microservices-vs-monolithic-architectures/)

위 단점들을 보완, 해결 하고자 MicroServices Architecture를 사용하기 시작했고 장단점을 정리하자면 다음과 같다.

장점

  1. 각 서비스가 모듈화되어있기 때문에 모듈끼리 RPC 또는 message-driven API 등을 이용하여 통신한다.
  2. 각 서비스에따라 개발하기 때문에 유지보수가 쉽고 팀단위로 적절한 수준에서 기술스택을 선택할 수 있다.
  3. java Spring 기반으로 MSA를 적용하더라도 node.js 모듈과 연동함에 무리가 없다.
  4. 각 서비스별로 독립적인 배포가 가능하며 각서비스별 단위테스트 역시나 가능해진다.

단점

  1. MSA구조는 모놀리식에 비해 상대적으로 복잡하다.
  2. 서비스가 모두 분산되어있고 서비스별 통신이 필요하기에 개발과정에서 내부시스템의 통신을 어떤 방식으로 사용할지 표준을 정의해야 한다.
  3. 서버부하에 따라 transaction을 유지할지 결정하고 구현해야 한다.
  4. 단위테스트에는 장점이 있으나 통합테스트과정이 매우 어렵다.
  5. 또한 운영환경에 배포하는 것 또한 쉽지 않다.( 만들어두었던 모든 서비스들을 묶어서 배포해야 하고 유지보수측면에서 각서비스업데이트마다 배포파일을 교체해주어야 하는 작업이 필요하다 또한 업데이트순간 모든 서비스들이 정상작동하는지를 한번 더 확인해야 하기 때문에)

장점과 단점 모두 실무에서는 도메인에 맞게 활용할 수도 활용하지 않을 수도 있다고 생각한다.

무엇보다 고객의 트랜잭션관리 부분이 가장 어려울 거라 생각이 든다.

오늘은 MSA구조가 무엇인지 알아보았다.

Reference

  1. https://mydream72.tistory.com/entry/%EC%95%8C%EA%B3%A0%EB%B3%B4%EB%8B%88-MSA%EB%9E%80
  2. https://hahahoho5915.tistory.com/71

'지식 창고' 카테고리의 다른 글

REST API란?  (0) 2022.09.12
HLS protocol 이란 무엇일까?  (2) 2022.09.11
프레임워크랑 라이브러리는 뭐가 다를까??  (0) 2022.09.03

REST API 란?


흔히 웹 개발자라면 REST API , REST ful 이란 말을 들어보셨을 겁니다.

 

 

이 REST API는 명확하게 무엇을 의미할까요?

 

 

REST를 한번 뜯어봅시다.

 

REST : Representational State Transfer API의 뜻으로 2000년대 웹의 장점을 최대한 활용할 수 있는 아키텍처입니다.

 

 

여기서 API는 Application Programming Interface로 애플리케이션에서 프로그래밍을 구축하고 통합하는 정의 및 프로토콜입니다. 흔히 API를 직접 프로젝트에서 활용할 때는 개발자(생산자)와 소비자(클라이언트)가 필요로 하는 호출(Request)과 응답(Response)을 구축합니다. 컴퓨터나 시스템에 사용자가 원하는 정보를 호출 및 응답받을 수 있도록 도와주는 조정자라고 생각하면 좋을 것 같습니다.

 

 

이어서 REST API를 설명하기 전 URI와 URL의 개념을 한번 짚고 넘어갑시다.

 

 

URL, URI 많이 들어봤는데 실제로 명확하게 어떤 차이점이 있을까요?

 

 

URN과 URL은 사실 URI에 포함되어있습니다.

 

 

URI,URL

위 사진을 보면 조금은 감이 오실까요?

 

 

위치는 고정적이며 식별자라고는 말할 수 없기 때문에 URL이며 URL 속 식별자를 이용해 특정 데이터를 지정할 수 있습니다.

 

 

이처럼 REST API를 이용할 때 URI를 통해 특정 데이터를 호출하고 응답받을 수 있습니다.

 

 

REST API 구성요소


 

REST API는 3가지의 구성요소가 있습니다.

  • 자원(RESOURCE) - URI
  • 행위(Verb) - HTTP method
  • 표현(Representations) - Representation of Resource

여기서 자원은 위에서 설명드린 URI개념으로 서버에 특정 자원을 Identifier로 구별하고 호출할 수 있어야 합니다.

 

 

행위(Verb)는 기본적인 HTTP 요청 Method로 Get, Put, Delete, Post, Patch를 통해 서버에 요청을 보낼 수 있어야 합니다. 우리는 흔히 CRUD(Create, Read, Update, Delete 기능을 구현하는 것과 매칭 된다고 보시면 됩니다.) 기능을 구현하고 이를 앞에 메서드에 맞게 구현합니다.

 

 

표현은 위 자원을 나타내는데 이 자원을 주고받기 위한 형식이 일반적으로 JSON, XML 형식이라는 것입니다.

 

 

그래서 이 구성요소로 어떻게 한다는 건데~라고 생각할 수 있는데

 

 

위 구성요소를 활용해 REST API라고 불리는 아키텍처 규칙에 맞게 구현해야 합니다.

 

 

이 설계 규칙을 모두 적절하게 잘 지켰을 경우 우리는 RESTful API라고 말할 수 있습니다.

 

 

이 REST API의 설계 규칙은 다음과 같습니다.

 

 

1) Uniform (유니폼 인터페이스) - 일반성의 원칙을 적용하고 아키텍처를 단순화하고 상호 작용의 가시성을 향상할 수 있다. 즉 리소스(자원)를 간결하고 명확하게 그리고 고유한 표현을 통해 식별할 수 있어야 합니다 ( URI를 조금 더 명확하게 네이밍하고 이용해야 합니다.)


2) Stateless (무상 태성) - 서버는 작업에 따른 상태 데이터를 따로 저장하지 않습니다 그렇기에 구현이 단순합니다. 또 요청 응답 간의 데이터 역시나 저장하지 않으며 사용자에 대한 세션 상태는 완전히 유지해야 합니다.


3) Cacheable (캐시 가능) - REST API는 HTTP의 표준 형식을 이용하기 때문에 캐싱 기능이 존재합니다. 그중에서도 응답에 따라 캐싱 가능과 불가능으로 레이블을 분리하고 캐싱이 가능할 경우 일정 기간 동안 사용자에게 해당 응답 데이터를 재이용할 수 있는 권한을 부여할 수 있습니다. 여기서 사용되는 캐싱 기능 역시 HTTP에 존재하는 캐싱 기능입니다.


4) Self-descriptiveness (자체 표현 구조) - 위 리소스를 특정 고유 표현으로 표현했기 때문에 REST API의 메시지 만으로 어떤 의미에 요청인지를 인지할 수 있는 구조가 되어야 합니다.


5) Client - Server 구조 - 클라이언트와 서버를 명확하게 나누어 확장성을 개선해야 합니다. 클라이언트와 서버가 진화(? 업데이트할 동안) 이 클라이언트 - 서버 간의 인터페이스가 가 깨지지 않도록 합니다.


6) 계층형 구조 - 계층형 구조는 말 그대로 우리가 URI를 참조할 때 ( / ) 표현으로 리소스의 계층을 타고 갈 수 있으며 마지막에는 슬래쉬( / )를 포함하지 않아야 합니다. 또 이 API사이에 보안, 로드밸런싱, 암호화 등의 계층을 추가해 보안성을 강화하거나 Proxy, Gateway 등을 추가해 네트워크의 중간 매체를 사용할 수 있습니다.

 

위 6가지 규칙 중 가장 중요한 것만 기억하자면

URI는 고유명사로 데이터를 명확하게 의미할 수 있어야 하며, 해당 데이터를 활용한 행동은 꼭 HTTP method를 이용해야 한다는 걸 기억하면 좋겠습니다.

 

 

그 밖에도 주의할 점으로는

 

 

( _ ) 표시보다는 ( - ) 하이픈을 사용해야 하고, 파일의 확장자(. jpg )등을 표시하지 않아야 하며, 소문자만을 사용해야 합니다

 

 

저도 역시나 프로젝트를 진행할 때 REST API 아키텍처를 지향하며 설계하고 구성했지만 결과적으로 로컬의 일부 리소스를 끌어다 쓰는 방식의 프로젝트를 종종 사용하곤 했습니다. (동영상, 이미지와 같이 데이터베이스에 담기 껄끄러운 데이터들..) 이럴 때마다 REST API의 설계 규칙에 위배되었다는 것을 오늘 개념을 정리해보며 다시 한번 느끼는 시간이 되었다고 생각합니다.

 

 

Reference


'지식 창고' 카테고리의 다른 글

MSA란 무엇일까?  (0) 2023.01.10
HLS protocol 이란 무엇일까?  (2) 2022.09.11
프레임워크랑 라이브러리는 뭐가 다를까??  (0) 2022.09.03

HLS란 무엇인가?


HLS (HTTP Live Streaming) 이며 주문형 스트리밍 이자 라이브 스트리밍 입니다. 일반적으로 우리는 웹상에서 동영상을 볼 때 한 동영상파일의 전체크기를 다운받고 시청을 하지 않습니다. 한 동영상파일을 잘게 분리한다음 한 조각조각씩 사용자가 순서대로 다운받아와서 동영상을 시청할 수 있는 방식입니다.

실제로 일상생활에서도 동영상을 보다가 HTTP통신환경이 좋지않아 동영상이 끊길 경우가 종종 생깁니다. 저는 이 경우를 버퍼링이 걸리는 경우로 기억하고있습니다. 항상 한 가지 개념을 기억하기 가장 좋은 예시는 본인의 경험의 한 상황으로 연결짓는다면 기억에 오래남는 것 같습니다. 실제로 버퍼링의 의미는 말 그대로 버퍼에 데이터를 담는다는 뜻으로 쓰이고 버퍼링이 걸린다 라는 것은 네트워크 통신이 약해져서 우리가 보고있는 (동영상 데이터)가 버퍼에 담기지않아 지금까지 버퍼에 담아두었던 영상의 부분까지만 시청하고 대기상태에 이르는 상황인 것입니다.

다시 HLS의 얘기로 돌아와서 HLS는 비디오 스트리밍 프로토콜로 Apple사가 개발했고 현재는 다양한 장치에서 이 프로토콜이 활용되고 있습니다.

다양한 장치에서까지 이 프로토콜을 사용하는 이유는 무엇일까요?

HLS의 장점으로는 모든 인터넷 연결 장치가 HTTP를 지원하기 때문에 전용 서버가 필요한 스트리밍 프로토콜보다 간단하게 실행할 수 있다는 것입니다.

또 다른 장점은 HLS스트리밍은 재생에 지장을 주지 않으며 네트워크 상태에 따라 비디오품질을 높이거나 낮출 수 있다는 것입니다. 여기까지 읽었을 때 가끔 영상을 보다가 화질이 안좋아지는 경험을 해보신 분이라면 공감을 하실 수 있을 것 같습니다.

이 때문에 사용자는 시청중 품질이 나빠지거나 좋아질 수 있고(네트워크 상황에 따라) 이 기능은 "적응 비트 전송률 비디오 전송", "적응비트 전송률 스트리밍" 이라고 알려져 있으며 이 기능이 없으면 네트워크가 느려진 경우 비디오 재생이 완전히 멈출 수 있습니다.

여기서 스트리밍에 대한 개념을 한번 짚고 넘어가겠습니다.

스트리밍은 무엇이냐?

  • 스트리밍은 인터넷을 통해 비디오, 오디오 미디어를 전달하는 방식으로 미디어파일을 한 번에 모두 보내는 대신 한 번에 조금씩 지속적으로 사용자 장치에 보냅니다. 원 미디어 파일은 멀리 떨어진 곳에 저장되어 있거나 라이브 스트리밍의 경우 원격 카메라나 마이크를 이용하여 실시간으로 제작됩니다.
  • 위 특징을 읽어보면 HLS의 이야기와 같게 느껴질 수 있습니다. 결론적으로 맞습니다 스트리밍의 방식을 그대로 적용하기 때문입니다.
  • 그리고 이 작은 데이터조각들을 지속적으로 사용자가 다운로드받는 것을 버퍼링 이라고 합니다.

그래서 이 HLS는 적응 비트레이트 스트리밍 방식의 스트리밍을 제공합니다.

그렇다면 이제 HLS 중 H에 대한 이야기가 남아있습니다.

H는 HTTP입니다.

HTTP(Hyper Text Transfer Protocol)는 무엇이냐?

  • HTTP는 네트워크에 연결된 장치사이 정보를 전송하기 위한 어플리케이션 계층 프로토콜입니다. 일반적인 사용자가 액세스할 수 있는 모든 웹사이트와 어플리케이션은 HTTP에서 실행됩니다. HTTP를 통한 데이터 전송은 일반적으로 용청과 응답에 따라 이루어지며 이 HTTP의 통신방식은 추후 다른 게시글을 통해 자세하게 설명해드리겠습니다. 현재는 이 HTTP는 목적지와 편지를 주고 받는 개념이라고 생각하시면 좋을 것 같습니다.
  • 그리고 이 HTTP를 스트리밍의 경우 표준 요청 응답 패턴이 적용되지 않습니다. 클라이언트와 서버 사잉의 연결은 스트리밍 기간 동안 열려 있고 서버는 비디오 데이터를 클라이언트는 비디오 데이터 세그먼트마다 요청하지 않아도 됩니다.
  • 또한 HTTP통신 중 데이터를 주고 받을 때 흔히 발생하는 CORS, CORB 에러가 있습니다. 이 에러는 HTTP의 구조를 조금 더 명확하게 알고 있다면 수월하게 해결할 수 있으며 이 문제역시나 다른 게시글에서 조금 더 깊게 다루어 보겠습니다.

이 HLS의 또 다른 특징으로는 스트리밍 데이터를 .m3u8 확장자와 .ts확장자를 가진 파일로 분리한다는 특징이 있습니다.

저는 이것을 직접 구현하기위해 우선 ffmpeg 프로그램을 이용해 동영상 파일은 분리하는 작업을 진행했습니다.

코드는 다음과 같고 ffmpeg파일은 HLS관련 코드를 검색하시면 쉽게 구하실 수 있습니다.

const ffmpeg = require('fluent-ffmpeg');

const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg');

//ffmpegInstaller는 ffmpeg만 사용했을 때 생겼던 오류를 해결하기 위해 사용.
ffmpeg.setFfmpegPath(ffmpegInstaller.path);

ffmpeg('videos/고등어조림.mp4', {timeout : 432000}).addOptions([
    '-profile:v baseline',
    '-level 3.0',
    '-start_number 0',
    '-hls_time 10', // hls_time : 몇 초 단위로 동영상을 분할할 것인지 설정
    '-hls_list_size 0',
    '-f hls' // 포맷을 설정 -> HLS사용.
]).output('videos/output.m3u8').on('end',() =>{
    console.log('end');
}).run();

소스를 보시면 fluent-ffmpeg라는 것을 처음 불러오고 이 ffmpeg를 통해 "videos/고등어조림.mp4" 라는 동영상 파일을 옵션에 맞게 분할하는 것을 생각해볼 수 있습니다. 그리고 output부분을 확인해보시면 m3u8의 확장자로 뽑아내는 것을 확인할 수 있습니다.

이렇게 m3u8파일만 뽑는 것처럼 읽을 수 있으나 m3u8뿐만 아니라 ts파일 역시 같이 만들어지게되고 이 m3u8은 ts파일들의 순서를 기록하는 설명서역할을 합니다.

즉 웹 브라우저는 HTTP통신을 통해 처음 m3u8파일을 최초로 가져오게되고 이 m3u8의 내용을 읽어 0번째의 ts(동영상 분할 파일)을 가지고와서 영상데이터를 제공하는 방식입니다.

저는 이 HLS protocol을 이용하는 방식을 React X Spring Boot에서 이용해 보았습니다. 처음 설계를 진행할 때는 이 Spring Boot가 스트리밍 서버의 목적에 맞지 않고 조금더 범용적인 여러 기능을 핸들링할 수 있는 백엔드서버의 역할성 때문에 또 다른 백엔드서버인 Nodejs를 활용해 스트리밍서버를 구성하려고 했으나 해당 프로젝트를 진행할 때 강사님의 조언으로는 백엔드서버가 여러개 있는 것보단 현재 프로젝트 기준으로써는 하나의 백엔드 서버가 맞다는 이야기에 Spring Boot 백엔드 API서버와 React의 react-hls-player를 통해 이 프로토콜을 활용하게 되었습니다.

해당 프로젝트의 소스코드가 궁금하신 분들을 위해 아래 깃허브 링크를 남겨두겠습니다.

이상으로 HLS Protocol에 대한 간단한 개념 정리글을 마치겠습니다.

https://github.com/ukjinlee66/metanet_internship_project

HLS에 대한 기초적인 소스코드를 확인하고싶다면 root위치에 streaming_server/HLSTest 를 확인해주시면 감사하겠습니다.

Reference

'지식 창고' 카테고리의 다른 글

MSA란 무엇일까?  (0) 2023.01.10
REST API란?  (0) 2022.09.12
프레임워크랑 라이브러리는 뭐가 다를까??  (0) 2022.09.03

Framework VS Library 차이가 무엇일까??


개발관련공부를 하다보면 한번쯤 의문을 가질 수 있을것이다.

 

라이브러리는 알겠는데 프레임워크는 무엇인지 잘 모르겠다..

 

 

혹은 프레임워크는 알겠는데 라이브러리는 뭔지 모르겠다..

 

 

내가 생각할 때는 우선 크기가 다르다고 생각을 한다.

 

 

프레임워크 자체는 환경적인 것이라 생각하고 라이브러리는 환경보다는 작은 내가 마음대로 수정하고 이용할 수 있는 것으로 생각한다.

 

즉 환경이란 것은 말 그대로 구성되어있기 때문에 특별하게 사람이 수정할 수 없고 주어진 환경에서 활동할 수 있다.

 

그리고 라이브러리라는 것은 주머니 속 물건처럼 내가 필요할 때마다 꺼내고 사용할 수 있으며 수정할 수 있다.

 

여기까지가 내 생각이고 이후 정의를 한번 살펴보자.

 

프레임워크 (Framework)

프레임워크는 Frame + work로 합성어다.

Frame(틀)을 Work(일하다) 이용한다. 즉 틀을 가지고 활용한다 사용한다라고 볼 수 있다.

 

여기서 틀은 레고라고 생각하는 것도 좋다고 본다. 레고는 블록이라는 틀로 구성되어있으며 특정 모양을 가지고 여러 결과물(집, 차 등등)을 조립하여 만들어 볼 수 있다.

 

즉 레고 자체의 모양을 직접 바꿀 수 없게 틀로 구성된 자원을 가지고 특정 규칙을 통해(레고를 조립하는 방법) 결과물을 만들어 내는 것이다.

 

그래서 나는 이것을 환경이라고 외우고 있다.. 받아들이기 편한 비유법을 통해 이해하고 넘어간다면 오랫동안 기억할 수 있을 것이다.

 

그래서 이러한 Framework는 Spring, Spring Boot, Django 등이 존재한다.

 

해당 환경에서 특정 요소를 가지고 여러 결과물들을 만들 수 있기 때문이다. 다만 Spring이라는 틀에서 제공하는 요소 자체는 변경이 불가능하다.

 

라이브러리 (Library)

라이브러리는 그나마 친숙할 것이라 생각한다.

 

C, C++, Java, Python 등의 프로그래밍 언어를 공부하다 보면 공통적으로 코드 상단의 가장 처음 불러오는 것이 있다.

 

#include <stdio.h> // 스튜디오라는 헤더
#include <math.h> // 매스라는 헤더

int main()
{
  printf("라이브러리는 무엇일까?");
  return 0;
}

 

우리는 구현을 진행하며 이러한 header file 속의 함수를 가져와서 사용할 수 있고 또한 이러한 header file을 직접 만들어서 사용할 수도 있다.

 

/* header file */
#include <stdio.h>

# define SIZE 1024
# define MAX_NUM 2147483647
# define MIN_NUM -2147483648

typedef struct    n_list
{
  void        *data;
  struct    n_list    *next;
}
그럼 이 헤더는 라이브러리인가??

 

또 그건 아니다.

 

 

결과를 먼저 말하자면 라이브러리는 기계어로 번역된 바이너리이며 헤더 파일은 컴파일러가 컴파일하기 전 프로그래머가 이해할 수 있는 언어이고 컴파일러가 이런 헤더 파일들을 가지고 심볼네임을 만들고 후에 오브젝트파일이 생성된다. 이후 링커가 심볼네임을 가지고 라이브러리를 찾아 링크시키게 된다.

 

 

즉 헤더가 여러 개 모이는게 라이브러리가 아니며 라이브러리는 컴파일된 바이너리이므로 소스파일의 컴파일된 오브젝트파일들을 여러개 묶어놓은 것이 라이브러리이다.

 

오브젝트 파일은 리눅스, 맥에서는 (. o 파일로) 윈도우에서는 (. obj) 파일로 표현된다.

 

라이브러리는 리눅스의 경우 .a 로 표현되고 윈도우의 경우에는 .dll 로 표현된다.

 

그리고 간혹 맥에서 .dylib라는 파일도 있는데 이것은 동적 라이브러리라고 불리며 윈도우에서의 .dll과 유사하다.

 

자 여기까지 라이브러리를 헤더 파일을 통해 설명해보려고 했으며 이해하지 못해도 괜찮다! 사실 한 줄만 기억해도 상관없으며 후에 컴파일 과정을 꼼꼼하게 공부한 후 다시 한번 읽어본다면 조금 더 깊이 이해할 수 있을 것이다.

 

라이브러리는 내가 마음대로 수정하고 이용할 수 있는 것이라고 말했다.

 

라이브러리는 프레임워크보다는 작은 단위로 도구 모음 들이며 이러한 하나의 도구와 같은 것을 직접 만들 수도 수정할 수도 사용하지 않을 수도 있다.

 

라이브러리는 도구의 모음이다.

 

프레임워크라는 환경 속에서 해당 프레임워크의 규칙을 지키며 아무 라이브러리나 불러서 사용할 수 있다.

 

나는 산이라는 프레임워크 속에서 나무를 베고 싶은데 (톱, 도끼)라는 라이브러리를 이용하겠다.

 

로 말할 수 있다.

 

엄밀히 따지자면 더 깊은 개념이 있다고 생각이 있으며 틀린 말도 있을 수 있다고 생각한다.

 

내가 아직 공부한 것이 부족할 수 있기 때문에..

 

그래도 이 두 가지 개념이 헷갈렸던 사람들은 이 글을 보고 조금 더 쉽게 이해하고 넘어갔으면 좋겠다.

'지식 창고' 카테고리의 다른 글

MSA란 무엇일까?  (0) 2023.01.10
REST API란?  (0) 2022.09.12
HLS protocol 이란 무엇일까?  (2) 2022.09.11

+ Recent posts