본문 바로가기

전체 글139

WebClient 인코딩 중복 이슈 이전글 에서 WebClient 인코딩 중복에 대해서 한번 다룬적 있다. 간단히 요약하면, uriBuilder 를 이용해서 만들면 이미 인코딩된 query string 값을 또 인코딩 해서 이중 인코딩 한 결과가 나온다. 그래서 미리 인코딩 할 필요가 없다. // 아래처럼 만들면, 최종 request 는 이중 인코딩된 결과로 보내진다. this.webClient .get() .uri(uriBuilder -> uriBuilder .path("/api") //.query("name=양봉수") .query("name=%EC%96%91%EB%B4%89%EC%88%98") .build() ) .retrieve() 그런데 query string 이 json 일때는 미리 인코딩 해야만 한다. 안하면 에러가 발생한다... 2023. 3. 13.
DID 스터디 2회차 1. DID 샘플 프로젝트 로컬에서 띄우기 1. web 을 띄워야함(node 서버) - https://github.com/conanoc/indy-sample-agents 2. npm install 해야함 3. node version 16.13.0 으로 down grade 해야함. -> npm 과 궁합 4. indy-sdk 설치 $ brew tap conanoc/libindy $ brew install --build-from-source libindy $ sudo ln -s /opt/homebrew/lib/libindy.dylib /usr/local/lib/libindy.dylib (M1 mac) - 참고 : https://github.com/hyperledger/indy-sdk/#macos 샘플 프로젝트.. 2023. 2. 25.
Enum 타입 에 따른 테스트(DynamicTest) 커머스 관련 개발을 하다보니 수많은 Enum 들을 만나게 된다. 아래 Enum 은 간단한 상품타입 코드다. 단순 옵션과 복잡한 옵션 두개의 타입이 있다. public enum ProductType { SIMPLE_OPTION, COMPLEX_OPTION } 상품타입에 따라 달라지는 부분을 테스트 하기 위해선 ParameterizedTest 와 EnumSource 를 사용하면 된다. @ParameterizedTest @EnumSource(names = {"SIMPLE_OPTION", "COMPLEX_OPTION"}) void enumSourceTest(ProductType productType) { System.out.println(productType); } 하지만 Enum 들 관계에 따라 비지니스 로직.. 2023. 2. 18.
DB Connection Storm 1. DB Connection 일반적으로 DB 서버와 애플리케이션 서버는 물리적으로 분리해 운영한다. 그래서 네트워크 통신을 해야하고 서로 Connection을 맺어야 한다. 2. DB Connection Pool TCP 기반 네트워크 통신으로 Connection을 맺어야 하는데 연결을 맺을때는 3 way handshake, 연결을 끊을 때는 4 way handshake 가 필요하다. 즉 연결을 맺고 끊는데 시간이 걸린다. 사용자 요청마다 Connection 을 맺고 끊는 작업을 하게 되면 비효율적이다. 그래서 DB Connection Pool 을 이용해 애플리케이션 서버가 배포될 때 미리 DB 서버와 통신할 때 사용할 Connection 들을 만들어 놓는다. 그리고 사용자 요청이 오면 Pool 에 있는.. 2023. 2. 11.
자바로 같은 상품 Grouping 아래 장바구니 페이지를 보면 손목 보호대는 같은 상품 2개가 묶여서 담겨있다. 하지만 팔꿈치 보호대는 같은 상품임에도 1개씩 개별적으로 담겨있다. 그래서 같은 상품끼리 Grouping 해주는 작업이 추가적으로 필요하다. 먼저 Product 와 Item 의 관계를 이해해야한다. 위에서 Product 는 '슈퍼비스트 손목보호대' '슈퍼비스트 팔꿈치, 무릎 관절보호대' 이고 Item 이 블랙, 팔꿈치(무릎은 선택안함) 이다. 쉽게 생각하면 Item 은 옵션정보다. 그래서 Product 는 여러개의 Item 들을 가질 수 있다. import java.util.List; import lombok.Builder; import lombok.Value; @Value @Builder public class Product.. 2023. 2. 5.
DID 스터디 1회차 1. SSI(Self Sovereign Identity) 와 DID(Decentralized Identifier) SSI 에 대해 설명하기전에 먼저 기존 ID 시스템에 대해 설명하려한다. 1세대: 서비스마다 각자 ID 관리 2세대: SSO(Single Sign On) 페이스북인증, 구글인증 0. 페이스북의 개발자 포털에 접속하여, 페이스북 인증을 사용하고자 하는 애플리케이션 정보를 등록한다(서비스명, 서비스 URL, 그리고 인증이 성공했을 때 인증 성공 정보를 받을 콜백 URL) 그리고 Client ID와 Client Secret을 발급받는다. 1. 사용자가 웹 브라우저에서 Client Application(페이스북 로그인 기능 사용)을 이용하려고 요청한다. 2. Client Application 은 사.. 2023. 1. 28.
네이버페이 주문/결제 DB 전환 이슈 우리팀은 네이버페이 주문/결제에 사용중인 Oracle DB 를 nBase-T 라는 분산 DB(사내 솔루션)로 전환 하고 있다. 1. DB 전환이란? 기존 애플리케이션 서버는 Oracle DB 를 사용하고 있다. 새로운 애플리케이션 서버와 nBase-T DB 로 문제없이 전환하기 위해선 실시간 DB 복제가 이뤄져야 한다. cf) 기존 데이터 마이그레이션은 당연히 되어 있다는 전제 cf) DB 전환할 때 꼭 새로운 애플리케이션 서버가 필요한건 아니다. 우리팀은 DB 전환 뿐만 아니라 애플리케이션도 새롭게 개발하고 있다. 새로운 애플리케이션 서버와 nBase-T DB 가 준비되면 사용자 요청을 스위칭해서 전환을 시작한다. 이때 역동기화 복제를 해주는데 롤백을 대비한 조치다. 만약 신규 서버에 문제가 생기면 기.. 2023. 1. 23.
DB 장애로 인한 EDA 기반 이벤트 보정처리 지난주 갑자기 모든 애플리케이션 서버들이 DB 서버와의 네트워크 연결을 실패했다. 전면장애인 상황이다. DB 에 문제가 생기면 내가 담당하는 주문서 서버는 어떤 문제가 발생하고 왜 보정처리가 필요한지 알아보자. // api 응답 에러 메세지 Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Cannot get a connection, pool error Timeout waiting for idle object 사용자가 주문서 화면에서 결제 버튼을 누르면 유효성 검사를 거쳐 결제가 진행되고 최종적으로 주문완료 작업을 수행한다. 만약 결제가 수행되기 전에 DB 문제가 생긴다면 사용자는 불편함을 겪.. 2023. 1. 15.
나는 하루 5분만 바꾸기로 했다 예전 아웃퍼포머 책리뷰에서 '마이루틴' 에 대해 잠깐 언급한적이 있었다. '마이루틴' 은 내가 정한 삶의 루틴들을 잘 수행할 수 있게 도와주는 앱이다. 그땐 시작한지 5일 밖에 안됐지만 지금은 300일을 넘길 정도로 잘 활용하고 있다. 그러던 중 해당 스타트업 대표가 책을 썼다고 해서 '마이루틴' 사용 후기를 남기고 책을 선물 받았다. 내가 느낀 이 앱의 매력은 유연함에 있다. 루틴들을 지키지 못해도 포기하지 않고 꾸준히 할 수 있게 도와준다. 이 앱은 달성을 의미하는 초록불 기준이 러프하다. 루틴을 수행 못하면 못했다고 표시하고 넘어가면 된다. 물론 못하는게 계속 반복되지 않도록 신경은 써준다. 이 책은 루틴을 만들어 실천하고 싶지만 마음처럼 잘 안되는 사람들에게 도움이 될 거 같다. 나도 요즘 회사일.. 2023. 1. 15.
index 가 필요해도 자바 고전 for 문 안쓰는 방법 먼저 Product 는 item 리스트를 갖고 있다(Product 는 여러개일 수 있다). @Value @Builder public class Product { List items; } item 은 id 필드만 존재한다. @Value @Builder public class Item { String id; } 이제 각 Product 안의 모든 Item id 를 검사하는 로직을 만들어보자. 그런데 2가지 조건이 있다. 1. 모든 Item 들을 다 검사하고, 실패하는 것들은 예외 리스트로 담아서 전달. 2. 예외 객체에 담을 때 item index 정보가 필요. index 정보가 필요하니 가장 먼저 생각나는것은 고전 for문 방식이다. 이중 for문 으로 각 Product 안의 모든 Item 을 검사하고 예외.. 2023. 1. 14.
WebClient 프록시(CONNECT HTTP Method) 이전 글에서 간단히 설명한 WebClient 프록시 방식에 대해서 자세히 살펴보려한다. 먼저 우리는 보안 요구사항으로, 네이버망에 있는 서버와 API 통신을 할 때 프록시 서버를 거치도록 수정했다. 코드 작업은 간단하다. reactor.netty HttpClient 에서 제공하는 proxy 메서드를 사용해 프록시 host 와 port 만 적어주면 프록시를 거쳐서 baseUrl 에 등록된 서버로 호출된다. HttpClient httpClient = HttpClient.create() .proxy(it -> it.type(Proxy.HTTP) .host(프록시 서버 주소) .port(443) ); WebClient webClient = WebClient.builder() .clientConnector(new.. 2022. 11. 27.
주문 동시성 이슈 정리 상황 설명 주문서 서버는 이벤트 기반으로 동작한다. 주문서를 만들고 결제 프로세스를 진행하면 '주문 완료 이벤트'를 발행한다. 그러면 해당 이벤트를 consume 해서 아래 그림 1번 작업이 수행된다. 문제는 1번 작업에서 API 를 호출해, 주문/결제 서버로 요청을 보냈는데 Read Timeout 에러가 발생했다. 2번 주문 완료 요청중 에러가 발생하면 주문 실패 이벤트가 발행되고, consumer 가 4번 작업을 수행하면서 새롭게 API 를 호출한다. 여기서 기존 2번 작업과 동시성 이슈가 발생하면서 실제로는 주문이 완료 처리 됐지만 완료 되지 않았다는 결과를 받게 된다. 그래서 주문서 서버는 주문이 이미 완료 됐는지 확인하는 방어로직이 있음에도 불구하고 롤백 프로세스가 진행됐다. 주문서 서버 입장에.. 2022. 11. 14.