업로드된 파일이 비디오인 경우, 파일을 비디오 스트리밍 처리한다 (결과는 비디오 스트림 서비스 접속 url).
파일이 업로드 될때와 비디오로 생성되었을 때, 파일을 업로드한 유저에게 노티가 된다.
대시보드에서는 업로드 시킨 파일의 상태 (파일사이즈, 파일명, 인덱싱여부, 업로드여부, 비디오url) 가 표시된다.
서비스 구현에 필요한 바운디드 컨텍스트 목록 :
dashboard
drive
indexer
video processing
notification
Instructions
모델링
1. EventStorming Model 생성
위에서 접속한 www.msaez.io 에서 아래로 스크롤하면 MODELING TOOLS 종류들이 나옵니다.
이 중 EventStorming Model의 CREATE 버튼을 클릭해 새 모델을 하나 생성해줍니다.
2. Bounded Context 구분
우선 구글 드라이브 서비스가 총 5개의 마이크로서비스로 구성된다고 가정하고, 단위 마이크로서비스의 범위를 설정해주는 바운디드 컨텍스트를 총 5개 만들어줍니다.
각 바운디드 콘텍스트의 명칭은 위에서 언급한대로 dashboard, drive, indexer, video processing, notification으로 설정해줍니다.
3. Event(오렌지 스티커) 도출
제시된 시나리오를 바탕으로 각 마이크로서비스에서 산출될 결과물을 오렌지색의 ‘Event’ 스티커로 나타내줍니다.
첫 번째 시나리오인 ‘사용자가 파일을 업로드한다’ 라는 이벤트가 ‘drive’ 마이크로서비스를 통해 실행된다고 보면 여기서 도출될 이벤트는 'FileUploaded’로 이름 붙이는 게 좋겠습니다.
두 번째 시나리오인 ‘파일이 업로드 될 때마다 파일의 위치를 파일 이름으로 인덱싱한다’ 라는 이벤트는 바운디드 컨텍스트 ‘indexer’ 내에서 처리되는 것이 적합할 것 같습니다. 이벤트의 명칭은 'FileIndexed’로 설정해줍니다.
세 번째 시나리오인 ‘업로드된 파일이 비디오인 경우, 파일을 비디오 스트리밍 처리한다’ 를 처리할 바운디드 컨텍스트는 'video processing’입니다. 그 안에 이벤트로 'VideoProcessed’를 넣어줍니다.
유저에게 노티를 주고 업로드한 파일을 조회하는 4, 5번째 시나리오는 이벤트로 나타내기에 적합하지 않으므로, 우선 저희가 만들 구글 드라이브 서비스에서는 크게 위와 같은 3가지의 이벤트가 발생한다고 보겠습니다.
4. Event 에 대한 Input 추가
이벤트 스티커를 모두 적용했다면 해당 이벤트를 발생시키는 액션, 즉 input을 설정해줘야 합니다. 여기서 사용되는 스티커는 파란색 스티커인 'Command’와 라일락색 스티커인 'Policy’이며, 모든 액션은 이벤트와 연결되도록 배치해줍니다.
커맨드와 폴리시의 차이점은 해당 액션의 주체에 있습니다. 유저가 직접 행하는 액션은 커맨드로, 시스템에서 자동으로 실행되는 액션은 폴리시로 설정해줍니다.
즉 첫 번째 시나리오인 ‘사용자가 파일을 업로드한다’ 는 유저가 직접 파일을 시스템에 업로드하는 액션을 수반하므로 파란색 커맨드 스티커로 표현해주고, 명칭은 간단하게 ‘upload’ 만 적어줍니다.
그 옆에 스틱맨이 그려진 ‘Actor’ 스티커를 붙여 액션의 주체를 표현해주면 모델의 이해도가 더욱 높아집니다.
반면 2, 3번째 시나리오는 유저가 파일을 업로드한 후 시스템에서 자동으로 해당 파일을 인덱싱해주고 비디오 여부를 판단해 스트리밍 처리를 하는 것이므로, 폴리시 스티커를 적용하는 것이 적합합니다.
'FileIndexed’에 대한 액션은 ‘make index’, 'VideoProcessed’에 대한 액션은 'process video’로 각각 넣어줍니다.
또한 유저가 파일을 업로드하는 이벤트가 완료되어야 그 다음 단계인 파일 인덱싱과 비디오 스트리밍이 진행되므로, pub/sub 라인을 ‘FileUploaded’ 이벤트에서 'make index’와 'process video’로 각각 연결해줍니다.
여기서 pub/sub은 publish/subscribe의 약자로, publish된 이벤트를 폴리시 측에서 subscribe해 그 다음 이벤트가 실행되도록 해주는 것입니다.
5. Aggregate(노란색 스티커) 속성 추가
여기까지 작업을 마쳤다면, 보드 왼쪽에 위치한 스티커 팔레트의 배치 순서대로 본 튜토리얼이 진행되고 있다는 것을 알 수 있습니다.
그렇다면 다음 순서는 커맨드와 폴리시 아래에 있는 노란색 스티커, 'Aggregate’가 되겠죠.
어그리거트는 모든 액션(input)과 이벤트(output) 사이에 위치하며, 해당 액션과 이벤트로부터 얻어지는 데이터를 표현할 수 있는 대표단어를 찾아 이름으로 지정해줍니다.
drive 측에서 얻을 수 있는 가장 대표적인 데이터는 유저가 업로드한 파일이므로, 'File’을 이름으로 넣어줍니다.
indexer와 video processing 측에 위치한 어그리거트의 이름은 비교적 쉽게 도출됩니다. 파일을 업로드했을 때 진행된 인덱싱 작업의 결과물인 'Index’와 스트리밍 작업의 결과물인 'Video’를 각각의 이름으로 넣어주면 됩니다.
이렇게 3개의 어그리거트를 선언해준 후에는, 각각의 속성 정보를 입력해줘야 합니다. 여기서 입력한 속성 정보는 차후 이벤트스토밍 모델을 토대로 코드를 생성할 때 사용됩니다.
어그리거트 스티커를 더블클릭해 ‘Attributes’ 부분을 보면 이미 Long 타입의 id가 기본 속성으로 선언되어 있는 것을 볼 수 있습니다. 여기에 부가적인 속성을 추가하는 작업이 필요합니다.
가장 먼저 File의 속성을 정의해보겠습니다. 평소에 로컬이나 서버에 파일을 업로드할 때 표기되는 값들을 생각하면 작업이 편합니다.
File
Type
Name
Long
id
String
name
Long
size
Date
createdTime
String
type
String
userId
String은 문자열, Integer는 4바이트의 기본 숫자열, Long은 Integer보다 큰 8바이트 용량의 숫자열, Date는 날짜를 표시해주는 데이터 타입입니다.
업로드된 파일의 속성을 모두 정의해준 후에는 인덱싱 및 비디오 스트리밍 작업의 결과에 대한 속성까지 추가해주면 이번 스텝이 마무리됩니다.
Index
Type
Name
Long
id
Long
fileId
List(String)
keywords
Video
Type
Name
Long
id
Long
fileId
String
url
두 결과물 모두 업로드한 파일을 기반으로 생성되므로 고유의 키값인 id 외에 파일을 식별하기 위한 'fileId’가 들어가야 하고, Index의 경우에는 파일의 이름으로 인덱싱된 ‘keyword’, Video는 스트리밍 서비스로 접속 가능한 'url’을 추가로 설정해줍니다. 여기서 keyword의 경우 여러 개가 나올 수 있으므로, List 타입의 String으로 설정해줍니다.
6. Event 속성 추가
어그리거트에 필요한 속성 정보를 추가했다면, pub/sub 기능을 활성화해주기 위해 이벤트 쪽에도 동일한 정보를 입력해줘야 합니다.
이벤트 스티커를 더블클릭하면 어그리거트와 동일한 ‘Attributes’ 영역이 있고, 그 아래에 Sync Attributes 버튼이 있습니다. 이 버튼을 클릭하면 해당 이벤트와 연결된 어그리거트에 등록된 속성 정보들이 복제됩니다.
이와 같은 방식으로 앞서 도출한 3개의 이벤트에 대한 속성 정보를 추가해주면 됩니다.
7. notification Policy 추가
유저에게 노티를 주는 기능은 간단하게 폴리시 하나를 선언해줌으로써 구현 가능합니다.
‘notify to user’ 라는 이름의 폴리시를 ‘notification’ 바운디드 컨텍스트에 넣어주고, 해당 액션이 실행되기 위한 pub/sub 라인을 그려줍니다.
시나리오에서는 ‘파일이 업로드 될때와 비디오로 생성되었을 때, 파일을 업로드한 유저에게 노티가 된다’ 라고 했으므로, FileUploaded 와 VideoProcessed 이벤트가 퍼블리시 되었을 때 해당 폴리시가 실행되도록 설정해줍니다.
8. ReadModel(초록색 스티커) 속성 추가
마지막 시나리오에 등장하는 파일의 상태를 표시하는 대시보드는 초록색 스티커인 'ReadModel’로 나타내줍니다. 리드모델에서 설정해주는 CQRS는 서비스 운용에 큰 역할을 하게 됩니다.
우선 남아있는 바운디드 콘텍스트인 dashboard에 리드모델을 하나 추가하고 이름은 'Dashboard’로 선언해줍니다.
그리고 여기서도 속성 정보를 추가해야 하는데, 시나리오에서 제시된 대시보드 상에서 나타내야 할 요소들(파일사이즈, 파일명, 인덱싱여부, 업로드여부, 비디오url)을 추가해줍니다.
Dashboard
Type
Name
Long
id
String
fileName
Long
fileSize
Boolean
isCreated
Boolean
isIndexed
String
videoUrl
9. ReadModel CREATE WHEN 추가
다음 스텝은 우리가 제작한 모델에 대한 CQRS 규칙 선언입니다.
CQRS란 Command and Query Responsibility Segregation의 약자로, 시스템에서 명령을 처리하는 책임과 조회를 처리하는 책임을 분리하는 것이 핵심입니다.
Create, Update, Delete의 3가지로 크게 구분되며, 어떤 상황에 내용이 생성되고 수정되고 삭제되는지에 대한 규칙을 선언해주는 파트입니다.
우리가 제작하고 있는 구글 드라이브의 경우 파일이 업로드 되었을 때 모든 액션이 시작되므로, Create 절에는 FileUploaded를 선언해줍니다.
// 컴포넌트 검색창 여는 단축키
// 맥 환경이라면 command + p
// 윈도우 환경이라면 ctrl + p
Index.java 파일 내 makeIndex 메소드를 아래와 같이 변경해줍니다.
public static void makeIndex(FileUploaded fileUploaded){
Index index = new Index();
index.setFileId(fileUploaded.getId());
index.setKeywords(Arrays.asList(fileUploaded.getName().split(' ')));
repository().save(index);
}
코드의 내용을 살펴보면, 인덱스의 fileId 에는 업로드된 파일의 id를 담아주고, keywords에는 업로드한 파일의 이름을 빈칸(스페이스)로 나누어 각각의 단어로 저장해주는 코드입니다.
코드 수정 작업이 끝나면 앞서 진행한 것과 같이 indexer 폴더에서 터미널을 열어 스프링부트를 실행하는
mvn clean spring-boot:run
명령어를 입력해 줍니다.
17. 테스트용 파일 업로드
index 기능까지 활성화가 된 것을 확인했다면, 본격적으로 파일을 하나 업로드해 우리가 지금까지 작업한 내용이 시나리오를 충족하는지 확인해 보겠습니다.
앞서 업로드한 파일의 이름인 my favorite video를 빈칸으로 나눈 3개의 키워드가 위와 같이 리스트에 담겨있는 것이 확인되면 indexer의 기능도 정상적으로 작동함을 의미합니다.
19. video 코드 수정 및 서비스 실행
이번엔 Video.java 파일 내부 코드를 수정해 업로드된 동영상 파일에 대한 스트리밍 url을 도출하는 작업을 진행해보겠습니다.
이전과 동일하게 컴포넌트 검색창을 열고 Video.java를 검색해 열어줍니다.
해당 파일에서 processVideo 메소드 내부의 코드를 아래와 같이 변경해줍니다.
public static void processVideo(FileUploaded fileUploaded){
if('movie'.equals(fileUploaded.getType())) {
Video video = new Video();
video.setFileId(fileUploaded.getId());
video.setUrl('http://youtube.com/' + fileUploaded.getName());
repository().save(video);
}
}
코드의 내용은, 비디오의 fileId에는 업로드된 파일의 id를 담아주고, url에는 유튜브 링크 방식으로 http://youtube.com/ 뒤에 등록된 파일명을 붙여주는 식으로 담아주는 코드입니다.
그 후 video processing 폴더에서 터미널을 열고
mvn clean spring-boot:run
명령어를 입력해 스프링부트를 실행해 줍니다.
20. 업로드된 파일에 대한 video processing 작동 확인
8084 포트에서 실행되고 있는 video processing 마이크로서비스의 작동 여부를 확인해보겠습니다.