작년 6월 두번째 회사 다닌지 만 1년이 되었을 때 회고를 썼는데 그때는 그당시 내가 가지고 있던 일을 대하는 태도, 첫 번 째 회사에서 받았던 내상을 회복하는 과정을 중심으로 글을 썼었다. 이제는 그 후로 1년이 또 지나 그동안 내가 느낀 것, 배운것들의 변화 기록을 위한 2년차 회고를 써보려한다.

 

작년에는 휴가, 업무, 문화, 연봉, 일할 때 가져야할 태도에 대한 내용을 썼다면 지난 1년은 조금 다른 걸 느꼈고 다른 이유들로 이직을 결심하고 실행에 옮기게 되었다. 작년과 동일하게 아직 같은 회사에 다니고 있지만 계속 이직 준비를 하고 있다. 회사에서 딱히 배운 건 없이 얻은 건 이직 해야겠다 라는 결심밖에 없어서 그거에 대해서만 쓴 글이다. 

 

이직

일단 가장 큰 건 여전히 지금 회사를 떠나고 싶어 계속 이직을 생각하고 있다는 것이다. 다만 달라진 게 있다면 이젠 좀 더 구체적인 방법으로 진짜 이직을 하기 위한 노력을 조금씩 하고 있다는 거다. 

 

올해 들어와서 출근 전이나 퇴근 후에 조금이라도 짬을 내서 개발 공부를 하고, 공고를 지원하고 있다. 또 3월에는 한 SI회사에 지원한 후 면접을 보고 최종합격까지 했지만 같은 업계는 가고 싶지 않았고 면접 본 회사도 근로자에 대한 기본적인 태도가 없어보여 입사를 거절했다. 그리 유쾌한 면접 경험은 아니었지만 그래도 어딘가를 서류합격 할 이력서, 면접 실력은 되는 것 같다는 증거 같아서 나름 희망적인 부분도 있었다.

 

작년에 이직하고 싶었던 이유는 휴가, 업무, 문화 같이 비교적 표면적인 것들이었는데 1년이 지나고 나니 이는 그렇게 큰 애로사항은 아니라는 걸 알게 되었다. 일이 많고 바쁘다보면 힘들긴 하지만 휴가를 못 쓸 수 있는 거고 수직적이고 상명하복의 문화는 그냥 이 집단의 생리이니 내가 여기에 오래 있으려하지 않는 한 크게 문제가 되지는 않겠다 싶었다.

 

그보단 좀 더 개인적이고 일의 본질적인 것들 때문에 이직 생각이 간절히 들었는데, 구체적으로는 회사 업무 방식, 내가 여기서 느끼는 무기력함/수동성 그리고 경영진의 태도이다. 이런 요인들로 인해 이곳에서의 나의 미래를 생각했을 때 이곳에서 시간을 더 보내면 보낼수록 돈은 벌 수 있을지 모르겠지만 시간과 경력, 미래 커리어와 선택권을 잃을 수 있다는 생각에 빨리 떠나야겠다는 생각이 든다.

 

 

1. 회사 업무 방식

회사 업무 특성과 관련해선 얘기할게 참 많은데, 

 

1) 협상 기술이나 업무 효율화를 고민하기 보단 내부 직원들 갈아넣어서 주먹구구식으로 메꾸려는 고질적인 업무 방식

2) 회사 본질 파악 못해서 쓸데 없는 데 시간 낭비하는 경영진

  • 표준화에 집착한다
  • 패키지를 표준화해서 만든다해도 결국 고객사마다 요구사항과 스타일과 기존의 일하는 방식이 다르므로 실상 표준화에 집중하는 게 의미가 없다

3) 사장되는 기술들을 사용하고 있다는 것(경력이 쌓일수록 경쟁력이 떨어진다는 큰 리스크가 있다)

4) 기술 위주가 아니니 금융 업무로 진행되는 프로젝트(기술적 발전 가능성이 크지 않다)

5) 개발 문화 없음(기술적 발전 가능성 크지 않다2)

6) SI라는 특성상 다양한 고객사가 있어 업무 위치가 지속적으로 바뀔 수 있고 그 위치가 대부분 여의도/종로라 직주거리가 멀다는 것(왕복 4시간)

 

위의 3 ~ 6번은 개인이 바꿀수는 없는 부분이기도 하고 이렇지 않은 회사로 이직을 하면 해결될 문제이라 딱히 얘기할 건 없고, 가장 얘기하고 싶은 부분은 1, 2번이다.

 

1) 주먹구구식의 고질적인 업무 방식

작년에는 다른 프로젝트에서 일했는데, PM은 고객사와 갑을관계가 되어 고객들 접대 비용에만 매달 큰 돈을 쓰고 비위 맞춰주느라 시간 없는데 요구사항 무조건 다 수용하고, 업무도 잘 몰라 개발 기간에 업무도 제대로 파악 못하고 인터페이스 관리 못하다가 통합테스트 때 터져서 한 달 내내 전체 직원들에 야근을 강요하고(나같은 경우 현재 사원이고 당시 업무 책임이 많지 않아 야근을 해도 도움을 줄 게 없었는데 다같이 힘들게 일하니 퇴근할 때마다 할 거 더 없는지 확인받고 가라고 했던 적도 있다) 프로젝트 상무급들은 부사장한테 카톡으로 언제 퇴근했는지 보고(;;)하라고 하는 얘기를 듣고 경악했던 기억이 있다. 야근을 하는 것에 불평을 하는 것이 아니라 일이 많고 급한 일이면 야근이 필요하다고 생각하고 그럴 의향도 있다. 내가 말하고자 하는 건 미리 시간 기한에 맞춰서 고객 요구사항 쳐낼건 쳐내고 검토할 거 검토하는 것을 하지 않고(이 역할 하라고 돈 많이 주고 pm 쓰는 거 아닌가) 고객 요구사항, 변동사항 다 받고 직원들보고 야근으로 떼우라고 말하고, 나는 내 할 일이 없는데 더이상 도움을 줄게 없는데 왜 남아있어야하지? 이해가 가지 않았다. 제대로 일을 할 생각은 안 하고 곁다리(아첨, 야근)에만 에너지를 쏟는게 이런 업무 방식을 하는 곳에 더이상 있고 싶지 않았고 이런 업무 방식은 여기선 절대 바뀌지 않을 거라는게 자명해 그냥 생퇴사도 고민했었다. 이렇게 일하는 곳에서 더는 있고싶지 않았다.

 

당연히 고객사가 갑이고 외주사는 일단 돈을 받았기에 그에 최대한 맞춰줘야한다. 이거는 어찌보면 당연하고 자연스러운 일인데 내가 납득할 수 없는 부분은 고객사의 정당한 요구가 아닌 굉장히 불합리한 요구를 끊어내지 못하고 머리를 조아리는데 정작 자기 사람들인 내부 직원들의 안위는 전혀 신경쓰지 않고 착취하는 것을 당연하게 여긴다는 것이다. 들어온 사람은 막 대하고 들어올 사람은 환대하는 뭐 어찌보면 인간이란게 원래 그렇다고도 여기지만 굳이 이런 곳에 내가 있으면서 건강 나빠지고 기분 안 좋고 싶지 않았다. 무엇보다 회사가 여기만 있는 것도 아니고 이 회사에서 경력을 쌓는게 앞으로 내 인생에 그리 도움이 될 것 같지도 않다고 생각해 이 때 절실히 이직을 생각하고 움직이기 시작했다.

 

2) 경영진의 태도

- 업무 본질 불인지와 쓸 데 없는데 자원을 낭비하는 경영진

 

회사의 미래는 여러 요인에 의해 정확히 예측할 수는 없겠지만 경영진의 태도가 어느정도 예측하는데는 도움을 준다 생각한다. 현재 내가 느낀 경영진의 태도는 SI 회사라는 걸 망각한 채 AI 트렌드를 좇아가는 것에 취해 있는 것 같다. 

 

올해 초부터 회사는 AI에 위기감을 느꼈는지 GPU서버와 같이 AI 관련 장비들을 구매하고 서버실 증축에 집중하기 시작했다. 그러면서 계속 하는 말이 ‘이제 신입 안 뽑아. 신입보다 일 잘하는데 싼 AI가 있는데 신입을 뽑는 이유가 없어.’이다. 어느정도 일리는 있다. 이제 AI가 기본적인 화면에서부터 기능 구현까지 웬만하면 다 하는데 시간과 노력 그리고 돈이 드는 신입을 뽑는 것이 비용적으로 손해인 것은 사실이니까. 

 

하지만 한 가지 이 사람들이 망각하고 있는 것은 본인들은 사람으로 장사하는 SI 회사라는 것이다. 결국에 소프트웨어를 만드는 사람을 사이트에 잠깐 파는 게 이 업종의 본질인데 그런 사람이라는 자원을 줄이는 것이 정말 경영진이 자기가 어떤 곳을 운영하고 있는지 알고 있는 것인가 의문이 들었다. 

 

또 프로젝트 특성상 인터넷도 연결 안되는 보안이 철저한 사이트에서 일하는데 거기에 내부적으로 개발한 AI를 일단 들고 가지고 나올 수 있는지가 의문이다. AI 프로덕트를 개발한다고 해도 사이트에선 보안적인 이유로 반입을 안 해줄 가능성이 크고, 설사 반입한다 해도 사이트 데이터로 학습한 AI를 반출하는 건 더더욱 불가능해 보인다. 그럼 사실상 AI에 투자하는게 의미가 없는 것 아닌가 하는 생각이 든다.

 

회사는 이 사실을 모르는건지 아님 애써 외면하고 있는 건지 실제로 나 이 후로 신입은 안 뽑고 있고, AI 부서까지 신설했지만 방향성 없이 중구난방으로 AI 개발을 이어가고 있다. 자기가 운영하고 있는 회사의 본질은 모른채 혹은 애써 무시한 채 헛발질만 하고 있는 경영진을 보면서 앞으로 이 회사의 미래는 그리 좋지 않을 것 같다는 예감이 들어 탈출해야겠다 라는 생각을 했다. 또 이런데 시간, 돈 쓸바엔 기존의 엉망진창인 패키지와 업무방식부터 고쳐야 하는 게 급선무가 아닌가 하는 생각도 든다.

 

2. 수동성과 무기력

- 시간이 지나도 쌓이지 않는 경력과 부족하다는 평가

 

이 부분은 개인적인 부분이긴한데 이 회사에 입사할 때부터 지금까지 만성적으로 계속 느끼는 감정이 무기력이라는 것을 깨달았고, 수동적인 내 모습을 발견하게 됐다.

 

작년에 거의 매일 야근을 하고 야근 강요할 때는 10시에 퇴근하기도 하고 사람들 야근할 때 저녁 취합해서 사오고 보상도 안되는 주말출근까지 했는데 그렇게 개고생을 해놓고 결과적으로 얻은 건 없다는 느낌과 일 열심히 안 했다는 이미지였다.

 

일단 나에게 할당된 화면들은 공통 화면들이었지만 계속 바뀌는 요구사항을 적용하고 여러 잡일들을 하느라 바쁘고 시간이 없었다. 결국 시간을 많이 들인 부분이 공통 화면들이었기에 업무 관련해서 배울 기회가 없었던 건 사실이다. 그래서 프로젝트가 끝나고 본사로 돌아오니 나는 프로젝트에 1년 동안 있으면서 업무도 모르는 사원이 되어 있었다. 처음 이런 대우를 받았을 때 억울함에 눈물이 왈칵 쏟아졌다. 내가 일을 대충하고 편하게 일을 했다면 그냥 넘어갔을텐데 나도 나 나름대로 주어진 일 쳐내느라 쌔가 빠질뻔 했는데 내부 사정도 모르고 표면적으로 드러나있는 걸로 쉽게 판단하고 말로 내뱉는게 속상했다. 오해받는 것 같아 싫었다. 또 시간과 노력은 있는 대로 다 썼는데 정작 업무적으로는 얻는 것은 없다는 것에 허탈하기도 했다.

 

그래도 내가 반성해야할 점은 나도 은근히 업무를 안해도 된다는 것에 안도감을 느꼈던 것이다. 업무를 잘 모르고 왠지 어려워보이니 타의적으로 거리를 두게 됐을 때 거기서 편하다고 생각했다. 강 건너 불구경 하는 느낌이라고 해야하나. 그렇더라도 업무에 대해 파악하고 공부를 하려고 했어야 하는데 그러지 못했던 건 앞으로 내가 개선시켜야 할 부분임은 확실하다.

 

하지만 이걸 통해 점점 알게된 부분이 있는데, 여기를 다니면서 알게모르게 무기력에 젖어들고 있었다는 것이다. 주어진 일만 하고, 그렇지 않으면 할 일이 없고 입사 후 딱히 무언가 배울만한 시스템이나 구조가 없다. 근데 또 업무 능력에 대한 평가를 하니 나는 무언가를 해볼 기회가 없이 무방비상태로 평가를 받는 느낌이 들었고 무기력함을 느꼈다. 내가 행동으로 옮기고 무언갈 실제로 행할 수 있다면 거기서 활력과 능력치를 얻는다고 생각하는데 무언갈 직접 할 기회는 없다 느껴지고 시간은 가는데 내 능력은 쌓이지 않다는 느낌에 위축되었다. 그냥 입 닫고 조용히 있는게 맞는 것 같은 분위기가 나를 점점 말라가게 했다.

 

이는 내가 전혀 지향하지 않는 방향이고 이건 환경 요인도 있다고 생각해 더더욱 이곳을 떠야겠다고 생각하게 되었다. 시간이 갈수록 스스로 무기력해짐을 느끼는 공간은 벗어나는게 나에게 가장 좋은 선택지인 것 같다는 생각을 했다.

 

 

작년 2025년 6월부터 2026 6월까지 이 회사에서의 2번째 1년을 돌아봤는데 이직밖에 안 남아 있네. 작년 말에는 이 이직 생각을 하면서 정작 실행에 옮기지 못했던 내 모습에 현타가 많이 왔었다. 불평불만은 하면서 정작 실행에 옮기지는 않고 있는. 그래서 올 해에는 조금씩이라도 실질적인 이직 준비를 하기 위해 노력하고 있다. 목표는 올 해 안에 이직 성공인데, 솔직히 아직 많이 모자란 것 같고 갈 길이 멀게 느껴지긴 하지만 아무것도 안 하는 것보단 조금씩이라도 발걸음을 떼는게 내가 가고자 하는 방향과 조금이라도 가까워진다는 걸 알기에 계속 해보려고 한다. 내년 회고 글에서는 이직한 회사에 대해 쓸 수 있기를 바라며.

 

 

 

1. NoSQL

NoSQL은 특정한 요구사항에 맞춰 데이터를 저장하고 조회하는 기법을 제공하는 데이터베이스를 말한다. 기존의 RDBMS를 사용하는 것보다 더 적합한 방식일 수 있다.

 

예시로

  • 수천만 회원 간의 연결 관계를 분석해서 친구를 추천하는 기능에는 그래프를 지원하는 데이터 베이스를 사용하거나
  • 대량의 데이터를 실시간으로 수집하고 통계를 추출하는 경우에는 수평 확장을 지원하는 데이터 베이스를 사용하는 것이 있다.

 

NoSQL을 사용하는 이유는 다음과 같다.

  • 수평확장을 통한 데이터 저장 용량 확장으로 대용량 데이터나 분산 처리 가능
    • 예시 : Casandra, HBase
  • 고속의 읽기와 쓰기 성능
    • 트랜잭션의 ACID 기능 일부를 미지원해 일관성보단 DB 접근 속도를 높이고
    • 인덱스를 최소화하고 데이터 분산 저장함으로써 병렬처리로 성능 향상
  • 특정한 요구사항에 맞는 데이터 설계
    • 전통적인 관계형 모델을 사용하는 RDBMS의 저장방식과 반대
    • RDBMS의 조인 기능 미지원
    • DynamoDB : 키 값 형태로 데이터 저장, MongoDB : BSON(바이너리 JSON) 형태로 데이터 저장
  • 비정형 데이터 처리 또는 유연한 스키마
    • RDBMS의 고정된 스키마와 달리 고정된 스키마가 없거나 유연한 스키마를 갖는다
    • 데이터 신규 속성 추가와 같은 구조 변화에 더 유연하게 대처 가능하다

 

RDBMS의 Sharding vs. NoSQL

관계형 데이터베이스도 수평 확장을 할 수 있는데, 그 방식을 샤딩(sharding)이라 한다. 샤딩은 여러 개의 데이터베이스를 구성하고 각 데이터베이스 데이터를 나누어 넣는 식으로 확장하는 방식이다.

Sharding NoSQL
RDBMS는 서로 다른 데이터베이스 10개를 사용하는 것처럼 동작 NoSQL의 클러스터는 개념적으로 데이터베이스가 하나
데이터 베이스 하나에 장애가 발생하면 해당 데이터 베이스에 속한 데이터를 사용할 수 없다. 클러스터에서는 노드 중 하나에 장애가 발생해도 전체 클러스터가 정상 동작 가능

 

2. NoSQL 종류

NoSQL의 종류는 다음과 같다.

  • 키-값 DB
  • 문서 DB
  • 컬럼 패밀리 DB
  • 그래프 DB

 

키-값 DB(key-value DB)

키-값DB는 가장 강단한 형태의 NoSQL인데, 특징은 다음과 같다.

  • 키 밸류를 매핑해서 저장한다.
  • 모든 데이터를 값으로 사용 가능하다.
  • 구조가 단순해서 읽기/쓰기가 빠르다.
  • 예시 : DynamoDB, Redis
    • Redis는 키-값 외에 다양한 형태의 값을 지원한다.
    • 정렬된 집합을 제공해 순위표 쉽게 구현가능하고,
    • 큐 기능을 제공하고 있어 메시징 시스템으로도 활용가능하다

 

키-값 저장소의 주된 용도는 다음과 같다.

  • 세션 관리 : 인증 토큰과 같은 세션 정보를 저장한다.
  • 캐시 : 자주 사용하는 데이터를 캐싱하는 용도로 사용한다
  • 설정 관리 : 설정은 키-값 형태를 가지므로 키-값 DB로 관리하기에 적합하다

 

문서DB

  • 예시 : MongoDB
  • 가장 큰 특징은 스키마가 고정되어 있지 않다는 건데, 데이터를 주로 JSON과 유사한 문서에 저장한다. 
    • JSON 형태면 되므로 RDBMS의 테이블과 달리 복잡하고 중첩된 모델을 쉽게 표현할 수 있다.
    • 새로운 속성이 필요하면 추가하면 되고 중첩된 구조나 배열을 사용할 수 있다.
    • 어플리케이션에서 사용하는 데이터 모델과 DB에서 사용하는 데이터 모델이 거의 일치하는 장점도 있다. (RDBMS에서는 하나의 모델을 저장하기 위해 여러 테이블을 사용해야하는 것과 비교된다)

 

문서DB의 주요 용도는 다음과 같다.

  • 컨텐츠 관리 : 유연한 스키마를 이용해서 다양한 종류의 컨텐츠를 관리한다
  • 제품 카탈로그 : 다양한 메타데이터를 가진 카탈로그(제품/서비스의 설명/사진/가격 같은 상세정보 홍보물)를 제공한다.

 

컬럼 패밀리 DB

예시 : Cassandra, HBase

키-값DB의 확장 버전이라고 할 수 있다.

각 행은 여러 컬럼을 가질 수 있고, 여러 컬럼들을 그룹으로 묶어 관리한다는 공통점이 있다.

대량의 데이터를 저장할 수 있는 수평 확장이 용이한 구조를 갖는다.

 

컬럼 기반 DB의 주요 용도는 다음과 같다.

대규모 데이터 관리 : 채팅 플랫폼의 채팅 메시지IoT 데이터 등 대규모 데이터에 대한 저장과 조회가 필요한 서비스에 사용한다.

 

참고) 컬럼 기반 DB

컬럼 기반 DB 또는 컬럼형 DB는 컬럼 패밀리 DB와는 다르다. 컬럼 기반 DB는 컬럼 단위로 데이터를 저장하는데, 이는 RDBMS의 행 단위로 데이터를 저장하는 방식과 차이가 있다. 컬럼 기반 DB는 OLAP과 같이 데이터 분석을 목적으로 주요 사용된다. 컬럼 기반 DB로는 Clickhouse와 MariaDB ColumnStore 등이 있다.

 

그래프 DB

그래프DB는 데이터를 노드와 엣지가 있는 그래프 형태로 데이터를 관리한다.

노드와 엣지로 데이터의 관계를 표현하며 노드와 엣지는 필요한 프로퍼티를 갖는다.

예시 : Neo4j

 

그래프DB의 주요 용도는 다음과 같다.

  • 소셜 : 소셜 네트워크 그 자체가 그래프다.
  • 추천 : 사용자 관계에 기반한 친구 추천, 사용자 활동에 기반한 상품 추천 등에 활용할 수 있다.
  • 부정 탐지 : 관계에 대한 패턴을 이용해서 실시간으로 이상 사용을 탐지할 수 있다.

 

3. NoSQL 도입 시 고려 사항

NoSQL은 성능, 확장성, 고가용성, 모델 유연함 등 좋은 특징이 있지만 RDBMS가 아닌 NoSQL을 도입할 때는 몇 가지를 고려해야 한다.

 

1) 트랜잭션 지원 여부

다수의 NoSQL은 RDBMS가 지원하는 수준의 트랜잭션을 지원하지 않는다. 따라서 트랜잭션이 필요한 기능에 NoSQL을 도입하려면 해당 NoSQL이 ACID를 지원하는지 확인하고 검증해야 한다. 만약 NoSQL이 원하는 수준의 트랜잭션을 지원하지 않으면 어플리케이션에서 따로 트랜잭션을 보완해야 하고, RDBMS와 NoSQL을 함께 사용할 경우 두 데이터 저장소 간의 데이터 동기화도 고려해야 한다.

 

2) 데이터 모델 요구사항

데이터 모델이 요구사항에 적합한지 확인해야 한다. NoSQL마다 지원하는데이터 모델이 다르기에, 데이터 모델에 맞춰 적합한 NoSQL을 선택해야 한다. 예시로 설문조사처럼 질문/답변이 계층 관계를 갖고 있는 모델은 문서 DB 사용이 적합하고, 단순 캐시가 필요한 경우엔 문서DB보다는 키-값DB가 적당하다.

 

3) 확장성과 성능 요구

일반적으로 NoSQL은 RDBMS와 대비해서 확장성이 뛰어나고 속도가 빠른 특징을 갖지만 궁극적 일관성(eventual consistency)을 지원해 높은 일관성을 요하는 기능에서는 적합하지 않을 수 있다. 따라서 성능과 일관성 면에서 사용하려는 NoSQL이 적합한지 검증하는 단계가 필요하다.

 

4) 운영과 개발 역량

NoSQL을 적용하면 운영과 개발 역량 확보가 필요하다. NoSQL은 백업, 모니터링, 확장 등 관리가 복잡할 수 있기 때문이다. SQL의 조인을 사용하는 것에 익숙한 개발자는 NoSQL이 제공하는 데이터 모델을 사용하는 데에 어려움을 겪을 수 있다. 따라서 NoSQL을 도입할 때에는 팀이 가진 경험을 고려해야 하며 필요하다면 미리 학습해서 기술을 익혀야 한다.

 

4. CAP 정리

분산 시스템에서 주로 언급되는 이론으로 CAP 정리가 있다. CAP 정리는 다음 세 조건을 모두 만족하는 분산 시스템은 존재하지 않는다는 것을 증명한 정리이다.

 

  • 일관성(Consistency) : 모든 노드가 같은 순간에 같은 데이터를 볼 수 있다. 한 노드의 데이터가 변경되면 모든 노드의 데이터도 동일한 값으로 바뀐다.
  • 가용성(Availability) : 모든 요청이 성공 또는 실패 결과를 반환할 수 있다.
  • 분할내성(Partition tolerance) : 네트워크 장애가 발생해도 시스템이 계속 동작할 수 있다.

CAP정리에 따르면 위 조건 중 최대 2가지만 충족할 수 있다.

 

CAP 정리에 따르면 다음의 세 종류로 DB를 나눌 수 있다.

  • CA
    • 모든 노드에서 일관성과 가용성을 제공한다.
    • 즉 모든 노드에서 변경된 최종 값을 사용하고 일부 노드가 다운되어도 나머지 노드가 동작한다.
    • RDBMS가 CA에 해당한다.
  • AP
    • 가용성을 우선하며 분할내성을 제공한다.
    • 노드 간에 네트워크 분할이 발생하면 일관성을 포기하고 기능을 계속한다(가용성).
    • 컬럼 패밀리 DB인 Cassandra가 AP에 해당한다.
  • CP
    • 일관성을 우선하며 분할내성을 제공한다.
    • 네트워크 분할이 발생하면 일관성을 보장할 수 없으므로 분할이 해결될 때까지 (일부 또는 전체) 기능을 차단한다.
    • 문서DB인 MongoDB가 CP에 해당한다.

 

NoSQL은 분산 시스템을 기반으로 하고 있기 때문에 분할내성(P, Partition tolerance)을 기본으로 한다. 따라서 NoSQL은 가용성(AP)이나 일관성(CP)을 우선하는 설계를 선택한다. 따라서 서비스 품질 속성에서 가용성과 일관성 중 무엇을 중점에 두느냐에 따라 선택할 수 있는 NoSQL도 달라진다.

 

 

 

5. 마치며

느리게 공부하고 기록한 과정이 약 4개월 2주만에 마침표를 찍었다.

작년 9월에 본격적인 이직 준비를 하겠다며 이 책을 구매했지만, 속도가 더뎌 10월, 11월, 12월 많이 공부를하지 못했다. 그래서 올해 유일한 목표는 이직 성공으로 정하고 출근 전 스터디카페에서, 주말에 집에서 이 책을 이론적으로 한 번 훑고 블로그에 내용을 정리해서 올렸다. 시간과 체력이 한정적이라 속도가 더디긴 했지만 결국 마무리 했다는 게 후련하고, 이제 다음 단계로 넘어갈 수 있을 것 같아 마음이 가볍다. 결국 이 과정이 오래 걸리더라도 꼭 거쳐야 할 과정으로 생각한 이유는 기본적인 백엔드 지식을 쌓아서 기본적인 상황에서 어버버하지 않기 위해, 추후 면접을 보게 되었을 때 빠르게 참고할 정리된 자료가 높은 확률로 필요할 것 같았기 때문이다. 

 

이제 기본적인 건 습득을 했으니 실용적이고 실무적인 것으로 넘어가고 추후 이직 성공으로도 결과가 이어졌으면 한다. 기록 끝!

 

 

 

 

 

 

1. 성능 테스트

성능 테스트를 통해 서버가 특정 작업 부하 상태에서 응답 시간, 처리량, 자원 사용량(CPU, 메모리 등) 측면에서 시스템이 어떻게 작동하는지 확인하기 위한 작업을 의미한다.

 

테스트 종류

부하(load) 테스트 특정한 예상 부하에서 시스템이 어떻게 동작하는지 확인한다.
효과 : 주요 기능의 성능 지표(응답시간, 처리량) 확인 가능, 병목 파악
스트레스(stress) 테스트 시스템의 최대 성능을 확인하기 위한 테스트이다.
예상을 뛰어넘는 부하가 발생했을 때, 시스템이 어디까지 성능을 낼 수 있는 지를 확인한다.
지속 부하(soak) 테스트 시스템이 지속적인 부하를 견딜 수 있는지를 검증한다.
장시간 동안 일정 수준의 부하를 주어 성능 저하가 발생하는지 확인하며 메모리 누수도 탐지 할 수 있다.
스파이크(spike) 테스트 급격하게 트래픽이 변화할 때 시스템의 반응성과 안정성을 검증하는 테스트이다.
순간적으로 트래픽이 급증했을 때, 성능 저하나 실패가 발생하는지를 확인한다.

 

2. 포화점과 버클존

성능 테스트를 진행하는 일반적인 방식은 낮은 부하에서 시작해서 점진적으로 부하를 높이는 것이다. 이렇게 부하를 증가시키면 초기에 처리량이 같이 증가하다 일정 부하 구간에 도달하면 처리량과 응답 시간이 급격히 저하된다. 이때 저하되기 직전 최대 지점을 포화점이라 한다.

 

포화점(saturation point, tipping point)

  • 성능이 저하되기 전의 최대 처리량
  • 시스템이 감당할 수 있는 성능의 한계 지점

버클존은 포화점을 지나 성능이 꺾이기 시작하는 구간을 의미한다.

 

  • 포화점 > 목표 성능 : 만족스러운 성능 테스트
  • 포화점 <= 목표 성능 : 병목 지점을 찾아 제거 필요

 

일반적으로 웹 서버의 병목 지점은 호출 비중이 높으면서도 응답 시간이 긴 기능과 관련되어 있다.

응답 시간에 영향을 주는 요인은 다음과 같다.

  • DB 연동(쿼리 실행 시간)
  • 외부 연동 시간
  • 트래픽 대비 부족한 커넥션 풀 크기

어떤 지점에서 병목이 발생하는지 확인한 뒤 서버 확장, 캐시 적용, 비동기 연동과 같은 수단을 강구해서 응답 시간을 줄이려 하면 줄어든 응답 시간만큼 포화점을 높일 수 있을 것이다.

 

3. 주요 측정 지표

성능 테스트 시 주로 측정하는 지표에 대한 설명이다.

 

응답 시간

성능 테스트에서 응답 시간은 중요한 지표이다. 응답 시간은 다음과 같이 여러 값을 측정한다.

  • 평균
  • 최대
  • 최소
  • 중앙
  • 99%나 95% 백분위

 

  • 응답 시간의 평균과 최대값의 차
    • 이 차이값이 크다면 99%나 95% 백분위 값을 함께 확인해야 한다.
    • 이 백분위 값이 최대 응답 시간보다 평균 값에 가깝다면 최대 값은 이상치일 수 있다.

 

  • 응답시간의 중앙값과 평균값의 차이
    • 응답 시간이 중앙값보다 평균값이 더 큰 좌편향 분포를 보인다면 이는 평균값보다 느린 응답시간이 더 많이 분포해있다는 것을 의미한다.

 

위는 응답시간 중앙값이 응답시간 평균값보다 큰 우편향 그래프이다

 

처리량

처리량은 TPS(Transaction Per Second, 초당 트랜잭션 건수)처럼 초 단위로 얼마나 많은 요청을 처리했는지를 나타낸다. 테스트를 진행하는 동안 처리량은 변화하므로 최대, 평균, 최소 값을 함께 구한다.

 

에러율

에러율은 전체 요청 중에서 에러가 발생한 비율을 의미한다. 부하 테스트를 하다 보면 처리량은 높은데 에러도 함께 증가하는 상황이 발생한다. 에러가 발생한다는 건 시스템이 부하를 감당하지 못하고 있다는 신호일 수 있다. 에러가 증가하기 시작하는 지점이 시스템의 한계일 가능성이 높다.

 

CPU 사용률

부하 테스트 중에는 대상 시스템의 CPU 사용률도 함께 모니터링해야 한다. 일반적으로 웹 서버의 성능 문제는 DB외부 연동에서 발생하지만 높은 CPU 사용률로 인해 문제가 생기는 경우도 있다. CPU 사용률을 측정하면 문제 원인을 분석할 때 범위를 좁히는 데 도움이 된다.

 

4. 성능 테스트 설계 시 고려 사항

성능 테스트를 설계할 때는 다음 사항들을 고려해야 한다.

  • 시스템 트래픽 패턴
  • 사용자규모(동시 요청자 수, 트래픽 규모)
  • 기능별 트래픽 비율
  • 데이터 크기
  • 워밍업
  • 적절한 목표치 설정

 

시스템 트래픽 패턴

시스템은 보통 일정한 트래픽 패턴을 가진다. 콜센터 업무 시스템은 업무 시작 시간부터 종료 시간까지 비교적 고른 트래픽 패턴을 보이는 반면, 학원 관련 서비스는 주중 오후 시간대에 트래픽이 급증하는 패턴을 보인다. 이처럼 서비스의 특성에 따른 트래픽 상황을 가정해 성능 테스트 진행이 필요하다. 만약 트래픽이 짧은 시간에 증가하는 패턴을 보인다면 그에 맞춰 성능 테스트도 짧은 시간 간격으로 부하를 늘리는 방식으로 설계하는 것처럼 말이다.

 

사용자 규모

50명이 사용하는 내부 시스템과 1천만이 사용하는 온라인 서비스는 처리해야 하는 트래픽 규모가 다르다. 트래픽 규모가 작으면 한 대의 부하 발생기로도 충분하지만 트래픽 규모가 큰 서비스는 여러 대의 부하 발생기를 사용해야 할 수 있다.

 

또한 부하에 사용할 사용자 수도 중요하다. 예를 들어 한 사용자의 인증 토큰을 사용해서 모든 요청을 생성한다면 DB의 캐싱을 통해 시스템은 실제보다 더 좋은 성능을 낼 수 있기 때문에 정확한 테스트가 어려울 수 있다. 따라서 사용자에 따라 조회하는 데이터가 다르다면 목표로 하는 동시 사용자 수에 맞춰 요청을 발생시킬 수 있도록 테스트를 설계해야 한다.

 

기능별 트래픽 비율

자주 불리는 API 목록을 추리고 최대한 실제 호출되는 비율에 맞게 부하가 발생하도록 테스트를 설계한다. 실제 불리는 비율을 고려하지 않고 1개 API에 대해서만 부하를 발생시키면 캐시 효과와 같은 이유로 결과가 실제보다 잘 나올 수 있다.

 

데이터 크기

데이터 크기도 고려해야한다. 실제 상황과 유사한 데이터 양으로 테스트를 하는 것이 중요하다. 데이터가 100만 건이 예상되는 서비스에 대해 부하 테스트를 하는데 DB에 데이터를 50건만 넣으면 의미가 없다. 왜냐하면 데이터 규모가 작으면 성능이 잘 나오고 실제 상황에 적용했을 때는 더 많은 데이터 때문에 문제가 발생할 수 있다. 반대로 데이터가 많아야 1년에 2천 개밖에 생성되지 않는 기능에 대해 스트레스 테스트 목적으로 50만 개의 데이터를 만들면 안 된다는 뜻이기도 하다. 예상되는 규모에 맞게 테스트 데이터를 만들어야 실제에 근접한 성능 테스트 결과를 얻을 수 있다.

 

워밍업

테스트를 진행하기에 앞서 레디스를 캐시로 사용하는 경우 캐시를 어느정도 채우는 준비과정이 필요하다. 만약 캐시를 비운 상태에서 진행해야하는 테스트가 아닌 이상 실제 서비스에서는 캐시가 어느정도 채워진 상태라 가정할 경우엔 그 상황에 맞춰 미리 세팅을 해둬야 올바른 테스트 결과를 얻을 수 있다.

 

부하 테스트 시 점진적으로 트래픽을 늘려서 워밍업을 하기도 한다. 예를 들어 첫 30초 동안은 20명의 동시 사용자로 부하를 발생시키고 이후 15초마다 동시 사용자를 20명씩 늘리는 식으로 시스템에 가해진느 부하를 조금씩 증가시키는 방법이 있다. 이는 시스템이 안정화된 상태에서 본격적인 부하 테스트를 진행할 수 있도록 한다.

 

적절한 목표치

실제 예상 되는 사용자 수와 요청 건수를 감안해서 성능 목표치를 설정하자. 

 

5. 성능 테스트 도구

부하 테스트 도구로 nGrinder와 k6가 있다.

 

nGrinder

nGrinder는 네이버에서 개발한 부하 테스트 도구로 네이버에서 검증된 기술로 grinder를 기반의 더 편리한 버전이라고 할 수 있다.

nGrinder는 Groovy나 Jython을 이용해서 테스트용 스크립트를 작성한다.

 

nGrinder는 1개의 컨트롤러와 다수의 에이전트로 구성되어 있다.

  • 컨트롤러
    • 웹 UI를 제공하고 있어 사용이 쉽다는 이점이 있다. 
  • 에이전트
    • 실제로 부하를 발생시킴
    • 테스트 대상 서버의 시스템 지표(CPU와 메모리)를 모니터링
    • 2개 이상의 에이전트를 사용할 수 있기 때문에 여러 장비를 활용해서 대량의 부하를 발생시킬 수 있다.

 

k6

k6는 Grafana로 유명한 Grafana Labs에서 개발한 부하 테스트 도구이다. 비교적 최근에 나온 도구로 설치가 쉽고, 고 언어로 개발됐지만 테스트 스크립트는 자바 스크립트를 이용해 작성한다.

 

k6는 고루틴을 사용해서 부하를 발생시키기 때문에 스레드를 사용하는 도구 대비 더 적은 자원으로 더 많은 부하를 발생할 수 있다. 동시에 여러 장비에서 부하를 발생시키고 싶다면 유료 버전인 k6 클라우드를 사용하면 된다. 쿠버네티스 클러스터가 있다면 k6 Operator를 사용해서 분산 환경에서 부하를 발생할 수 있다.

 

k6는 CLI로 실행한다. 그래서 CI/CD 환경에 통합이 용이하다. 부하 테스트 결과도 콘솔에 출력한다. Prometheus나 InfluxDB 같은 곳에 결과를 저장해서 실시간 테스트 상황을 모니터링할 수 있다. 또한 별도의 리포트 플러그인을 사용해서 HTML과 같은 형식으로 생성할 수도 있다.

 

그 외의 부하 테스트 도구로는 

  • Locust
    • 파이썬 코드를 사용해서 테스트를 정의하며 명령행과 웹기반 UI로 테스트를 실행할 수 있다. 분산 환경에서 부하를 발생하는 기능을 제공하며 클라우드 버전도 제공한다.
  • Gatling
    • 자바, 스칼라, 코틀린, 자바스크립트를 이용해서 테스트 스크립트를 작성한다. 웹 요청 외에 AMQP나 카프카 등 다양한 프로토콜을 지원한다. 엔터프라이즈 버전을 사용하면 분산 환경에서 부하를 발생할 수 있다.
  • JMeter
    • 오랜 기간 명맥을 유지하고 있는 부하 테스트 도구로 GUI 환경과 CLI 환경을 지원한다. 웹 요청 외에 FTP, DB, TCP 등 다양한 어플리케이션과 프로토콜에 대한 테스트를 지원한다. 분산 환경에서 부하를 발생할 수 있다.

 

각자 상황에 맞추어 테스트 도구를 선택하고, 자바를 포함한 JVM 환경에 익숙하다면 nGrinder나 Gatling을, 자바스크립트가 익숙하다면 k6를 시도해보자.

 

6. 성능 테스트 실행 시 주의 사항

 

동일 서버에서 부하기와 테스트 대상 시스템 동시 실행

성능 테스트를 진행할 때 흔히 하는 실수 중 하나가 테스트 대상 시스템과 부하기를 한 장비에서 실행하는 것이다.

 

위처럼 부하기와 테스트 대상 시스템을 한 곳에서 실행하면 안된다. 왜냐하면 부하 생성은 그 자체로 많은 자원을 사용하는데, 테스트 대상 시스템과 부하기를 한 장비에서 실행하면 테스트 대상 시스템이 자원을 온전히 활용하지 못해 실제 성능보다 낮은 결과가 나온다.

=> 성능 테스트를 진행할 때는 반드시 부하 발생기와 테스트 대상 시스템을 분리해야 한다. 또 부하를 발생할 장비의 성능도 신경 써야 한다.

 

서버 설정 제한

초당 요청 개수나 스레드 풀 개수, DB 커넥션 풀 크기 설정 등 서버 설정에 제한을 걸고 부하 테스트를 실행하는 것도 자주 하는 실수다.

 

예를 들어 Nginx를 사용하는데 DDoS 공격을 막기 위해 limit_req_zone 설정을 사용해서 IP당 초당 요청 개수를 10개로 제한했다고 하자. 부하기는 1대 장비에서 다량의 요청을 발생하므로 초당 10개 제한에 걸리게 된다. 이러면 많은 요청에 대해 오류 응답이 발생하므로 제대로 된 부하 테스트를 할 수 없다. 

 

비슷하게 서버의 스레드 풀 개수나 DB 커넥션 풀의 크기가 작으면 부하 테스트가 제대로 이루어지지 않으니 테스트할 부하 규모에 맞게 풀의 크기를 미리 설정해야 한다.

 

운영 시스템과 동일한 네트워크 환경에서 테스트

스트레스 테스트처럼 대량의 요청을 발생시킬 때는 테스트 대상 시스템에 많은 네트워크 트래픽이 발생한다. 실 운영 시스템과 테스트 대상 시스템을 동일 네트워크에 넣고 테스트를 실행하면 테스트가 발생시키는 트래픽이 실 운영 환경에 영향을 줄 수 있다. 

 

실제 외부 서비스 사용

외부 서비스를 연동하는 기능을 테스트할 때는 실제 외부 서비스를 사용하지 않게 주의해야 한다. 테스트하고 싶은 대상은 우리 시스템이지 외부 시스템이 아니기 때문이다. 외부 시스템 연동을 그대로 둔 채로 부하 테스트를 진행하면 외부 시스템이 트래픽을 견디지 못하고 장애가 발생할 수 있다. 만약 외부 서비스 연동이 포함된 기능에 대해 부하 테스트를 진행해야 한다면 실제 외부 서비스 대신에 가짜 외부 서비스로 대체해야 한다.

 

실제 운영환경과 다른 테스트 대상 시스템 환경

테스트 대상 시스템은 최대한 실제 운영 환경과 동일하게 구성해야 한다. 간혹 실제 운영 환경 대비 저사양 환경을 사용해서 테스트 대상을 구성할 때가 있다. 예시로 실제 운영 서버는 8코어 CPU 16GB 메모리를 사용하는데 ㅔ테스트 환경은 2코어 2GB 메모리를 사용하는 식이다. 이렇게 되면 실제 환경에서 얼마나 성능을 낼 수 있는지 확인 할 수 없다. 따라서 최대한 실 환경에 맞춰 테스트를 실행해야 유효한 성능 지표를 구할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

1. MVC 패턴

MVC는 Model-View-Controller의 약자로, model, view, controller로 이루어진 패턴을 말한다. 이 패턴은 자바의 스프링 프레임워크, Node.js의 Exprdss.js에서 대표적으로 사용하는 패턴이다.

 

Controller

컨트롤러는 사용자의 입력 처리와 흐름 제어를 담당하고 사용자의 요청을 알맞게 해석한 뒤, 모델에 비즈니스 로직 실행을 위임한다.

컨트롤러에서는 사용자 입력값 유효성 검증, 쿼리 문자열을 알맞은 데이터 모델로 변환한다. 또한 비즈니스 로직에 포함되지 않는 사용자 인증과 같은 기능을 담당하기도 한다. 컨트롤러만 모델과 뷰에 의존해 컨트롤러 상관없이 모델과 뷰를 변경할 수 있어 유지보수에 용이하다.

 

Model

모델은 사용자가 요청한 기능을 실행한 후 처리 결과를 컨트롤러에 리턴한다. 모델은 회원가입, 암호 변경 등 비즈니스와 관련된 로직만 처리한다. 사용자에게 제공할 화면(HTML 등)이나 UI 흐름 제어에 대한 처리는 하지 않는다. 모델과 뷰는 분리되어 있기에 서로의 영향을 덜 받는다.

 

View

컨트롤러는 모델의 처리 결과를 기준으로 사용자에게 보여줄 뷰를 선택한 후 뷰는 사용자에게 결과 화면을 보여준다.

API를 구현한 컨트롤러는 JSON 응답을 생성하는 뷰를 선택하고,

웹 페이지를 구현한 컨트롤러는 HTML 결과를 응답하는 뷰를 선택한다.

뷰는 사용자에게 알맞은 응답을 제공하는 역할만 하고 로직이나 흐름 제어는 하지 않는다.

 

2. 계층형 아키텍처(Layered Architecture)

계층형 아키텍처는 각 계층마다 특정 역할을 수행하고, 하위에 위치한 계층에만 의존하는 특징을 가진 구조이다. 오래된 패턴으로 많은 곳에서 사용된다.

계층형 아키텍처에서 하위 계층은 상위 계층에 대한 의존을 갖지 않는다. 오직 상위 계층에서 하위 계층으로의 의존만 허용한다. 위 그림에서 계층 1은 계층2에 의존하지만, 반대로 계층2는 계층1에 의존하지 않는다.

 

웹 애플리케이션을 계층형 아키텍처로 구현할 때는 일반적으로 4개 계층으로 구성한다.

 

  • 표현(UI) 계층 : 사용자와의 상호작용 담당, MVC 패턴의 컨트롤러, 뷰 역할
  • 응용 계층 :사용자 요청을 실제 처리 하는 계층이고, MVC 패턴의 서비스 역할이다. 모델 인프라 계층 결과를 표현 계층에 리턴한다.
  • 도메인(모델) : 도메인 로직을 구현하는 역할이다. 주문 모델의 취소 제약조건, 상태 변경 같은 로직이 포함된다.
  • 인프라(영속) : DAO처럼 DB 연동, 문자 발송 같은 구현 기술을 지원한다.

 

장점

  • 구조가 단순하고 규칙이 명확해 코드 실행 흐름을 추적하기 쉽다

 

3. DDD(Domain Driven Design)와 전술 패턴

로직이 복잡한 도메인을 구현할 때는 DDD에 소개된 패턴 사용을 검토해보자. DDD에서 소개하는 전술패턴을 사용하면 도메인 영역에 도메인 로직을 집중시키는 데 도움이 된다.

 

DDD에서 도메인 모델 구성요소

엔티티(Entity) 각 엔티티 객체는 고유의 식별자를 가지며, 각 엔티티는 식별자로 구분된다. 내부 상태가 바뀌어도 식별자는 바뀌지 않는다. 예를 들어 각 주문 엔티티는 서로 다른 주문번호를 식별자로 갖는다.
밸류(Value) 밸류는 고유의 식별자를 갖지 않으며 개념적인 값을 표현한다. 금액, 배송 주소 같은 값이 밸류가 된다.
값은 불변으로 구현하는 것을 추천한다.
애그리거트(Aggregate) 애그리거트는 관련된 객체를 묶어 하나의 개념적인 단위를 표현한다.
예를 들어 주문 애그리거트는 Order 엔티티, OrderLine 밸류 집합, ShippingAddress 밸류로 구성될 수 있다. 애그리거트는 모델의 일관성을 관리하는 단위가 된다.
리포지토리(Repository) 리포지토리는 도메인 객체를 물리적인 저장소와 연결할 때 사용하는 모델이다. 리포지토리는 도메인 객체를 저장하고 조회할 때 사용되는 인터페이스를 제공한다. 리포지토리는 애그리거트 단위로 존재한다.
도메인 서비스
(DomainService)
특정한 애그리거트에 속하지 않은 로직을 구현한다. 외부 연동이 필요한 도메인 로직도 도메인 서비스로 사용해서 표현한다.
도메인 이벤트
(Domain Event)
도메인 내에서 발생한 이벤트를 표현한다. 도메인의 상태가 변경될 때 도메인 이벤트가 발생한다. 도메인 이벤트는 주로 다른 부분에 변화를 알리기 위해 사용된다.

DDD는 도메인 로직을 애그리거트 단위로 묶는다. 그 이점은 다음과 같다.

  • 복잡한 모델을 애그리거트 단위로 관리할 수 있게 함으로써 복잡도를 낮추고
  • 애그리거트에 관련 로직을 모아 응집도를 높이고
  • 복잡한 도메인의 유지보수성을 높여준다.

 

4. 마이크로서비스 아키텍처

마이크로서비스 아키텍처는 서비스를 더 작은 단위로 분리하고 각 서비스가 연동되는 구조를 갖는다.

 

모놀리식과 마이크로서비스와의 장단점은 다음과 같다.

  모놀리식 마이크로서비스
장점 - 배포가 단순하다.
- 코드 관리가 더 쉽다.
- 성능을 높이기 위해 복잡한 구조를 가질 필요가 없다.
- 테스트와 디버깅이 쉽다.
- 독립적인 배포와 지속적인 배포가 용이하다.
- 성능 확장에 용이하다.
- 기술에 대한 유연성을 가질 수 있다.
- (보통) 개발자의 만족도가 더 높다.
단점 - 규모가 커질수록 개발 속도가 느려질 수 있다.
- 한 기능의 문제가 전체에 영향을 줄 수 있다.
- 구현 기술 변경에 어려움이 있다.
- 작은 변경도 전체를 다시 배포해야 한다.
- 테스트와 디버깅이 어려울 수 있다.
- 모놀리식 대비 인프라가 복잡해진다.
- 소통에 따른 부하가 증가할 수 있다.
- 무분별하게 서비스를 만들면 분산 모놀리식이 될 수 있다.

 

마이크로서비스 핵심 개념

  • 독립적인 배포
    • 다른 마이크로서비스를 배포하지 않고도 마이크로서비스 변경/배포/출시가 가능해야 한다. 그러기 위해선 마이크로서비스 간 결합도를 최대한 낮춰야 한다.
  • 도메인 중심으로 모델링
    • 각 마이크로서비스는 도메인을 기준으로 구분해야 한다. 한 도메인의 기능 구현이 여러 마이크로서비스에 걸쳐 있으면 출시 비용이 증가
  • 자신의 상태를 가짐
    • 마이크로서비스는 DB를 공유하지 않는다. 다른 마이크로서비스의 데이터를 사용할 경우 DB에 직접 접근하지 않고 API 등을 통해 접근한다.
  • 크기
    • 크기에 기준은 없고, 조직이 감당할 수 있는 수준과 마이크로서비스 경계 정의가 필요
  • 유연함
  • 아키텍처와 조직을 맞춤

 

4. 이벤트 기반 아키텍처

이벤트 기반 아키텍처는 두 시스템 간에 통신할 때 이벤트를 사용하는 구조를 의미한다. 이벤트는 '주문함', '인증에 실패함' 같은 과거에 발생한 사실을 의미한다.

 

이벤트 기반 아키텍처의 3가지 구성요소는 다음과 같다.

  • 이벤트 생산자
  • 이벤트 소비자
  • 이벤트 브로커(또는 라우터)

  • 이벤트 생산자가 이벤트를 생성해 브로커에게 전달
  • 브로커는 해당 이벤트에 관심있는 소비자에게 이벤트를 전달
  • 이벤트 소비자는 이벤트를 받아 적절하게 반응한다.

 

이벤트는 변경된 데이터를 다른 시스템에 전달할 때 주로 사용된다. 예시로 주문 시스템에서 '결제 완료' 이벤트 발생 시 이벤트가 배송 시스템으로 전달되고, 배송 시스템은 전달받은 주문 정보를 바탕으로 배송을 시작한다.

 

알림 목적에도 사용할 수 있다.

잘못된 암호 반복 입력으로 로그인에 실패 ->  인증 시스템은 '인증 실패' 이벤트 발생 -> 이상 감지 시스템에서 비정상 접근 여부 판단

 

5. CQRS(Command Query Responsibility Segregation) 패턴

CQRS는 명령을 위한 모델과 조회를 위한 모델을 분리하는 패턴이다. 여기서 명령은 시스템의 상태를 변경하는 것을, 조회는 상태를 조회하는 것을 의미한다.

 

  • 장점
    • 각 기능에 맞게 모델을 구현해 모델 간 영향 도를 줄일 수 있다.
    • 캐시를 적용하거나 조회 전용 DB를 확장함으로써 조회 모델 향상에도 용이하다.
  • 단점
    • 작업 코드가 증가한다. 추가 코드 대비 얻는 이점이 큰지 비교가 필요하다
    • 구현 기술이 증가한다. 조회 전용 DB가 필요하고 서로 다른 DB 간의 데이터 동기화를 위해 추가적인 메시징 수단이 필요하다

 

 

 

 

+ Recent posts