Skip to content
Beside the Wheel
Search
Ctrl
K
Cancel
Email
GitHub
Select theme
Dark
Light
Auto
공부
(5)
spot 인스턴스에서 서버 가용성 개선하기
eBPF로 서버 성능 Profiling하는 법: Pyroscope의 구현 살펴보기
정수론부터 RSA까지
strace로 shaka-packager 버그 추적
Kubernetes The Hard Way
TIL
(956)
AI
(43)
DevOps
(230)
Network
(61)
OS
(155)
개발
(113)
데이터베이스
(64)
서버
(72)
수학
(20)
알고리즘
(24)
암호학
(32)
언어
(113)
컴퓨터구조
(5)
코드
(24)
독후감
(43)
과학
(1)
사회
(2)
산문
(3)
소설
(12)
인문
(11)
자기계발
(7)
철학
(7)
생각
(6)
고민
변화에 대하여
의식의 영역에 대하여
본질을 보려면
짧은 생각들
소유냐 존재냐
회고
(14)
2022.03-04 대덕소마고 입학소감/다짐
2022.05-08 프로젝트와 인간관계
2022.09-2023.02 불안과 판단
2023.03-07 DMS 리더 회고
2023.08-11 나는 누구인가?
2023.12 더 많은 걸 배우기 위한 경험
2024.01-02 회사 인턴 회고
2024.03-04 고3 근황
2024.05-07 고등학교 마무리
2024.08-12 첫 회사
2025.01-03 입출력
2025.03-08 효능감이란 무엇일까
2025.09-12 연말회고
2026.01-08 담론
Email
GitHub
Select theme
Dark
Light
Auto
태그: 아키텍처-및-방법론
총 54개의 글이 있습니다.
DRY
아키텍처-및-방법론
2026. 7. 31.
DRY(Don't Repeat Yourself)는 "같은 지식을 코드 여러 곳에 중복해서 두지 말라"는 원칙이다. 하나의 사실이 여러 곳에 흩어져 있으면, 바뀔 때 전부 찾아 고쳐야 하고 그중 하나라도 빠뜨리면 버그가 된다. 여기서 말하는 중복은 코드 모양이 같은 것이 아니라 지식이 같은 것을 뜻한다. 우연히 비슷하게 생겼을 뿐 서로 다른 이유로 존재하는 코드를 억지로 합치면, 한쪽 요구사항이 바뀔 때 함께 묶인 다른 쪽까지 영향을 받아 오히려 더 나빠진다. 그래서 DRY를 성급하게 적용하는 것은 위험하다. 아직 중복이라 확신할 수 없을 때는 YAGNI를 따라 그냥 두고, 실제로 같은 지식이 반복해서 나타난 뒤에 묶는 편이 정확하다. --- 참고
KISS
아키텍처-및-방법론
2026. 7. 31.
KISS(Keep It Simple, Stupid)는 "가능한 한 단순하게 만들라"는 원칙이다. 복잡한 설계는 그 자체로 이해·수정·디버깅 비용을 늘리기 때문에, 문제를 푸는 데 꼭 필요한 만큼만 복잡해야 한다는 것이다. 단순함은 코드가 짧다는 뜻이 아니라, 읽는 사람이 동작을 예측하기 쉽다는 뜻이다. 과한 추상화, 불필요한 계층, 영리하지만 이해하기 어려운 표현은 모두 복잡성을 키운다. 똑같이 동작하는 두 방법이 있다면 더 단순한 쪽을 고른다. 지금 필요하지 않은 것을 미리 만들지 않는 YAGNI와 방향이 같다. YAGNI가 시간축에서의 단순함이라면, KISS는 구조 자체의 단순함에 가깝다. --- 참고
YAGNI
아키텍처-및-방법론
2026. 7. 31.
YAGNI(You Aren't Gonna Need It)는 "지금 당장 필요하지 않은 기능은 미리 만들지 말라"는 원칙이다. 익스트림 프로그래밍(XP)에서 나온 말로, 나중에 쓸 것 같다는 추측만으로 코드를 미리 작성하는 것을 경계한다. 미래에 필요할 것 같다는 판단은 대부분 빗나간다. 막상 그 시점이 오면 요구사항이 달라져 있거나, 애초에 그 기능이 필요 없어지는 경우가 많다. 그런데 추측으로 만들어둔 코드는 그때까지 계속 유지보수 대상으로 남는다. --- 참고
3의 법칙
아키텍처-및-방법론
2026. 7. 31.
3의 법칙(Rule of Three)은 "같은 코드가 세 번째로 나타났을 때 비로소 공통 컴포넌트로 추출하라"는 재사용 경험칙이다. 두 번까지는 중복을 참고, 세 번째에 묶으라는 것이다. 성급하게 재사용 가능한 추상화를 만들면 잘못된 추상화가 되기 쉽다. 사례가 하나나 둘밖에 없으면 그 코드들이 정말 같은 이유로 존재하는지, 앞으로 어떻게 달라질지 판단할 근거가 부족하다. 이 상태에서 억지로 공통화하면 우연히 닮았을 뿐인 코드를 하나로 묶게 되고, 나중에 한쪽 요구사항이 갈라질 때 잘못 만든 추상화를 다시 뜯어내야 한다. 세 번째 사례가 등장하면 변형의 축이 드러나서, 무엇이 진짜 공통이고 무엇이 달라지는 부분인지 훨씬 정확하게 가려낼 수 있다. --- 참고
Worse is Better
아키텍처-및-방법론
2026. 7. 31.
"더 나쁜 게 더 낫다(Worse is Better)"는 리처드 가브리엘이 말한 내용이다. 가브리엘은 Lisp 프로그래머였고, 이 글이 실린 원 발표의 제목은 "Lisp: Good News, Bad News, How to Win Big"였다. 기술적으로 명백히 앞서 있다고 믿었던 Lisp와 Lisp 머신이 왜 C와 Unix에 밀려나는에 대해 적은 자기반성에 가까운 내용이다. 구체적인 이야기는 아래와 같다. MIT AI 랩과 스탠퍼드를 중심으로 한 Lisp 문화에는 "올바른 것(the Right Thing)"을 추구하는 태도가 있었다. 시스템은 완전하고 일관되고 정확해야 하며, 그렇게 만들기 위해 구현이 아무리 복잡해져도 감수한다는 것이다. 사용자가 마주하는 인터페이스에서 지저분함을 걷어낼 수 있다면
디미터의 법칙
아키텍처-및-방법론
2026. 7. 31.
디미터의 법칙(Law of Demeter)은 "한 객체는 자신이 직접 아는 대상에게만 말을 걸어야 한다"는 원칙이다. 최소 지식 원칙(Principle of Least Knowledge)이라고도 한다. 어떤 컴포넌트가 다른 컴포넌트의 내부 구현을 속속들이 알고 그 안까지 파고들어 조작하면, 두 컴포넌트가 강하게 결합되어 한쪽 변경이 다른 쪽을 깨뜨리기 때문이다. 구체적으로 한 메서드는 자기 자신, 자신의 필드, 인자로 받은 객체, 자신이 만든 객체 정도에게만 메시지를 보내야 한다. 남에게 받은 객체가 또 물고 있는 내부 객체까지 꺼내 쓰지 말라는 것이다. `a.getB().getC().doSomething()`처럼 점(.)이 길게 이어지는 호출이 전형적인 위반 신호다. 이런 코드는 a가 B의 구조를, 다시
콘웨이의 법칙
아키텍처-및-방법론
2026. 7. 31.
콘웨이의 법칙(Conway's Law)은 "시스템의 구조는 그것을 만든 조직의 의사소통 구조를 닮는다"는 관찰이다. 1967년 멜빈 콘웨이가 제시했으며, 조직이 시스템을 설계할 때 그 설계는 조직 내부의 소통 경로를 그대로 복제하게 된다는 것이다. 이유는 단순하다. 두 모듈이 서로 맞물려 동작하려면 그 모듈을 만드는 사람들이 계속 협의해야 한다. 자주 대화하는 팀끼리 만든 부분은 자연스럽게 긴밀하게 엮이고, 소통이 드문 팀 사이에는 명확한 인터페이스가 생긴다. 그래서 세 팀이 컴파일러를 만들면 3-패스 컴파일러가 나오기 쉽다는 식의 이야기가 따라붙는다. 이 법칙의 실질적 함의는 두 가지다. 하나는 여러 팀이 함께 손대야만 바뀌는 컴포넌트를 만들지 말라는 것이다. 그런 컴포넌트는 팀 경계와 어긋나 있어 변
파레토의 법칙
아키텍처-및-방법론
2026. 7. 31.
파레토의 법칙(Pareto principle)은 "결과의 대부분은 원인의 일부에서 나온다"는 경험칙이다. 흔히 80:20 법칙이라 부르며, 전체 효과의 80%가 원인의 20%에서 비롯된다고 본다. 이탈리아 경제학자 빌프레도 파레토가 "이탈리아 땅의 80%를 인구의 20%가 소유한다"고 관찰한 데서 이름이 붙었다. 이후 여러 분야에서 비슷한 편중이 반복해서 나타나는 것이 확인되면서 일반적인 경향으로 자리 잡았다. 정확히 80과 20이라는 숫자가 중요한 게 아니라, 기여도가 균등하지 않고 소수에 쏠려 있다는 점이 핵심이다. 소프트웨어에서도 자주 인용된다. 성능 최적화에서 실행 시간의 대부분은 코드의 일부 구간에서 소비되므로, 전체를 고르게 손보기보다 병목이 되는 소수 지점을 먼저 측정해 개선하는 편이 효율적
GraphQL
api-아키텍처
2022. 10. 9.
GraphQL은 정확하게 데이터를 요청하는 방법을 설명하는 구문이다. 서로를 참조하는 복잡한 엔티티를 사용하는 애플리케이션의 데이터 모델을 사용하고, 그것을 다양한 방식으로 조회해야 할때 유용하게 사용된다. 최근 GraphQL 생태계는 Apollo, GraphiQL, GraphQL Explorer와 같은 강력한 도구와 라이브러리로 확장되고 있다. GraphQL 동작방식 GraphQL은 GraphQL API에서 만들 수 있는 모든 쿼리와 반환하는 모든 타입에 대해 설명하는 스키마를 정의하는 것으로 시작한다. 스키마 정의 언어(SDL)에서는 엄격한 타입 정의를 사용하기 때문에 스키마 정의가 쉽지 않다. 쿼리 전에 스키마를 통해 쿼리에 대한 유효성 검사를 한 뒤 본 요청이 백엔드 애플리케이션에 도달하면,
REST
api-아키텍처
2022. 10. 9.
REST는 설계적 제약 조건으로 API 스스로에 대한 설명이 가능하여 수 많은 API 소비자에게 채택될 수 있도록 정의된 API 아키텍처 스타일이다. 오늘날 가장 대중적인 REST API 아키텍처 스타일은 2000년 Roy Fielding의 박사 학위 논문에 처음 소개되었다. REST API는 서버 측에서 JSON 및 XML과 같은 간단한 형식의 데이터로 표현 가능하게 한다. REST 동작 방식 REST는 SOAP만큼 엄격하게 정의되어 있지 않다. RESTful한 아키텍처는 6개의 설계 제약 조건을 준수해야 한다. 일관성 있는 인터페이스 : 장비 또는 애플리케이션 타입과 무관하게 목표 서버와 통신하도록 일관성 있는 통신 방법을 허용한다. 무상태 : 요청 자체가 요청을 처리하는 데 필요
RPC
api-아키텍처
2022. 10. 9.
RPC란 원격 프로시저 호출이라는 뜻으로, 다른 컨텍스트에서 함수의 원격 실행을 허용하는 사양이다. RPC는 로컬 프로시저 호출 개념을 확장한 것이지만, HTTP API 컨텍스트에 포함되는 개념이다. 초기 XML-RPC는 XML 페이로드 데이터의 타입을 보장하기 어렵다는 문제를 가지고 있었다. 그래서 차후의 RPC API는 보다 정형화된 JSON-RPC를 사용하여 SOAP보다 단순한 구조를 지닌 SOAP의 대안으로 인식되었다. 그중 gRPC는 2015년 Google에서 개발한 최신 버전의 RPC이며, 로드밸런싱, 추적, 상태 확인, 그리고 인증을 위한 플러그인을 지원하기 때문에 마이크로 서비스 연결에 매우 적합하다. RPC 동작방식 클라이언트는 원격 프로시저를 호출하고 매개 변수와 추가 정
SOAP
api-아키텍처
2022. 10. 9.
SOAP는 XML 형식의 고도로 표준화된 웹 통신 프로토콜이다. XML-RPC 출시 1년 후에 SOAP가 출시되었기 때문에 SOAP는 XML-RPC로부터 상당 부분을 물려받았다. 이후 REST가 출시되었을 때, SOAP와 REST는 같이 사용되었지만, 곧 REST만 사용하는 추세가 시작되었다. SOAP의 동작 방식 SOAP 메시지는 다음과 같이 구성된다. 메시지의 시작과 끝을 표시하는 envelop tag 요청 또는 응답 body 메시지가 특정 사항이나 추가 요구 사항을 결정해야되는지에 대한 정보를 나타내는 헤더 요청을 처리하는 도중 발생할 수 있는 오류에 대한 안내 SOAP API 로직은 웹 서비스 기술 언어(WSDL)로 작성된다. 이 API 기술 언어는 endpoint를 정의하고 실행
CQRS
아키텍처-및-방법론
2022. 10. 9.
CQRS는 Command Query Responsibility Segregation 의 약자로, 단어 그대로 해석하면 "명령 조회 책임 분리"를 뜻한다. 즉, 우리가 보통 이야기하는 CRUD(Create, Read, Update, Delete)에서 CUD(Command)와 R(Query)의 책임을 분리하는 것이다. CQRS가 필요한 이유 Application의 Business 정책이나 제약은 데이터 변경(CUD)에서 처리되고, 데이터 조회(R) 작업은 단순 데이터 조회를 처리하는데, 두가지 작업 모두를 동일 Domain Model로 처리하면 필요하지 않은 Domain 속성들이 생겨 복잡도가 증가한다. 도메인의 여러 속성들이 얽히면 유지보수의 비용이 증가하고 Domain model은 설계의 방향과 다르
DDD
ddd
2022. 10. 9.
DDD는 Domain Driven Design, 즉 도메인 주도 설계이다. 도메인을 중심으로 애플리케이션을 설계, 구성하는 방법이다. 도메인(Domain) 도메인이란 '소프트웨어로 해결하고자 하는 문제 영역'을 의미한다. 한 도메인은 다시 하위 도메인으로 나눌 수 있고, 도메인들은 서로 연동하여 완전한 기능을 제공한다. 이 `도메인`은 소프트웨어의 요구사항을 이해하는데 중요한 요소이다. 서비스를 통해 어떤 문제를 해결할 것인지, 어떤 도메인을 다룰 것인지, 도메인끼리의 관계가 어떠한지 확실하게 알아야 요구사항을 제대로 이해하고 개발을 효율적으로 진행할 수 있다. 도메인은 사용자가 누구인가, 어떻게 사용하냐에 따라 같은요소라고 할지라도 계속 바뀔 수 있고, 형태가 고정되어있지 않은
DDD의 아키텍처
ddd
2022. 10. 9.
도메인 주도 설계에서는 도메인을 중심으로하여 애플리케이션을 설계, 구성한다. 애플리케이션은 도메인 외에도 표현, 응용, 인프라스트럭처 등의 영억으로 나뉘어있고 각각의 역할을 수행한다. application전체를 구성하는 아키텍처 요소에 대해 알아보자. 대표적으로 DDD에서는 위와 같은 구조의 Layered Architecture를 가진다. 계층별 설명 1. Presentation Layer (표현 계층) 사용자 요청을 해석하고 응답하는 일을 책임지는 계층이다. 사용자에게 UI를 제공하거나 클라이언트에 응답을 보내는 모든 클래스가 포함된다. Client로부터 request를 받아 response를 보내는 API를 정의한다. 2. Application Layer (응용 계층) 사용
도메인영역
ddd
2022. 10. 9.
도메인 영역의 주요 구성요소는 아래 다섯가지가 있다. | 요소 | 설명 | | --| --| | 엔티티(Entity) | 고유의 식별자를 갖는 객체이다.도메인 모델의 데이터를 포함하며, 해당 데이터와 관련된 기능을 함께 제공한다. | | 밸류(Value) | 고유의 식별자를 갖지 않는 객체로, 주로 개념적으로 하나인 도메인 객체의 속성을 표현할 때 사용된다. (ex. 주소, 배송상태)엔티티의 속성뿐만 아니라 다른 밸류 타입의 속성으로도 사용될 수 있다. | | 애그리거트(Aggregate) | 애그리거트는 관련된 엔티티와 밸류 객체를 개념적으로 하나로 묶은 것이다.도메인 관계 복잡도를 낮추기 위해 여러 하위 도메인을 독립된 객체군으로 나눈다. | | 리포지터리(Repository) | 도메인 모델의 영속성
이벤트 스토밍
ddd
2022. 10. 9.
이벤트 스토밍이란 도메인에 관련된 모든 이해 관계자가 모여서 화이트 보드와 포스트잇을 활용하여 이벤트를 중심으로 업무들 간의 상호 연관성을 찾기 위해 진행하는 워크숍 방법론이다. 도메인 전문가와 개발자를 학습 과정에 참여시키기 위해 설계되었고, 모든 사람들이 시각적으로 도메인에 시각적으로 접근할 수 있게 해준다. 이벤트 스토밍을 하는 이유? 이벤트 스토밍의 가장 큰 목적은 도메인지식을 공유함으로써 전체 비스니스가 어떻게 돌아가는지 한눈에 볼 수 있는 지도(타임라인)를 만드는 것이다. 각 도메인 전문가들의 도메인 지식은 모두 분산되어 있기 때문에 한번에 전체 지도를 그리기 힘든데, 이벤트 스토밍은 그 지식을 모아 정리할 수 있도록 한다. 이벤트 스토밍 하는 법 이벤트 스토밍을
컨트랙트
ddd
2022. 10. 9.
바운디드 컨텍스트의 모델은 서로 독립적이지만 바운디드 컨텍스트 자체는 독립적이지 않다. 컨텍스트는 각자 독립적으로 발전할 수 있지만 컨텍스트끼리는 서로 상호작용해야 하기 때문에, 그 사이에는 항상 접점이 생기는데 이를 컨트랙트(Contract) 라고 부른다. 바운디드 컨텍스트 간의 연동, 즉 컨트랙트에 대한 고민은 솔루션 설계에서 평가되고 다뤄져야 한다. 이 특정 라이브러리에 의존성을 가지고 있다면 기술 스택을 업그레이드하고 바꿔야 할떄, 모든 비즈니스 로직과 infrastructure를 갈아 엎어야 할 것이다! 육각형 아키텍처(Hexagonal Architecture)는 그러한 문제를 해결하기 위해 기술과 비지니스 로직 사이를 분리하여 비지니스 로직이 기술에 구애받지 않고 동작할 수 있도록 하는 아
MSA의 장단점
msa
2022. 10. 9.
마이크로서비스 아키텍처의 장점 크고 복잡한 애플리케이션을 지속적으로 전달/배포할 수 있다. (CI/CD) MSA를 구축하면 크고 복잡한 애플리케이션을 지속적 전달/배포할 수 있다. MSA는 다음과 같은 세가지 방법으로 지속적 전달/배포를 실현한다. 테스트성: 지속적 전달/배포를 하려면 자동화 테스트가 꼭 필요하다. MSA는 상대적으로 크기가 작아서 자동화 테스트를 작성하기 쉽고 더 빨리 실행되며, 애플리케이션 버그도 적은 편이다. 배포성: MSA는 독립적으로 배포할 수 있기 때문에 개발자가 자신이 담당한 서비스 변경분을 배포할때 다른 개발자와 복잡한 협의 과정을 거칠 필요가 없다. 그래서 프로덕션에 변경분을 반영하기가 훨씬 수월하다. 자율성, 느슨한 결합: 작은 팀이 여러개 결
메시지 브로커
msa
2022. 10. 9.
브로커리스 메시징 브로커리스 아키텍처의 서비스는 메세지를 서로 직접 교환한다. 장점 송신자가 보낸 메시지가 브로커를 거쳐 수신자로 이동하는 것이 아닐, 송신자에서 수신자로 직접 전달되므로 네트워크 트래픽이 가볍고 지연 시간이 짧다. 메시지 브로커가 성능 병목점이나 SPOF(단일 정야좀)가 될 일이 없다. 메시지 브로커를 설정/관리할 필요가 없으므로 운영 복잡도가 낮다. 단점 서비스가 서로의 위치를 알고 있어야 하므로 서비스 디스커버리 메커니즘을 사용해야한다. 메시지 교환시 송신자/수신자 모두 실행중이어야 하므로 강ㅇ성이 떨어진다. 전달 보장같은 메커니즘을 구현하기가 어렵다. 브로커 기반 메시징 메시지 브로커는 모든 메시지가 지나가는 중간 지점이다. 송신자가 메시지 브로커에 메시
사가 패턴
msa
2022. 10. 9.
사가는 MSA에서 분산 트랜잭션 없이 데이터 일관성을 유지하는 메커니즘이다. 사가는 일종의 로컬 트랜잭션인데, 각 로컬 트핸잭션은 ACID 트랜잭션 프레임워크/라이브러리를 이용하여 서비스별 데이터를 업데이트한다. 주문 서비스의 createOrder() 작업은 6개의 로컬 트랜잭션을 가진 주문 생성 사가로 구현된다. Txn:1 주문 서비스: 주문을 APPROVAL_PENDING 상태로 생성한다. Txn:2 소비자 서비스: 주문 가능한 소비자인지 확인한다. Txn:3 주방 서비스: 주문 내역을 확인하고 티켓을 CREATE_PENDING 상태로 생성한다. Txn:4 회계 서비스: 소비자 신용카드를 승인한다. Txn:5 주방 서비스: 티켓 상태를 AWATING_A
사가 편성
msa
2022. 10. 9.
사가는 단계를 편성하는 로직으로 구성된다. 시스템 커맨드가 사가를 시작할 때 해당 편성 로직은 첫 번째 사가 참여자를 정하여 로컬 트랜잭션 실행을 지시하고, 트랜잭션이 완료되면 모든 단계를 실행 될때까지 계속 그다음 사가 참여자를 호출한다. 로컬 트랜잭션이 도중에 하나라도 실패한다면 사가는 보상 트랜잭션을 역순으로 실행한다. 이와 같은 사가를 편성하는 로직은 두 가지 종류가 있다. |종류|설명| |-|-| |코레오그래피(choreography)|의사 결정과 순서화를 사가 참여자에게 맡긴다. 사가 참여자는 주로 이벤트 교환 방식으로 통신한다.| |오케스트레이션(orchestration)|사가 편성 로직을 사가 오케스트레이터에 중앙화한다. 사가 오케스트레이터는 사가 참여자에게 커맨드 메시지를 보내 수행할 작업
시맨틱 버저닝
msa
2022. 10. 9.
마이크로서비스 애플리케이션은 클라이언트를 다른 서비스 팀이 이비 개발한 경우가 대부분이기 때문에 서비스 API를 변경하기가 어렵다. 서비스를 클라리언트를 모두 찾아 강제로 업그레이드시키기도 쉽지 않다. 또 요즘은 유지보수시 서버를 내리지 않기 때문에 규칙적인 단계로 서비스를 업그레이드하여 신구버전을 동시에 실행해야한다. [시맨틱 버저닝]( 명세는 API 버저닝에 관한 유용한 지침서이다. 여기에ㅔ는 버전 번호를 사용하고 증가시키는 규칙들이 면시되어있다. 시맨틱 버저닝은 원래 소프트웨어 패키지의 버저닝 용도로 쓰였지만, 분산 시스템의 API 버저닝에도 사용할 수 있다.  보상 가능 트랜잭션이 생성/수정하는 레코드에 무조건 플래그를 세팅하는 대책이다. 레코드가 아직 커밋 전이라서 변경될지 모르니, 다른 트랜잭션이 레코드에 접근하지 못하도록 락을 걸어놓는 것이다. 그 플래그는 재시도 가
트랜잭션 로그 테일링 패턴
msa
2022. 10. 9.
메시지 브로커는 보통 메시지를 적어도 한 번 이상 전달한다. 클라이언트나 네트워크, 혹은 브로커 자신에 이상이 있는 경우 같은 메시지를 여러번 전달할 수도 있다. 하지만 이때 메시지를 여러번 전달함으로 인해 중복 메세지가 발생하여 멱등하지 않은 시스템에 지장을 주거나, 메시지 순서가 꼬여 잘못 처리될 수도 있다. 이를 해결하기 위해 ID를 기록하여 검사하거나 DB 폴링 방식을 사용하기도 한다. 이때 사용할 수 있는 정교하고 성능이 꽤 좋은 방식중 하나로는, 트랜잭션 로그 테일링 패턴이 있다. 말 그대로 메시지 릴레이를 통해 DB 트랜잭션 로그(커밋 로그)를 tailing하는 방법이다. 애플리케이션에서 커밋된 업데이트를 각 DB의 트랜잭션 로그 항목(log entry)으로 남긴다. 그리고 그 후에 트
SOLID
객체지향
2022. 10. 9.
1. 단일 책임 원칙 (Single Responsibility Principle, SRP) 하나의 모듈는 하나의 책임만 가져야 한다. SRP를 적용하면 메소드의 책임 영역이 확실해지기 때문에 한 기능이 수정되었을 때 다른 연쇄작용을 일으키지 않는다. 또, 책임을 적절히 분배함으로써 코드의 가독성이 향상되고 유지보수가 용이해진다. 2. 개방 폐쇄 원칙 (Open-Closed Principle, OCP) 소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀 있어야 한다. 코드를 수정하거나 기능을 추가할 일이 생겨도 기존 구성 요소는 바뀌지 말아야한다. 추상화와 다형성으로 구현할 수 있다. 3. 리스코프 치환의 원칙 (Liskov Substitutiong Principle, LSP) 서브 타
응집도와 결합도
객체지향
2022. 10. 9.
응집도와 결합도는 코드의 관심사와 연결관계가 어느정도로 구분되어있고, 얽혀있는지를 나타내는 정도이며, 모듈의 독립성을 판단하는 두 가지 지표이다. 응집도는 모듈 내부의 기능적인 집중 정도, 결합도는 모듈과 모듈간의 상호 의존 정도라고 할 수 있다. 높은 응집도와 낮은 결합도를 가진 코드가 객체지향적으로 좋은 코드로 여겨지며, 객체지향 원칙 중 개방 폐쇄 원칙(Open-Closed Principle, OCP)과 연관있는 개념이다. 응집도(Cohesion) 응집도는 모듈에 포함된 내부 요소들이 하나의 책임/ 목적을 위해 연결되어있는 연관된 정도이다. 응집도가 높다는 것은, 하나의 모듈또는 쿨래스가 하나의 책임 또는 관심사에만 집중되어있다는 것을 뜻한다. 응집도가 높으면 그 모듈이 처리할 수
빌더 패턴
1-생성패턴
2022. 10. 9.
빌더 패턴은 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다. 빌더 패턴을 사용하면 객체를 생성할 떄 필요한 값만 넣을 수 있다. 그리고 파라미터룰 사용한 생성자가 아니라 변수명을 명시하여 생성하는 것이기 때문에 변수 순서가 바뀌거나 새로 추가될때 유연하게 대처할 수 있고 매개변수가 많아져도 가독성을 높일 수 있다. 구현하는 것이 복잡하기 때문에 직접 구현하면 코드 구조가 읽기 어려워진다는 단점이 있다. Lombok에서 제공해주는 @Builder 어노테이션을 사용하면 Lombok이 자동으로 빌더를 만들어준다. --- 예시 코드 java @Getter @Setter public class Pizza { String
싱글톤 패턴
1-생성패턴
2022. 10. 9.
싱글톤 패턴은 애플리케이션이 시작될 때, 어떤 클래스가 최초 한 번만 메모리를 할당(static)하고 인스턴스를 생성하여 사용하는 패턴이다. 똑같은 인스턴스를 여러개 생성하지 않고, 어디에서 접근하든 기존에 만들었던 인스턴스를 이용하도록 한다. --- 예시 코드 java public class LazyInitSingleton { private static LazyInitSingleton instance; private LazyInitSingleton() {} public static LazyInitSingleton getInstance() { if (instance == null) { instance = new LazyInitS
추상팩토리 패턴
1-생성패턴
2022. 10. 9.
서로 관련있는 여러 객체를 만들어주는 인터페이스를 만들어 구체적으로 어떤 클래스의 인스턴스를(concrete product)를 사용하는지 감추는 패턴이다. 구체적인 객체 생성 과정을 추상화한 인터페이스를 제공한다는 점에서 팩토리 메소드 패턴과 비슷하지만 팩토리 메소드 패턴은 구체적인 객체 생성 과정을 하위 또는 구체적인 클래스로 옮기는 것이 목적이고, 추상 팩토리 패턴은 관련있는 여러 객체를 구체적인 클래스에 의존하지 않고 만들 수 있게 해주는 것이 목적이라는 점에서 다르다. --- 예시 코드 java @Getter @Setter @AllArgsConstructor public abstract class Pizza { private String name; private Sau
팩토리메소드 패턴
1-생성패턴
2022. 10. 9.
팩토리 메소드 패턴은 부모(상위) 클래스 코드에 구체 클래스 이름을 감추고, 자식(하위) 클래스가 어떤 객체를 생성할지를 결정하도록 하는 패턴이다. 구체적인 객체 생성 과정을 추상화한 인터페이스를 제공한다는 점에서 추상 팩토리 패턴과 비슷하지만 추상 팩토리 패턴은 관련있는 여러 객체를 구체적인 클래스에 의존하지 않고 만들 수 있게 해주는 것이 목적이고, 팩토리 메소드 패턴은 구체적인 객체 생성 과정을 하위 또는 구체적인 클래스로 옮기는 것이 목적이라는 점에서 다르다. '확장에 대해 열려있고 수정에 대해 닫혀있어야 한다'는 개방-폐쇄 원칙(OCP)을 만족하는 객체 생성 방법이다. --- 예시 코드 java @Getter @Setter @NoArgsConstructor public abstrac
프로토타입 패턴
1-생성패턴
2022. 10. 9.
기존 인스턴스를 프로토타입으로 사용해 새 인스턴스를 만드는 패턴이다. 비슷한 객체를 여러개 만드는 경우 인스턴스를 생성하는 복잡한 과정을 거칠 필요 없이 새 인스턴스를 만들 수 있다는 장점이 있다. --- 예시 코드 java의 Cloneable 인터페이스와 Object의 clone() 메서드를 사용하면 프로토타입 패턴을 간단하게 사용할 수 있다. java @Getter @AllArgsConstructor public class Pizza implements Cloneable{ String name; String topping; String sauce; @Override public Pizza clone() { try {
데코레이터 패턴
2-구조패턴
2022. 10. 9.
데코레이터 패턴은 주어진 상황 및 용도에 따라 객체에 책임을 덧붙이는 패턴이다. 기본 기능에 추가할 수 있는 기능의 종류가 많은 경우에 각 추가 기능을 Decorator 클래스로 정의 한 후 필요한 Decorator 객체를 합함으로써 추가 기능의 조합을 설계 하는 방식이다. 데코레이터 패턴은 객체의 결합 을 통해 기능을 동적으로 유연하게 확장 할 수 있게 해준다. --- 예시 코드 java public interface CommentService { void addComment(String comment); } public class DefaultCommentService implements CommentService{ @Override public void addCom
브릿지 패턴
2-구조패턴
2022. 10. 9.
브릿지 패턴은 구현부에서 추상층을 분리하여 각자 독립적으로 변형할 수 있도록 하는 패턴이다. 즉, 기능과 구현에 대해 별도의 클래스로 구현하여 서로의 코드에 간섭하지 않고 변형, 확장할 수 있도록 하는 것이다. --- 예시 코드 java @AllArgsConstructor public abstract class Pizza { private String name; private Recipe recipe; public String result(){ return recipe.getName() + " " + name; } } public class CheesePizza extends Pizza { public CheesePizza(Recipe
어댑터 패턴
2-구조패턴
2022. 10. 9.
어댑터 패턴은 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴이다. 기존 코드를 변경하지 않고 원하는 인터페이스 구현체를 만들어 사용하는 것이기 때문에 기존 코드가 하던 일과 특정 인터페이스 구현체로 변환하는 작업을 각기 다른 클래스로 분리하여 관리할 수 있다는 장점이 있다. --- 예시 코드 java public interface UserDetails { String getUsername(); String getPassword(); } public interface UserDetailsService { UserDetails loadUser(String username); } public class LoginHandler { priv
컴포짓 패턴
2-구조패턴
2022. 10. 9.
컴포짓 패턴이란 객체들의 관계를 트리 구조로 구성하여 부분-전체 계층을 표현하는 패턴으로, 사용자가 단일 객체와 복합 객체 모두 동일하게 다루도록 한다. 복합 객체와 단일 객체의 처리 방법이 다르지 않을 경우, 그 관계를 전체-부분 관계로 정의할 수 있는데, 이 전체-부분 관계를 효율적으로 처리하기 위한 디자인 패턴이 컴포짓 패턴이다. --- 예시 코드 대표적인 컴포짓 패턴의 예시는 파일 디렉토리 구조이다. 내가 있는 폴더가 다른 폴더의 자식 폴더인지, root 폴더인지에 상관없이 똑같이 다룰 수 있다. 컴포짓 패턴을 사용하면 재귀적인 트리 구조를 구현할 수 있다. java public interface Composite { String getName(); String g
퍼사드 패턴
2-구조패턴
2022. 10. 9.
퍼사드 패턴은 클라이언트가 사용해야 하는 복잡한 서브 시스템 의존성을 간단한 인터페이스로 추상화 하는 디자인 패턴이다. Client는 서브시스템의 존재를 모르는 상태로, 오직 facade클래스에만 접근할 수 있도록 하는것이 특징이다. --- 예시 코드 java public class PizzaFacade { private final Chef chef = new Chef(); private final Oven oven = new Oven(); public Pizza makingPizza() { Pizza pizza = chef.makingDough(); pizza = chef.addToppings(pizza); retu
프록시 패턴
2-구조패턴
2022. 10. 9.
프록시 패턴은 인터페이스를 사용하고 실행시킬 클래스에 대해 객체가 들어갈 자리에 대리자 객체를 대신 투입하여, 클라이언트는 실제 실행시킬 클래스에 대한 메소드를 호출하여 반환값을 받는지 대리 객체의 메소드를 호출해서 반환값을 받는지 모르도록 하는것을 말한다. 프록시 패턴을 사용하면 실제 메소드가 호출되기 이전에 필요한 기능(전처리등의)을 구현객체 변경없이 추가할 수 있고, 구현클래스에 직접 접근하지않고 Proxy를 통해 한번 우회하여 접근하도록 되어있기 때문에 흐름제어를 할 수 있다는 장점이 있다. --- 예시 코드 java public interface HelloService { String run(); } public class HelloServiceImpl implements
플라이웨이트 패턴
2-구조패턴
2022. 10. 9.
플라이 웨이트 패턴은 동일하거나 유사한 객체들 사이에 가능한 많은 데이터를 서로 공유하여 사용하도록 하여 메모리 사용량을 최소화하는 패턴이다. 플라이웨이트 패턴에서는 일부 오브젝트의 상태 정보를 외부 자료 구조에 저장하여 플라이웨이트 오브젝트가 잠깐 동안 사용할 수 있도록 전달한다. --- 예시 코드 java @Getter @Setter public class Pizza { private String name; private int price; private Dough dough; private Sauce sauce; } 피자가 있다. 이제부터 피자를 아주 많이 만들어서 배송할건데, 만들 때 마다 새 인스턴스로 생성해서 배송하기엔 메모리가 너무 아깝다.
메멘토 패턴
3-행위패턴
2022. 10. 9.
메멘토 패턴은 객체를 이전 상태로 되돌릴 수 있는 기능을 제공하는 소프트웨어 디자인 패턴이다. 현재(원본) 상태를 저장하는 객체인 Originator에서 특정 상태를 저장하는 Memento 객체로 변환하여 CareTaker에 저장하는 구조이며, 핵심 객체의 데이터를 계속해서 캡슐화된 상태로 유지하는 것이 특징이다. --- 예시 코드 java @Getter @Setter public class Originator { private String state; public Memento saveStateToMemento() { return new Memento(state); } public void getStateFromMemento(Memento
방문자 패턴
3-행위패턴
2022. 10. 9.
방문자 패턴은 알고리즘을 객체 구조에서 분리시키는 디자인 패턴이다. 기존 클래스 필드 정보를 유지하면서 새로운 연산을 추가하는 방식 중 하나이다. 비슷한 동작을 수행하는 로직을 Visitor 객체에 모을 수 있기 때문에 코드를 유지보수하기 좋지만, Element와 Visitor 간의 결합도가 상승한다는 단점이 있다. --- 예시 코드 java public interface Element { void visit(Visitor visitor); } public class ElementA implements Element{ @Override public void visit(Visitor visitor) { visitor.visit(this); } }
상태 패턴
3-행위패턴
2022. 10. 9.
상태 패턴은 상태 패턴 인터페이스의 파생 클래스로서 각각의 상태를 구현함으로써, 상태를 객체화시키고 상태전이 메서드를 구현할 필요 없이 상태객체가 슈퍼클래스에 의해 정의한 메소드를 호출하여 사용하도록 하는 패턴이다. 상태 전이를 위한 조건 로직이 복잡한 경우 이를 해소하기 위해 사용될 수 있다. --- 예시 코드 java public interface State { State feelingBetter(); State feelingBad(); void printCurrentEmotion(); } java public class Happy implements State{ @Override public State feelingBetter() {
옵저버 패턴
3-행위패턴
2022. 10. 9.
옵서버 패턴은 객체의 상태 변화를 관찰하는 관찰자들을 생성하여, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 패턴이다. 옵저버 패턴을 활용하면 다른 객체의 상태 변화를 별도의 함수 호출 없이 즉각적으로 알 수 있기 때문에, 이벤트를 자주 처리해야하는 프로그램에서 적합하다. --- 예시 코드 java public interface Publisher { void add(Observer observer); void delete(Observer observer); void notifyObserver(V message); } public class NewsPublisher implements
이터레이터 패턴
3-행위패턴
2022. 10. 9.
이터레이터 패턴은 컬렉션 구현 방법을 노출시키지 않으면서 집합체 안에 들어있는 모든 항목에 접근할 수 있도록 하는 패턴이다. java의 stream이 대표적인 이터레이터 패턴의 예시이다. --- 예시 코드 java @RequiredArgsConstructor public class ArrIterator implements Iterator { private final Integer[] list; private int position = 0; @Override public boolean hasNext() { return position { private final List list; private int position = 0;
인터프리터 패턴
3-행위패턴
2022. 10. 9.
인터프리터 패턴은 자주 등장하는 문제를 간단한 언어로 정의하고 재사용하는 패턴이다. 인터프리터 패턴을 사용하면 반복되는 문제 패턴을 언어 또는 문법으로 정의하고 확장할 수 있다. 쉽게 말하면, 일정한 형식을 갖춘 텍스트(String)를 해석해서 규칙에 맞는 로직을 실행할 수 있도록 하는 것이다. 어떤 용도로, 어떤 언어를 구현하는지에 따라 정말 다양한 코드가 나올 수 있지만, 보통 명령을 입력받아 해석하는 Parser와 그것을 바탕으로 로직을 실행하는 Expression으로 나뉜다. --- 예시 코드 항이 2개인 간단한 덧셈, 뺄셈 식 계산을 인터프리터 패턴으로 구현했다. java public interface Expression { Integer interpret(String co
전략 패턴
3-행위패턴
2022. 10. 9.
전략 패턴은 프로그램이 진행되면서 캡슐화된 로직을 선택할 수 있게 하는 디자인 패턴이다. 로직 실행은 인터페이스에 의존을 시키고 인터페이스를 구현한 로직들을 전달해줌으로써 분기처리 없이 유연성을 갖출 수 있다. 객체지향 원칙중 개방-폐쇄 원칙(Open-Closed Principle)을 지키기 위한 디자인 패턴이다. --- 예시 코드 java @Setter @AllArgsConstructor public class Coupon { private DiscountStrategy discountStrategy; public int discount(int price) { return discountStrategy.execute(price); } } public
중재자 패턴
3-행위패턴
2022. 10. 9.
중재자 패턴은 객체간 커뮤니케이션을 하는 경우 중재자를 생성하여 객체끼리의 결합을 약화하는 디자인 패턴이다. 중재자 패턴을 사용하면 N:M개의 객체, 또는 N:1개의 객체간의 데이터 전달도 구현할 수 있다. 객체의 통신을 다룬다는 점에서 옵저버 패턴과 비슷하지만, 옵저버패턴은 한 객체에서 일방적으로 데이터를 송신하는데 반해 중재자패턴은 양방향으로 데이터를 전달할 수 있다는 것이 차이점이다. --- 예시 코드 java @Getter @Setter public abstract class Colleague { protected String name; private Mediator mediator; private String message; public Collea
책임연쇄 패턴
3-행위패턴
2022. 10. 9.
책임 연쇄 패턴은 객체를 연결리스트와 같은 사슬 방식으로 연결한 후에 요청을 수행하지 못하는 객체인 경우 책임을 다음 객체에 넘기며 책임을 넘기는 형태의 패턴을 말한다. 각각의 체인은 자신이 해야하는 일만 담당하기 때문에 집합 내의 처리 순서를 변경하거나 처리객체를 유연하게 추가 또는 삭제할 수 있다. --- 예시 코드 java @AllArgsConstructor public class RequestHandler { private RequestHandler nextHandler; public void handle(Request request) { if (nextHandler != null){ nextHandler.handle(request
커맨드 패턴
3-행위패턴
2022. 10. 9.
커맨드 패턴은 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 매서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다. 어떤 로직에 대한 요청을 객체화 시킴으로써, 코드를 수정하거나 교체하기 쉽게 하고, 유지보수성을 높인다. --- 예시 코드 java @Setter @AllArgsConstructor public class Lamp { private boolean power; public boolean isOn(){ return power; } } @Setter @AllArgsConstructor public class AirConditioner { private boole
템플릿메소드 패턴
3-행위패턴
2022. 10. 9.
템플릿 메소드 패턴은 동작 상의 알고리즘의 프로그램 뼈대를 정의하는 행위 디자인 패턴이다. 템플릿 메소드 패턴은 여러 작업들이 동일한 구조를 갖지만, 일부 동작은 각각 다르게 구현해야할 때 사용된다. 템플릿 메소드 패턴은 전체 실행과정을 구현한 상위 클래스(추상 클래스)와 실행 과정의 일부 단계를 구현한 하위 클래스(구체클래스)로 나뉘며, 추상 메서드를 재정의함으로써 알고리즘의 구조를 변경하지 않고 알고리즘의 특정 단계들을 다시 정의할 수 있게 해준다 --- 예시 코드 java public abstract class Human { abstract void Introducing(); void eating() { System.out.println("밥먹기"
디자인패턴
디자인패턴
2022. 10. 9.
디자인 패턴이란 프로그래밍을 할 때에 공통적으로 생기는 문제를 해결하고자 설계한 일정한 코드의 패턴이다. 애플리케이션이나 시스템을 디자인하는 과정에서 자주 발생하는 문제를 해결하는데에 쓰이는 형식화 된 관행이자, 재사용 가능한 해결책이기도 하다. GoF 디자인 패턴 종류 디자인 패턴에 대해 다루는 유명한 책 중 하나인 'GoF의 디자인 패턴'에서 다룬 디자인 패턴의 종류는 다음과 같다. 1. 생성 패턴 (Credential Patterns) 객체 생성과 관련된 패턴이다. 객체의 생성과 조합을 캠슐화하여 특정 객체가 생성되거나 변경되어도 프로그램 구조에 크게 영향을 받지 않도록 유연하게 설계하는 것이 목적이다. 싱글톤(Singleton) 패턴 클래스의 인스턴스를 오직 한개만 생성하여 제공
위임 패턴(Delegate Pattern)
디자인패턴
2022. 10. 9.
소프트웨어 엔지니어링에서 delegate pattern(위임 패턴)은 객체 합성이 상속과 동일하게 코드 재사용을 할 수 있도록 하는 객체 지향 디자인 패턴이다. 상속(inheritance) vs 합성(composition) 객체지향 시스템에서 기능의 재사용을 위해 구사하는 가장 대표적인 기법은 클래스 상속, 그리고 객체 합성(object composition)이다. 클래스 상속 서브클래싱, 즉 다른 부모 클래스에서 상속받아 한 클래스의 구현을 정의하는 것. 서브클래싱에 의한 재사용을 화이트박스 재사용(white-box reuse)이라고 한다. '화이트박스’는 내부를 볼 수 있다는 의미에서 나온 말로, 상속을 받으면 부모 클래스의 내부가 서브클래스에 공개되기 때문에 화이트박스인 셈이다. 상속의 장