거래성사 목록 쿼리에 인덱스를 적용하여 tps 속도를 높일려고 한다. 거래성사 목록 조회 쿼리 explain select completere0_.complete_request_id as col_0_0_, completere0_.from_card as col_1_0_, item3_.item_name as col_2_0_, card2_.thumbnail as col_3_0_, item3_.price_range as col_4_0_, completere0_.to_card as col_5_0_, item8_.item_name as col_6_0_, card7_.thumbnail as col_7_0_, item8_.price_range as col_8_0_, completere0_.created_date as c..
전체 글
백엔드 서버 개발자를 준비하고 있는 컴퓨터공학 학부생입니다.문제점 클라이언트는 에러가 날 때 어떤 오류가 나는지 상세히 알지 못한다. 프론트와의 원활한 협업을 위해 에러를 상세히 내려주자는 의견이 나왔다. 우리 프로젝트에선 에러코드를 Enum으로 정의하고 있었는데, 이 ErrorCode를 건드리지 않고 그대로 클라이언트에게 전송할 수 있을지가 이슈였다. @Getter @AllArgsConstructor public enum ErrorCode { UNKNOWN("G0001", "알 수 없는 오류가 발생했습니다."), INVALID_ACCESS("G0002", "잘못된 접근입니다."), DUPLICATED_EMAIL("G0003", "중복된 이메일이 이미 존재합니다."), DUPLICATED_NAME("G0004", "중복된 이름이 이미 존재합니다." ), INVA..
멀티 모듈을 도입한 이유 나비마켓 프로젝트는 서버가 한대로 구성되어 있어, 멀티 모듈로의 변환이 필수적이지는 않았다. 하지만 대부분 기업에서는 여러 서버로 운영되므로 멀티모듈 적용의 경험이 필요하다 느끼게 되었다. 멀티모듈이란 ? 멀티 모듈은 하나의 시스템이나 프로젝트를 여러 개의 독립적인 모듈로 분리하여 구성하는 방식이다. 모듈화된 구조는코드의 재사용성을 높여주는데, 비슷한 기능을 가진 모듈을 다른 프로젝트에서도 재사용해서 개발 시간과 노력을 절약할 수 있다는 장점이 있다. 모듈의 분리 기준 하나의 모듈을 여러개의 모듈로 분리를 하게 되면서 기존 프로젝트의 패키지 별, 즉 계층별로 모듈을 분리하게 되었다. 이렇게 모듈을 구성했을 시에 순환 참조의 문제가 생기게 되었다. 순환참조 문제를 해결한 아키텍처 ..
배경 다음과 같이 나의 카드들 중, 오퍼/찔러보기를 요청하고자 하는 CardInfo와 이미 해당 카드에 내 카드가 제안된 상태인지를 담는 SuggestionInfo 가 있어야 한다. 문제 상황 내 카드들의 정보는 모두 채워져서 내려져야 하며, SuggestionInfo 정보는 내 카드들 중에서 어떠한 카드가 타겟 카드에 이미 제안을 한 상태인 카드이면 정보가 채워져서 내려가고, 아니면 null로 내려가야한다. 나의 생각 따라서 대상 테이블은 Card이며, Suggestion을 leftjoin으로 조인해야한다. 그래야 Card의 정보는 채워지고 타겟cardId를 제안한 카드가 있을 경우에만 suggestionInfo 테이블이 채워진다. 작성 코드 public List getSuggestionAvailabl..
문제 카드 이미지를 기존 jpaRepository.saveAll 하는 과정에서 insert 쿼리가 다음과 같이 image url의 갯수만큼 나간다. insert into card_images (created_date, modified_date, card_id, image_url) values (?, ?, ?, ?) Hibernate: insert into card_images (created_date, modified_date, card_id, image_url) values (?, ?, ?, ? 한번의 쿼리만 나갈 수 있는 방법이 없을까? Batch insert INSERT INTO table (col1, col2) VALUES (val1, val11), (val2, val22), (val3, val3..
객체지향 프로그래밍 어떤 객체들이 필요할지 부터 고민하라 클래스의 윤곽을 잡기 위해서는 어떤 객체들이 어떤 상태와 행동을 가지는지를 먼저 결정해야함 객체를 기능을 구현하기 위해 협력하는 일원으로 봐야한다. 객체들의 모양과 윤곽이 잡히면 공통된 특성과 상태를 가진 객체들을 타입으로 분류하고 이 타입을 기반으로 클래스를 구현하라 클래스 구현하기 어떤 부분을 외부에 공개하고 어떤 부분을 감출지를 결정하는 것. 외부에서는 객체의 속성에 직접 접근할 수 없도록 막고 적절한 public 메서드를 통해서만 내부 상태를 변경할 수 있게 해야함 자율적인 객체 객체는 상태와 행동을 함께 가지는 복합적인 존재 데이터와 기능을 객체 내부로 함께 묶는 것 : 캡슐화 객체의 상태는 숨기고 행동만 외부에 공개해야 한다. 자신이 할..
우리는 db를 이용하기 위해서 connection을 얻어야한다. EntityManagerFactory라는 곳에서 요청이 올때마다 EntitiyManager를 생성하고, 이 엔티티매니저는 커넥션 풀 안에 있는 커넥션을 사용하여 db에 접근할 수 있게된다. 영속성 컨텍스트란 엔티티를 영구 저장하는 환경 ! EntityManager.persist(entity); 로 영속성 컨텍스트에 엔티티를 영속화 시킨다. 엔티티매니저를 통해서 논리적인 개념인 영속성 컨텍스트에 접근할 수 있다. 스프링 프레임워크와 같은 환경에서 엔티티 매니저와 영속성 컨텍스트가 N:1의 관계이다. 엔티티매니저 == 영속성 컨텍스트라고 봐도 무방하다. 엔티티 생명주기 비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 ..
의문 데브코스에서 백엔드 프로젝트의 테스트 코드를 작성하던 중, 어느곳에서는 given()을 쓰고, 어느곳에서는 when()을 썼다. 둘 다 하는 기능은 똑같은데 왜 다른 이름을 쓰는걸까? 하는 의문점이 생겼다. when() 은 org.mockito.Mockito 를 import 하고, given()은 org.mockito.BDDMockito를 import한다. Mockito란? 우리는 객체간의 의존성에 대한 설계만 잘해주면 스프링에서는 DI를 지원해주어 알아서 객체들간의 의존성 관리를 해준다. 하지만 테스트를 하게될 때, 의존 관계를 맺고 있는 다른 객체가 있는 경우 다른 객체에 의해서 테스트 결과각 영향을 받을 수 있다는 문제가 있다. 이런 경우 우리는 테스트 대상을 고립되게 만들어야 하는데 그것을 ..
멤버를 조회할 때는 멤버만 가져오고 팀은 프록시로 가져왔다. 이제 m.getTeam().getName() 으로 팀에 있는 뭔가에 접근을 할 때, 쿼리가 나감! team 프록시 객체가 초기화 되면서 db에서 이 값을 가져와서 채운다. eager로 변경을 하게 되면 팀을 조인해서 select 쿼리가 나간다. 실무에서는 즉시로딩 쓰면 안된다. jpql의 경우 member를 select한 후 member를 가져왔더니, team이 즉시로딩으로 되어있네? 즉시로딩인 경우 값이 다 들어가 있어야 한다. -> member 쿼리가 나가고, member의 개수가 10개라면 10개만큼 eager로 가져오기 위해서 쿼리가 별도로 나간다 예를 들면 select * from Member; select * from Team whe..
캐시 캐시란 자주 사용하는 데이터를 미리 보관해둔 임시장소를 의미한다. 캐시는 비교적 저장 공간이 적고 전체적인 비용이 비싸다. 대신 빠른 IO를 통해 성능적 이점을 가져올 수 있다. 일반적으로 도중에 변경될 일이 없는 데이터베이스 조회 값 자주 호출하는 데이터 와 같은 특징들을 가지고 있는 데이터에 대해 캐시를 사용하면 좋다. 스프링부트에서의 캐시 스프링부트에서 사용할 수 있는 캐시는 대부분 JSR-107을 따른다. JSR-107을 따르는 캐시를 사용하면 어떤 구현체 캐시를 사용하는지에 관계없이 추상화를 지원한다. 로컬 캐시와 글로벌 캐시 로컬 캐시 로컬(해당 서버)에서만 사용하는 캐시 외부 서버와 트랜잭션 비용이 들지 않기 때문에 속도가 빠르다. 로컬에서만 사용하기 때문에 분산 서버의 구조에서 캐시를..
EntityManagerFactory는 사용자의 요청이 있을때마다 EntityManager를 생성하고,각각의 EntityManager는 db connection을 통해 db에 접근한다. 영속성 컨텍스트란?- 엔티티를 영구 저장하는 환경- EntityManager.persist(entity);를 통해 엔티티를 영속성 컨텍스트 안에 저장한다.- 영속성 컨텍스트는 논리적인 개념으로, 엔티티매니저를 통해서 영속성 컨텍스트에 접근한다.package hellojpa;import jakarta.persistence.*;public class JpaMain { /* jpa는 sql을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공 */ public static void main(Stri..
디자인 패턴은 객체 지향의 특성 중 상속, 인터페이스, 합성을 이용한다. 어댑터 패턴 호출 당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출하는 패턴이다. 기존의 ServiceA, ServiceB의 메서드를 같은 이름의 메서드로 호출해서 사용할 수 있게 해주는 변환기다. public class ServiceA { void runServiceA() { } } public class ServiceB { void runServiceB() { } } public class ClientWithNoAdapter { public static void main(String[] args) { ServiceA serviceA = new ServiceA(); ServiceB serviceB =..