Sep 2, 2019 - CQRS

CQRS는 Command and Query Responsibility Segregation(명령과 조회의 책임 분리)을 나타냅니다. 커맨드 ( Create - Insert, Update, Delete : 데이터를 변경) 와 쿼리 ( Select - Read : 데이터를 조회)의 책임을 분리한다는 것을 뜻합니다. CQRS는 네이밍에서 알 수 있듯이 명령과 쿼리의 역할을 구분 한다는 겁니다.

너무 단순하다고 생각될지 모르겠지만 이것이 전부입니다. 어쩌면 CQRS에 대한 오해는 CQRS가 생각보다 복잡하지 않기 때문일지도 모릅니다. 이 단순한 규칙이 몇 가지 응용기술과 조합되어 시스템에 적용되면 그 모습은 무척이나 다양합니다. 그만큼 CQRS를 설명하는 정보들이 표현하는 구현체의 모습이 제각각이고 여기서 혼란이 시작될 가능성이 있습니다.

Martin Fowler 형님께서 이미 2011년도에 이야기 하셨던, 등장한지는 조금 오래된 패턴입니다. Martin Fowler는 스택 자료구조의 pop() 연산을 예로 들었습니다. 참고주소 (참고로 버란트 마이어(Bertrand Meyer) 의 CQS가 CQRS의 출발 이었고, CQRS를 처음 소개한 이는 Greg Young 이라고 합니다.)

사업이 점점 번창하게 된다면, 전통적인 CRUD 아키텍처 기반에서 Application을 개발 및 운영하는 개발자들에게는 자연스레 Domain Model의 복잡도가 증가될 겁니다. 그리고 그로 인하여 히스토리를 간직해야할 유지보수 Cost는 지속적으로 증가하게 되며 Domain Model은 점점 설계 시 의도한 방향에서 벗어나게 될 겁니다. 모든 연산이 명령과 조회로 쉽게 양분되지는 않겠지요.

개념적으로 어려운 경우도 있고 동시성 등 기술적인 문제도 있습니다.

이런 일련의 변경사항과 흐름을 곰곰히 관찰해 보며, 단순 검색 및 조회만 하면되는 데이터를, 비즈니스 로직이 거대해지면서 CUD에 의해 변경되는 도메인모델들이 의미없이 늘어나며, 그 모델들을 조인해서 가져와야하는 단순 검색결과들 또한 거대해지게 됩니다.

그리고 그 해답으로 나온 것이 CQRS 입니다. 바로 명령을 처리하는 책임과 조회를 처리하는 책임을 분리 구현 하자는 취지가 바로 이것입니다. CQRS에서 명령은 시스템의 상태를 변경하는 작업을 의미하며 조회는 시스템의 상태를 반환하는 작업을 의미합니다. 정리하면, CQRS는 시스템의 상태를 변경하는 작업과 시스템의 상태를 반환하는 작업의 책임을 분리하는 것입니다.

전통적으로 사용하는 CRUD 모델의 경우 데이터를 갱신하기 위해서는 데이터 저장소에서 해당 데이터를 가져오는 작업이 필요합니다. 동시성 문제가 나타날수도 있고, 확장성을 낮추는 문제점을 지닌 지점이 되기 쉽습니다.

CQRS 의 경우 어떻게 보면 일련의 이벤트를 통해 데이터를 조작하는 접근방식이 될 수 있겠습니다. 데이터에 영향을 주는 모든 동작을 이벤트라는 저수준의 데이터로 관리하는 것으로 여러 문제를 해결할 수 있습니다.

Testing Your Message-Driven Application by Jakub Pilimon @ Spring I/O 2018

서울에서 SPRING ONE 세미나에 참석해서 집적 들어봤습니다. 그때는 우리 솔류션에 적용하기 힘들 것같다고 생각했는데, 어느순간 적용가능한 시점이 다가온거 같네요.

계속 반복해서 이야기하지만, 이름처럼 CQRS는 시스템에서 명령을 처리하는 책임과 조회를 처리하는 책임을 분리하는 것이 CQRS의 핵심입니다.

CQRS를 설명할 때 명령 처리기 패턴(Command Processor Pattern)을 얘기하기도 하고 다른 경우는 다계층 아키텍처(Multitier Architecture)나 이벤트 소싱(Event Sourcing)을 다룹니다. 이것들 모두와 DDD(Domain-Driven Design)를 조합하기도 합니다.

CQRS를 처음으로 소개한 Greg Young은 CQRS는 아주 단순한 패턴(“CQRS is a very simple pattern”)이라고 말했습니다. 경우에 따라 이미 실천하고 있을지도 모릅니다.

Aug 27, 2019 - IDE 별 프로퍼티 인코딩에 따른 설정

보통의 회사라면, 같은 IDE 툴을 사용하도록 어느정도 강제하거나 가이드라인을 정하지만,
본인이 편한대로 일하는 우리 회사는,

인텔리J 를 쓰는 사람과 이클립스를 쓰는 사람이 혼용되어있습니다.

이때 가장 골치아픈 2가지가, 소스 디버거 해줄때, 단축키를 잘… 모르겠네요.

이클립스를 쓰다가 인텔리J 로 오면서 인텔리J 단축키를 외우게 되며, 이클립스 단축키를 잊어버리고 만 겁니다…. 그리고 다른 하나는 툴이 다름으로 오는 문제인데요.

저같은 경우 프로퍼티 문제가 있었습니다.

인텔리J에서 제 프로퍼티는 자동으로 유니코드들을 소문자로 변환해주는데, 이클립스는 그렇게 하지 않더군요.

그래서 이클립스의 경우

Properties Editor

를 설치해서 강제로 소문자로 변환하는 추가 작업을 해줘야합니다.

PS. 저는 여지껏 인텔리J에서 소문자를 자동으로 변환해주는 줄 알았는데,

<IDE_HOME>\bin\idea.properties

경로의 idea.properties 프로퍼티에

idea.native2ascii.lowercase=true

이값을 추가해야한다고 하네요. (왜 여지껏 소문자로 잘 변환되고 있었는지는 의문입니다.)

아마 자동으로 앞글자가 대문자로 변환하는 이슈가 아니라서 그런게 아닌가,

intellij에서 properties파일 name명 자동으로 앞글자 대문자로 변경되는 문제

[MAC] application>intellij 패키지보기>bin>idea.properties
[WIN] C:\Program Files (x86)\JetBrains\IntelliJ IDEA 최신버젼\bin\idea.properties

에서 idea.native2ascii.lowercase=true 추가

Aug 16, 2019 - gitignore 와 git commit 제외

한 번도 커밋 되지 않은 파일은 .gitignore 를 사용하면 변경 사항을 무시 할 수 있습니다.

하지만 커밋 된 적이 있는 파일은 .gitignore 에 등록 해도 변경 사항을 트래킹하여, gitignore에 등록되더라도 계속 커밋되는 현상이 생기게 됩니다. git status 사용시에 변경되는 파일 목록을 볼수있습니다.

임의의 파일 datasource.properties 라는 파일을 gitignore에 등록을 했는데, 트래킹되면서 커밋이 발생할 수 있습니다.

인텔리J의 경우는 커밋하지 않을 파일들을, Move Files to Another Changelist… 를 이용해서 별도의 파일을 관리할 수 있습니다. 그러나, 타툴을 사용하시는 분들의 경우 (이클립스, 소스트리 등등)에는 해당 기능이 없어 git 순수한 명령어를 통해 커밋을 제외할 수 있습니다. 그렇기 때문에 기본적인 git 명령어를 통해 커밋 된 파일의 수정 사항 무시하는 방법은 다음과 같습니다.

특정 파일의 수정사항 무시

git update-index --assume-unchanged [file path]

보통의 git이 설치된 분들이라면 git이 기본적으로 환경설정되어있을 터이니, 설정되어있을겁니다.

{경로}\src\main\resources>git update-index --assume-unchanged ./datasource.properties

처럼 특정파일(위의 예제는 datasource.properties) 와같이 위와같은 형태로 등록하시면, 커밋목록에서 삭제됩니다.

특정 파일의 수정사항 무시 취소

git update-index --no-assume-unchanged [file path]

추가로 해당 기능을 제외하고자 하면 위와같이 사용하시면됩니다. 이클립스의 경우, 우측버튼을 눌러 메뉴를 사용할 수 있으며, 인텔리J의 경우, Move to Another Changelist 를 통해 특정파일들을 별도의 그룹으로 하여 관리할 수 있습니다.

임시로 사용할 때는 좋지만 현재 unchanged로 지정된 파일의 내역을 보는 명령어는 없으므로 너무 장기간 사용해서 –assume-unchanged로 지정된 것을 잊어먹으로 오히려 혼란을 초래할 수도 있어 보입니다. 이럴 경우에는 git update-index –really-refresh 를 사용하면 앞에서 –assume-unchanged로 지정한 내용을 무시하고 워킹트리에 대한 인덱스를 새로 갱신합니다.

위 방법을 사용하는 것은 로컬의 계정이 다 틀리기 때문에 발생하는 이슈입니다.

로컬 설정값이 실수로 올라가게 되는 경우를 방지하기 위한 목적이므로, 해당 방법이 좋아보입니다.

git ignore Plugins

  1. 인텔리J의 플러그인 설치
Settings > Plugins > Browse repositories…

에서 ‘.ignore’ 검색 후 install 실행 후 재시작하면, 제외할 파일을 우측메뉴에서 하나씩하나씩 추가할 수 있습니다. 회색음영으로 변경되며 커밋리스트에 나타나지 않는다.

  1. 이클립스의 메뉴 이클립스 메뉴를 통해서도 설정가능합니다.
    이클립스의 경우, assume 자체를 메뉴 명령어를 통해 등록하고 해지할 수 있는 것으로 확인됩니다.
    Assume 등록할 경우, 해당 파일은 체크 이미지가 붙게 되며, 마우스 우측 버튼을 통해 해지할 수 있습니다.
    Team > Advanced > Assume Unchanged
    

반대의 경우에는

Team > Advanced > No Assume Unchanged

으로 해지하면됩니다.