티스토리 뷰

이번에 MSA를 사용하게 되면서, 백엔드 개발자 각자 한 서비스씩 맡게 되었다.

나는 comment 서비스를 맡게 되었고, 본격적으로 개발하기 전에 module, DB 설정 등을 해주었다.

 

1. SQS, SNS 알림

MSA는 각 서비스마다 독립적이므로, 이전의 Monolithic 방식과는 다르게 다른 서비스의 DB를 참조할 수 없다.

그래서 서비스마다 이벤트를 발행하고, 필요한 이벤트를 구독하는 식으로 진행한다.

 

내가 맡은 comment 서비스에서는, comment_created 알림과 comment_deleted 알림을 발행하고

comment-user_deleted와 comment-post_deleted 알림을 구독한다. user가 삭제되거나 post가 삭제되었을 때 알림을 받아 처리할 수 있게 하는 것이다.

 

2. JWT

JWT는 JSON Web Token으로 당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 간결하고 독립적인 방법을 정의하는 개방형 표준이다. 이 정보는 전자 서명되어 있어 신뢰할 수 있다.

JWT를 암호화하여 당사자 간에 비밀성을 제공할 수도 있지만, '서명된(signed)' 토큰에 중점을 두고 그 안에 포함된 클레임의 무결성(integrity)을 확인할 수 있다. 공개/개인 키 쌍을 사용하여 토큰에 서명할 때 서명은 개인 키를 보유한 당사자만이 서명한 당사자임을 인증한다.

 

우리 서비스에서는 JWT를 모두 사용하여 서명한 당사자만이 접근가능하게 한다. 그래서 각 서비스마다 JWT를 만드는데, 중복되는 코드가 많아 하나의 라이브러리로 만들고 그것을 사용했다.

 

2-1. Module

 

위는 comment의 module 코드이다.

import에 미리 만든 JWT 라이브러리 'CommonModule'을 추가해주었다.

 

2. Controller

먼저, Controller에 관한 코드 가장 위에 @UseGuards() 데코레이터를 사용해 RolesGuard와 JwtAuthGuard를 추가해주었다.

RolesGuard는 권한에 대한 guard로 User와 Admin을 구분한다.

JwtGuard는 jwt 토큰을 자동으로 유효성을 검사해준다.

 

그리고 이를 사용하기 위하여, 특정 권한만 접근하게 할 때 @Roles()를 사용하여 권한을 설정해준다.

 

 

3. 이벤트 발행 및 수신

 

3-1. 이벤트 발행

이벤트 발행을 위하여, JWT와 마찬가지로 미리 만들어놓은 SNS 라이브러리를 import 해준다.

이번에도 comment의 module에 imports: [] 부분에 'SnsModule'이라고 작성하기만 하면 된다.

comment 서비스에서 발행할 이벤트는 댓글이 생성되었을 때(comment_created)와 댓글이 삭제되었을 때(comment_deleted)이다.

그러므로, service에서 댓글을 생성하고 삭제할 때 각각 이벤트를 발행해야 한다. 발행하는 방법은 간단하다.

위는 댓글을 생성하는 코드인데, 이전처럼 댓글을 생성하는 코드를 작성한 뒤, 마지막에 snsService의 publishMessage에 이벤트를 발행하면 된다. 댓글 생성이므로 'comment_created'의 이름으로 발행한다. 댓글이 작성된 post_id도 함께 보낸다.

 

댓글이 삭제되었다는 이벤트도 비슷하다. 댓글 삭제 코드를 작성하고, publishMessage에 post_id와 함께 'comment_deleted' 이름의 이벤트를 발행한다.

 

 

3-2. 이벤트 수신

다른 서비스에서 발생된 이벤트를 받기 위하여, module에서 SqsModule를 추가한다. 이 코드 역시 imports에 작성하면 되고, 다른 서비스에서 comment 서비스로 받을 이벤트에 따라 다음과 같이 작성하면된다.

나의 서비스가 comment이므로 앞에 comment로 표시를 해두고, 받을 이벤트인 'user_deleted'와 'post_deleted' 이벤트(미리 지정한 이름)를 name에 작성한다. 그리고 queueUrl에 우리가 사용하는 아마존 이벤트의 주소에 내가 수신할 이벤트까지 작성한다. SQS URL은 환경변수를 적어둔 .dev.env 파일에 적어두었고, 'process.env.SQS_URL'로 불러왔다.

'user_deleted' 이벤트는 유저가 삭제되었을 때, 'post_deleted'는 게시글이 삭제되었을 때 각각 user, post 서비스에서 이벤트가 발행되어 수신할 서비스들에서 받게 된다.

 

그리고 각 이벤트를 수신했을 때, 처리는 message handler에서 한다.

comment.message.handler.ts라는 파일을 생성한 후, 이벤트를 처리하는 코드를 작성한다.

user_deleted message
post_deleted message

위와 같은 식으로 작성해준다. 실제 처리하는 코드는 service에 작성하는데, user_deleted 이벤트의 경우 service의 deleteCommentByUserID() 함수에, post_deleted 이벤트의 경우 service의 deleteCommentByPostID() 함수에 작성하였다.

유저가 삭제되거나 게시글이 지워진 경우 모두 해당 이벤트가 발생하면 댓글도 자동으로 지워져야 하므로, 둘 다 댓글을 삭제하는 함수이다.

게시글이 삭제된 경우, 해당 post_id를 가진 댓글을 모두 삭제하고, 유저가 삭제된 경우, 해당 user_id를 가진 댓글을 모두 삭제하는 간단한 코드이다.

 

이런식으로 MSA 구조에서 JWT와 이벤트를 발행하고 수신하는 과정을 진행하였다.