🫡 요구사항 촬영장비 렌탈 플랫폼 DayFilm 의 아이템(상품) 도메인을 맡아 서버 개발을 진행했다. 아이템을 등록할 때, 여러 장의 사진과 함께 등록해야 하는 요구사항이 있었고 배포 Tool로 AWS 를 선택했기 때문에 S3 Bucket 에 등록하기로 결정하였다. 🫡 엔티티 Item.class @Entity @Builder @NoArgsConstructor @AllArgsConstructor @Table(name = "ITEM_TABLE") @Getter public class Item { @Id @GeneratedValue @Column(name = "item_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="sto..
Devit 플랫폼을 개발한지는 시간이 조금 지났지만, 마감 기한에 맞추기 바빠 채팅구현에 대한 포스팅을 진행하지 못한 점이 아쉬워 복습할 겸 다시 공부해 기록을 작성하려한다. 👍🏻 STOMP 란 Simple Text Oriented Messaging Protocol 의 약자로, 텍스트 기반 메시징 전송을 효율적으로 하기 위한 프로토콜이다. 특징으로는 Rabbit MQ 와 같이 구독 발행 시스템인 pub/sub 기반으로 작동한다. 메시지에 대한 송신 수신에 대해서 명확하게 구분하며, 별도의 핸들러를 구현할 필요 없이 @MessageMapping 어노테이션을 통해 메시징에 대한 엔드포인트 처리를 진행 할 수 있다. 위 그림은 기본적인 Message Queqe 를 이용한 STOMP 로직이다. Message B..
스프링은 스프링 컨테이너 ( Ioc 컨테이너 , DI 컨테이너라고도 불린다. ) 를 통해 객체를 빈에 등록하고 생명주기를 관리한다. 때문에 비즈니스 로직에 맞게 알맞은 생명주기를 선택해 적용하는 것은 매우 중요하다. 어떻게 빈을 생성하고 관리하고 소멸할지에 대해서는 백엔드 개발자에게 매우 민감하고 중요한 문제이기 때문에 스프링의 빈 관리 특징들을 이해해보자. 싱글톤 스프링의 기본 디자인패턴은 싱글톤이다. 싱글톤 디자인 패턴은 스프링 애플리케이션의 시작부터 종료까지로 빈의 생명주기를 관리한다. 즉 애플리케이션이 실행될 때 스프링 컨테이너에서 해당 빈 객체들을 생성하고 의존관계를 맺어준다. 또한 애플리케이션이 종료될 때 빈 객체의 소멸 메소드를 실행해 빈 객체의 소멸까지 보장해준다. 또한 싱글톤 디자인 패턴..
Spring Boot starter 에 내장되어있는 tomcat 은 기본적으로 Multi Thread 환경을 지원한다. 덕분에 클라이언트의 요청을 처리하고 있는 도중 새로운 클라이언트 요청이 들어왔을 경우, 이전 요청이 끝날 때까지 기다리지 않고 다른 쓰레드가 해당 요청을 처리한다. 자칫 잘못하면 데이터의 일관성이 무너질 수 있기 때문에 해당 쓰레드간의 동기화 과정은 매우 중요하다. 보통 멀티 쓰레드 환경에서 하나의 사용자의 요청을 하나의 쓰레드로 처리한다. 동일한 ip의 요청일 때에는 같은 쓰레드로 처리할 수 있긴하지만, 일반적인 경우에는 하나의 요청에 하나의 쓰레드가 붙는다. 그러나 매번 요청이 생성되고 끝날 때마다, 쓰레드를 생성하게 되면 생성하고 삭제하는 코스트가 발생한다. 스프링에서는 이러한 코..
이전 포스팅에서 Cache 를 구현할 수 있는 다양한 방법에 대해서 알아보았다. 각 방법의 특징을 서술하고 본 프로젝트에 HashMap 을 적용해 Cache 를 구현하는 이유에 대해서도 설명하였다. 이번 포스팅에는 HashMap 으로 어떻게 Cache 를 구현하는지에 대해 알아보겠다. https://daisyit.tistory.com/43 : 캐시 전략 비교 🌊 Key 설정 우선 캐시에서 가장 중요한 건 key 값의 설정이다. key 값을 통해 원하는 value 에 접근하기 때문에, 어떻게 key 값을 설정할 것인지 명확하게 구분지어야 한다. 해당 프로젝트는 바라보는 데이터베이스 소스인 datasourceKey 값과 실행할 쿼리 sql 값에 따라서 데이터가 달라지기 때문에 이 두 변수를 key 값으로 지..
인턴에서 백오피스 개발을 하던 도중, 같은 데이터를 계속 조회하는 상황이 빈번하게 발생했다. 데이터 수도 꽤 많았기 때문에 매우 비효율적이라고 판단했고, Cache 를 적용해 이전에 조회한 데이터를 다시 데이터베이스에서 조회하지 않게 설계하였다. JDBC를 사용해 커넥션을 연결하고, 쿼리를 날린 후, 데이터베이스에서 다시 가져와 커밋하는 코스트가 매우 높기 때문이다. 캐시를 사용해야겠다고 마음 먹은 후, 요구사항에 맞는 캐시전략을 사용해야했다. 이번 프로젝트의 요구사항은 서버는 하나이며, 캐시의 키 값으로 구분지을 데이터 종류가 많지 않았다. 대시보드의 각 서브 메뉴마다 데이터가 존재했기 때문에, 서브메뉴 * 쿼리 파라미터 개수만큼 데이터 종류가 나왔기 때문이다. Redis, EHcache, HashMa..
index 는 데이터베이스 테이블의 검색 속도를 향상시키기 위한 방법 중 하나이다. 많은 예시에서 책갈피로 불리는 index에 대해서 자세히 알아보자. 사진에서 볼 수 있듯이, 테이블에 Full Scan 으로 값을 찾기 전 빠르게 해당 데이터의 위치를 찾아 효율을 높이기 위해서 index를 사용한다. 다만 SELECT 를 제외하고, UPDATE, DELETE, INSERT 명렁어를 사용하는 sql일 경우 오히려 성능이 저하될 수 있다. 해당 데이터가 변경되면 인덱스에도 적용해야하기 때문에 추가적인 작업이 필요하기 때문이다. 결론은 해당 서비스 로직과 데이터베이스 테이블의 특징을 면밀히 분석해 index 를 적용했을 때 성능이 향상될 거 같다고 판단될 때 사용해야한다. 인턴을 경험해보니, 대규모 데이터의 ..
이전 포스팅에서는 순수 JDBC 를 사용해 사용자가 직접 트랜잭션을 제어하고 관리하는 방법에 대해서 알아보았다. 근본적이고 "유일한" 방식은 틀림없지만, 매번 연결할 때마다 선언하고 관리하는건 비효율적이다. 때문에 스프링에서는 @Transactional 어노테이션을 제공해 코드의 중복을 없애고 편리하게 관리할 수 있도록 지원한다. 하지만 동작원리는 똑같다. - 코드예시 @Transactional public UUID saveUser(User user) { log.debug("User(service) : 새로운 유저를 저장합니다. {}", user); return userRepository.save(user); } 다음과 같은 새로운 유저를 저장하는 예시 코드가 있다. 기존 스프링에서는 Spring Con..