728x90

멘토링을 시작한 계기

2022년 3월 부터 6월 까지 인턴을 하였고 인턴이 끝나가는 6월 말쯤 고민이 많아졌다. “인턴을 하던 회사에서 정규직으로 제안이 오면 계속 회사에 남을지”, “공부하는 시간을 가질지” 선택 사항을 두고 고민이 많았다.

 

인턴을 하며 개발이 쉽게만 생각했던 나는, 현업에서의 개발은 절실히 공부의 필요성을 느끼게 했다. 처음에는 현업에서 나 정도면 그냥 하면 되겠지 라는 안일한 생각을 하며 입사를 했었지만, 현업을 몸소 느껴보니 호락호락하지 않았다. 특히 기술적으로 부족함을 많이 느껴 공부할 시간이 필요하다고 생각했다. 그리고 학부때 배운 지식이 파편화되어, 파편 조각들을 모으는 작업이 필요했다.

 

정말 고맙게도 인턴을 하던 회사에서 정규직 제안을 나에게 해주었다. 이미 나의 마음속에 답은 정해져 있었지만, 막상 제안이 들어오니 다시 한번 고민하게 되었다. 그렇지만 앞으로 긴 시간을 따로 내어서 공부할 수 있는 시간이 많지 않다고 생각했다. 이번 기회에 혼자 공부 하는 시간을 가지고 싶었다. 그리고 무엇보다, 개발자로서 자기 주도 학습을 할 수 있는 힘을 스스로 키우고싶었다. 그래야 앞으로 개발자의 길에서 스스로 성장할 수 있는 힘이 생길 것 같다고 생각했다.

 

일단 뭐부터 공부해야할지 감이 오지 않았기 때문에 혼자는 무리가 있었다. 그래서 검색을 통해 나의 요구사항에 맞는 교육과정을 찾았다. 나의 요구사항은 간단했다. “기초부터 탄탄히 하고, 답을 알려주지 않고 스스로 성장할 수 있는 힘을 가질 수 있는 곳”이었다. F-lab이 나의 요구사항에 딱 드러맞았다.

 

정규직을 제안을 해오시던 사수님께 “저는 공부할 시간이 필요할 거같다” 라고 말씀 드렸다. 사수님이 “혼자 어떻게 할건지 구체적인 목표가 있냐, 없으면 회사에 남아 일하면서 공부할 시간을 주겠다”며 정말 감사하게도 이렇게 말씀해주셨다. F-lab 멘토링 과정에 참여할 예정이라고 말씀 드리니, F-lab 이라면 놓아주겠다고 하셨다. 왜냐하면 F-lab에 대한 사수님의 평이 정말 좋았었기 때문이다. 그렇게 인턴 생활을 했던 회사와 좋은 인연으로 남게되었다.

 

 

F-lab 멘토링의 시작

2022년 8월부터 자바 백앤드 코스를 시작했다. 처음에는 부담되는 가격이었다. 인턴 생활을 하며 저축한 돈과 주식으로 번 돈을 모두 나의 미래에 투자했다. “처음에는 이게 맞을까?” 라는 생각과 함께 불안감을 떨칠 수 없었다. 그러나 그 불안감은 멘토님을 만나고 더이상 느끼지 않았다. 뭔지 모를 확신이 들었다. 그렇게 Carrey 멘토님과 인연이 시작되며 6개월의 시간동안 매주 한번씩 만나게 되었다.

 

 

자바 기초 공부

처음 6주는 자바의 신 1, 2권을 읽고 토론하는 시간을 가졌다. 나는 그때까지는 언어를 사용하면서 그 언어를 기초부터 제대로 공부하지 않고 그 언어를 사용해 왔는데, 멘토링을 하면서 기초부터 제대로 배우는 느낌이 들었다. 그리고 실무에서 꼭 필요한 지식과 개념들을 알려주신 점도 알 수 있었다. 앞으로 실무를 하며 이런 개념들을 어떻게 사용되는지 상상이 되어서 좋았다. 그렇게 6주라는 시간이 흐르고 프로젝트를 하기 시작했다.

 

 

프로젝트 시작

처음에는 프로젝트 주제를 정하고 유즈케이스를 만드는 시간을 가졌다. 나는 당시에 스터디 카페를 즐겨 다녀서 스터디 카페 시스템을 만들어보고 싶어서 프로젝트 주제를 스터디카페로 정했다. 그 다음 마일스톤브렌치 전략, 프로토타입을 만들고 개발을 시작했다.

처음 멘토님의 코드리뷰를 받으며 개발을 할 때 멘토님은 객체지향을 강조하셨다. 이론적으로 객체지향을 배웠지만 실제 코드로는 아직 익숙하지 않았다. 그러한 점들은 코드 리뷰를 통해 배워나갔다. 여러가지 기술들을 적용 하려고 노력 하였고, 여러 트러블 슈팅 겪으며 한층 더 성장한 계기가 되었다.

 

개발한 애플리케이션을 배포를 하는 단계에서 CI/CD 부터 Auto scaling, Load balancer, pinpoint 등을 구축하는 경험이 처음이라 나에게 생소하게 다가왔다. 나의 사전에는 불가능이 없기 때문에 계속 문서를 읽고 하다보니 모두 구축할 수 있었다. 이제는 NCP를 자유자재로 다룰 수 있다고 말하고 다닐 수 있을 거같다 😏. 그리고 NCP를 사용하며 정리해둔 블로그 글들이 NCP 공식 블로그에 개제되는 기쁨도 얻을 수 있었다.

 

그리고 API 개발과 인프라 구성이 끝나고 이 API를 사용하고 싶어서 프론트도 개발을 해서 사용해보았다.

 

 

마치며

멘토링을 하지 않았다면 등골이 오싹한 정도라고 표현하고싶다. 스스로 공부하는 힘을 길러주었고, 어떤 개발자가 좋은 개발자인지 스스로 정의를 내려보고 생각해볼 수 있는 힘이 생겼다고 말하고싶다. 무엇보다 자기주도 학습이 가능하다고 생각이 되어서 너무 기쁘고 무엇보다 정말 좋은 멘토님을 만나서 많이 배운거같다. 앞으로 계속 좋은 인연으로 남고싶다.

728x90

최근에 프로젝트를 하고 있는데 배포를할 때 NCP(네이버 클라우드 플랫폼)에서 진행했다. 

네이버 클라우드에서 여러가지 기술을 사용해보았다. 그 중에서 기록 해놓고 싶은 것들을 "적용기"로 기록해두었다. 그 글들을 네이버 클라우드 공식 블로그에서 인용을 했다. 정말 뿌듯했다 🥹 

 

https://m.blog.naver.com/n_cloudplatform/223006590728
https://m.blog.naver.com/n_cloudplatform/223013853228

 

728x90

인턴을 하면서 새로운 것들을 많이 배웠다. 기술들을 마구잡이로 붙여서 그냥 기능만 찍어내는 위주로 개발을 해왔던 나는 이번 인턴을 통해 사수분으로부터 개발론에 대해 많은 것들을 느끼며 더 많은 준비가 필요함을 느끼며 다시 집구석으로 자진 하방 했다. 더 큰 도약을 위한 일보 후퇴라고 믿고 열심히 하고 있다. 유레카의 순간을 안겨주신 나의 사수였던 경석 씨 에게 경의를 표하며 이 글을 써내려 가려고 한다.

 

본론으로 들어가서, hexagonal architecture 기반으로 DDD, TDD, CDD 라는 내가 처음 접해본 방법론으로 개발을 진행했다. 모두 아시다시피

  • DDD - Domain Driven Design
  • TDD - Test Driven Design

이다. 그런데 CDD는 기존에 없던 용어로 알고 있다.

  • CDD - Commit Driven Design

커밋 주도 개발이라고 이름을 붙였다ㅋㅋ Jira에 Task를 만들고 해야 할 작업 내용에 대해 적고 브렌치를 파고 해야할 작업 내용을 계속 생각하면서 코딩을 하자는 취지이다. 그러니까 내가 무엇을 해야 하는지 알고 코드를 작성 하자는 의미였다. ( 항상 나는 A를 개발하면 B, C … 들도 생각이 나서 옆으로 세면서 코딩을 해왔는데 커밋 주도 개발을 하면서 또 다른 좋은 개발론에 대해 생각해보게 되는 계기가 되었다. )

 

이번 포스팅에서는 DDD만 써내려갈 계획이다.

DDD 를 하기 위해 이벤트 스토밍을 하기 위해서 Miro 를 이용했다.

 

본격적으로 내가 인턴을 하면서 DDD 를 설명하기에 앞서 이와 같은 조건들을 사용하여 설계해 나갔다.

  1. 액터(Actor) 는 커맨드(Command) 를 내린다. 예를 들어, “서비스 사용자는 push 알람 설정 변경을 한다.” 는 예시를 들 수 있다.
  2. 커맨드는 애그리거트 단위의 기능을 제공하기도 하고 **액터(이벤트, 유저 그리고 외부 시스템)**에 의해서 수행된다. 이벤트가 들어오면 커맨드(명령)가 실행되고, **유저(어플리케이션)**가 API 를 요청해서 실행되는 경우도 있고, 구글 로그인, 이메일 발송, 알람 발송(Twillio, FCM, OneSignal…) 등 외부 시스템에서 실행할 수 있다. 나는 다른 도메인에서 실행되는 외부 서비스는 해당 서비스를 담당하고 있는 도메인에서 이벤트로 표시하였다.
  3. 액터(이벤트, 유저, 외부시스템)로 부터 시작된 동작의 결과로 이벤트가 생성된다. 이벤트는 액터에 의해 발생한 일을 의미한다. 예를 들어, “push 알람 설정 변경됨" 이 사례를 들 수 있다.
  4. Event의 결과는 Read Model 에 영향을 준다. Read Model은 CQRS 에서 비롯된 개념이다. 말 그대로 읽기와 쓰기를 분리해서 읽기에 특화된 모델이다. 커맨드를 나와서 이벤트가 되면 queue 에 이벤트가 쌓여서 그것을 읽기만 하는 모델이다. 이런 방식은 성능에 장점이 있다. 그리고 단순성이다. 데이터베이스에서 데이터를 가져오는 더 간단한 방법은 없다.
  5. 정책은 “A 이벤트가 발생하면 B 커맨드를 트리거 한다" 를 표현한다. ( 예를 들어 )즉 커맨드는 사실 액터와 Policy에 의해서 트리거 될 수 있는 셈입니다.
  6. 별도로 의문점이나 추후 해결해야하는 티켓이 있다면 핫스폿 으로 표현할 수 있다.

 

이벤트 정의

이벤트들은 CQRS 원칙에 따라 Read 를 제외한 Create, Update, Delete 성질을 가진 이벤트들이 주로 이루고있다. 그 외 Read 는 Read Model 로 표현되는 경우가 많다. SRP를 생각하며 이벤트들을 쪼개는 작업은 정말 애매했다. 그럴 때 마다 잘게잘게 쪼개야 한다는 것을 터득했다. (이 방법이 주로 괜찮았음)

 

이벤트 표현 방법

보통 좌 에서 우로 표현하며, 좌에서는 이벤트를 발생시키기 위한 명령(커맨드)를 배치하고 우에서는 커맨드가 실행하고 발생되는 이벤트 내용을 적는다. 커맨드와 그에 따라 발생되는 이벤트는 주로 동사형태로 작성된다. 

위를 해석해보자면, “이벤트가 왔을 때 sms 메시지를 저장하고 저장되면 sms 전송을 한다.” 로 해석된다.

“완료”는 개발이 완료 되었을 때 표시하는 용도로 사용했다.

 

또 다른 케이스가 있다. 커맨더가 실행되고 난 후 여러가지 케이스의 이벤트가 발생할 수 있다.

위와 같은 상황에서 “push 메시지 저장” 이라는 커맨드가 발생하고 “push 전송 메시지 저장됨" 이랑 “push 비전송 메시지 저장됨" 이 있을 수 있다. 이 때 위와 같이 발생되는 이벤트를 위아래로 표현할 수 있다.

 

 

액터와 정책으로 연결된 어그리개잇들 그리고 그렇지 않은것

처음에 DDD를 접하고 설계를 할 때, 액터가 있는 티켓도 있고 없는 티켓도 있었는데 여기서 좀 헷갈렸다.

이 티켓들을 예시로 들어보면, 액터가 이벤트인것을 알 수 있는데, 액터의 성질인 이벤트가 들어오면 해당 “push 메시지 저장" 커맨드를 수행하고 “push 전송 메시지 저장됨" 이벤트가 발생하면 “push 알람 전송" 커맨드가 실행되는 것을 알 수 있다. 여기에서 또 확인할 수 있는 부분이 “push 알람 전송" 커맨더 앞에 액터가 없는 것을 확인할 수 있다. 이 의미는 외부적으로 API 를 열지 않고 마스터 서버 내부적인 API 라는 뜻이다. 즉 액터가 없으면 외부적으로 API 를 열어놓지 않았다는 의미가 된다.

 

반면 이것은 정책으로 연결되어 있지 않은 티켓이다. 토큰을 등록하는 기능을 하는데 외부로 부터 API 를 열어둔 것을 확인할 수 있다.

 

 

 

 

 

 

 

또 다른 케이스는 이렇게 두 가지의 액터를 가질 수 있다. 해석하자면, 이벤트와 사용자 둘 다 “이메일 메시지 저장"커맨드를 실행하고 “이메일 메시지 저장됨" 이벤트를 발생할 수 있다.

 

지금까지 여러 경우의 이벤트 스토밍 된 티켓들을 봤다. 잘 생각해보면 정책으로 연결되어있는 것이 없을 수록 좋다. 그래야 내부적으로 복잡하지 않기 때문에 서버에 부담을 줄일 수 있기 때문이다. 잘 생각하고 판단해서 티켓들을 만들어야 했다.

 

 

 

Read Model 로 Read 작업 분리 이유

API 로 커맨드가 실행되고 커맨드를 받은 도메인에서 이벤트가 발생하고 queue 에 들어간다. QueryModel 은 queue 에 있는 이벤트들을 끌어와서 처리하는 방식이다. 도메인별로 서버가 각각 따로되어 있는데 비즈니스 로직을 맡고있는 도메인들이 죽어도 앱이 돌아가는 이유는 QueryModel 에서 화면을 보여주고 있기 때문이다. 기능은 수행하지 못할지라도 완전히 앱이 죽는 것 보다 앱을 켜서 사용은 할 수 있는 것이 훨씬 사용자 경험상으로 좋기 때문이다.

 

이 그림에서는 QueryModel 이라고 했는데 ReadModel 이랑 다를바 없다고 보면 된다.

 

TDD

테스트 주도 개발이다. 먼저 테스트 코드를 작성하고 로직을 짜는 식으로 코딩을 해야 진정한 TDD 라고 배웠는데 해보니까 쉽지 않았다. 회사에 들어와 처음 해보는 테스트 코드 작성이기도 한지 생각의 연속이었다. 빨리 서비스를 출시해야하기 때문에 많은 시간이 걸릴 것 같아서 결국에는 로직을 먼저 코딩하고 테스트를 짜는 식으로 하였다. 먼저 테스트 코드를 짜는 방식으로 연습이 필요하다고 느꼈다.

테스트 코드는 각 애그리거트 당 나오는 레파지토리 테스트를 하고 커맨드핸들러 들을 테스트 했다.

 

헷갈렸던 것들

테스트로 푸시메시지를 보내기 위해서 가짜 객체를 DI 해줘야 하는데 Stub 이랑 Spy 가 헷갈렸다.

 

- Stub: 로직에 영향을 끼친다. (Repository 같은 경우는 findbyId 같은것들도 있기에 stub이고, template 같은 것들도 stub이다..)

- Spy: 로직에 영향을 끼치지 않는다. (Send 같은 것들은 send 테스트 해보고 싶은거니까 spy 이다.)

 

이렇게 정리가 되었다.

 

CDD

앞서 말했듯이 커밋주도개발은 어떤것을 개발해야하는지 먼저 생각한 후 지라에 적고, 해당 브렌치를 파고 해당 브렌치에서는 지라에 적은 것들만 개발하자는 취지였다. 다시말해 관심사를 정해놓고 개발하자는 것이다. 예를 들어 

위와 같은 방식을 ⬇️ 이렇게 지라에 스토리로 하든 작업으로 하든 등록을 해 놓고 코딩을 시작하는 방식으로 하였다.

 

hexagonal architecture

육각형 아키텍처는 포트와 어댑터을 가장자리에 두고 비즈니스 로직은 어디에도 의존되지 않아야하는 것이 아이디어이다. 프로젝트의 핵심인 비즈니스 로직을 보호하고 외부 툴 및 기술로 부터 이를 격리하기 위해서 추상화를 하였다. 수시로 변경되는 요구 사항으로 인해 코드에 큰 변경이 필요한 소프트웨어가 아니라고 생각했기 때문에 지속 성장이 가능한 구조라고 생각이 되었다. 추상화는 어디 까지 해야하는지에 대한 질문을 사수분이 던져주셨다. 정말 애매했다. 결론은 Infrastructure 는 추상화 하는 것이 좋고 domain 은 추상화 하기가 어렵다로 났다. 여기에 대한 나의 생각을 덧붙이고 싶지만 육각형 아키텍처를 잘 모르는 상태에서 말하기에는 너무 주제넘는다고 생각한다. 추후 이에 대해 공부를 하면서 더 생각해볼것이다. 이에 대한 더 자세한 내용은 따로 포스팅 할 예정이다.

 

마치며

말로만 들었던 DDD 를 완전히 처음 접해보았다. 이번을 계기로 개발에 대한 나의 인식이 많이 바뀌게 되는 터닝포인트가 되었다. 어릴 때 정말 재미있게 한 레고가 떠올랐다. 처음 레고를 사면 함께 들어있는 설명서도 없이 블록들만 있는 상태에서 설명서를 내가 만들고 그 설명서를 보면서 블록을 가지고 만드는 것 같았다. 처음 배운다고 정말 힘들었지만 조금이라도 알고나니 정말 재미있다. 이런것들을 접하게 해준 나의 사수에게 정말 감사하다.

+ Recent posts