목록전체 글 (102)
algoqna
MSA 기반 이커머스 시스템 토이프로젝트에서 kafka 중복, 네트워크 이상으로 장애 문제에 대해 방법 기록. 우선 로직은 간단하게 구성하였다.- 유저가 상품을 주문1. 상품 서버에서 주문이 가능한지 재고를 먼저 확인한다. - 주문이 불가능한 경우 kafka까지 거치지 않고 그대로 Exception처리 2. 주문이 가능하다면 상품 서버에 있는 kafkaProducer가 UUID와 함께 주문 리스트를 넘겨준다. 3. 주문 서버에 있는 kafkaConsumer가 이에 응답하고, 주문을 Create하여 db에 insert한다. 먼저 2번 경우에 대해서 발생할 수 있는 장애는 다음과 같다.(Producer -> broker의 상황을 의미합니다.)1. Producer에서 데이터의 중복이 발생하지 않도록 동일..
Nested loops는 결합 알고리즘의 일종으로, 결합의 기본이 되는 알고리즘입니다. 이에 대해 헷갈리는 점이 있어, 확실히 정리하고 넘어가려 합니다. Nested Loops 영어 뜻 그대로, 중첩 루프라고 부르는 알고리즘입니다. SQL에서 결합은 한 번에 두개의 테이블만 결합하므로, 본질적으로는 이중 반복과 같은 의미로 나타납니다. 두 테이블을 결합하기 때문에, 기준이 되는 테이블과 그렇지 않은 테이블을 구분할 수 있습니다. 이를 Driving, Driven 또는 Inner, Outer의 개념으로 분류합니다. R(A) * R(B) = R(B) * R(A)? 드라이빙 테이블의 레코드를 R(A), 드리븐 테이블의 레코드를 R(B)라고 하겠습니다. Nested Loops에서 일반적으로 구동 테이블(Driv..
- 해당 내용은 Real MySQL 8.0 책을 읽고, 그동안 헷갈렸던 것들에 대해서 정리한 내용입니다. - MySQL 버전 8.0 이전 버전에 대해서는 올바르지 않을 수 있습니다. 쿼리의 실행 계획을 확인하는 키워드로 EXPLAIN, EXPLAIN ANALYZE를 이용할 수 있습니다. 실행 계획은 옵티마이저가 선택한 계획이며, 아래와 같은 정보로 나타납니다. 해당 내용에서는 type에 대해서 초점을 맞춥니다. type 칼럼 쿼리의 실행 계획에서 MySQL 서버가 각 테이블의 레코드를 어떤 방식으로 읽었는지 나타냅니다. 방식이라는 것은 인덱스를 사용했는지, 풀 테이블 스캔을 사용했는지를 의미합니다. 쿼리를 튜닝할 때 인덱스의 효율적 사용을 판단하는 지표로 type은 반드시 체크해야합니다. 1. syste..
참고 : 도메인 주도 개발 시작하기 - 최범균 저자 도메인 영역을 구성하는 요소를 DDD의 관점에서 바라본다. 1. 엔티티(ENTITY) 고유의 식별자를 갖는 객체로 자신의 라이프 사이클을 가진다. MySQL의 AutoIncrement를 이용하면, 엔티티들은 1, 2, 3 ....등의 각자의 고유 식별자를 가지는 것과 같다. 이들은 도메인 모델의 데이터를 포함하고, 해당 데이터와 관련된 기능을 함께 제공한다. 2. 밸류(VALUE) 고유의 식별자를 갖지 않는 객체로, 주로 개념적으로 하나의 값을 표현할 때 사용한다. 금액의 표현은 int price로 할 수 있지만, 금액이라는 것을 더 명확하게 하고 싶다면 Money타입의 클래스로 대체하여 사용할 수 있다. 배송지 주소는 여러 가지의 필드를 가질 수 있다..
계층형 카테고리를 구현한 내용을 정리합니다. 카테고리 Entity의 모습은 다음과 같습니다. @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "category_id") private Long id; @Column(name = "category_name", unique = true) private String name; private int depth; @OneToMany(mappedBy = "category", cascade = CascadeType.ALL) priv..
JDK 동적 프록시는 인터페이스를 필요로 하며, CGLIB는 인터페이스가 없어도 사용할 수 있다. 그렇다면 경우에 따라 나누어 사용할 수 있는데, 둘 다 필요로 하는 경우에는 둘 다 구현해야 하나?라는 생각이 들 수 있다. 스프링에서는 동적 프록시를 통합해서 편리하게 만들어주는 ProxyFactory라는 기능을 제공하며, 이 팩토리로 두 방식을 모두 처리할 수 있다. 쉽게 말해 ProxyFactory는 인터페이스가 있으면 JDK를, 없으면 CGLIB를 내부적으로 선택한다. 또한 이 설정을 변경할 수도 있다. 그림으로 보면 아래와 같다. JDK 동적 프록시 방식이던, CGLIB던 상관없이 모두 처리하기 위해 ProxyFactory에서는 Advice 개념을 도입한다. 결과적으로 InvocationHandle..
프록시 패턴을 이용하여 프록시 클래스를 생성하고, 생성한 프록시 클래스를 대신 주입하면 비즈니스 로직을 건드리지 않고 추가 로직(접근 제어, 부가 기능 등)을 구현할 때 기존 코드를 변경하지 않고 이용할 수 있는 장점이 있다. 하지만 대상 클래스 수만큼 프록시 클래스를 만들어야하는 단점이 있다. 즉 100개의 대상 클래스가 있다면, 100개의 프록시 클래스를 만들어야 한다. 이 단점을 해결하기 위해 자바가 기본으로 제공하는 JDK 동적 프록시 기술이나 CGLIB같은 생성 오픈소스 기술을 활용하여 프록시 객체를 동적으로 만들어 낼 수 있다. 프록시를 적용할 코드를 하나만 만들어두고 프록시 객체를 계속 찍어내는 것이다. 이해하기에 앞서 프록시의 기능을 잠시 정리해보자. 프록시는 타겟과 똑같은 메서드를 구현하..
컴퓨터 네트워크에서 클라이언트 / 서버를 말하면 보통 클라이언트를 웹 브라우저, 요청을 처리하는 서버를 웹 서버라고 한다. 해당 개념을 객체에 도입하면 요청을 하는 객체가 클라이언트가 되고, 요청을 처리하는 객체가 서버가 된다. 하지만 클라이언트가 서버에 직접적으로 요청하지 않고 중간(대리)자를 이용해서 요청할 수도 있다. 중간에 대리자를 둘 경우, 대리자에게 여러가지 목적을 위임할 수도 있다. 프록시를 중간에 두면 아래와 같은 그림이 된다. 위의 그림에서 Proxy를 하나만 두었지만, Proxy를 여러가지를 두어 최종적으로 서버에 도달하게 할 수도 있다. 프록시를 여러가지 두면 프록시 체인이 된다. 객체에서 프록시가 되려면, 클라이언트가 서버에 요청을 직접적으로 한지 프록시에게 요청을 한지 몰라야 한다..