전체 글

The sky is the limit
들어가기최종 프로젝트에서 판매자와 구매자 간 일대일 채팅을 구현하기로 하였다.처음에는 클라이언트가 서버에게 지속적으로 요청을 해 메시지를 받으면 되지 않을까 생각했다.하지만, 이런 polling 방식은 매번 HTTP 연결을 생성하고 끊기 때문에 서버에 부담을 준다. 때문에 실제로 채팅, 주식 거래 등 실시간성 데이터를 송수신할 때는 웹 소켓 방식을 활용한다고 한다.이번 글에서는 웹 소켓과 웹 소켓 위에서 쓰이는 STOMP를 알아보고, 코드에 적용해 볼 것이다. 웹 소켓이란?웹 소켓은 서버와 클라이언트 간 양방향 통신이 가능한 프로토콜이다.웹 소켓 과정은 Open Handshake, Data Transfer, Close Handshake로 나눌 수 있다. [Open Handshake]클라이언트는 HTTP에..
엔티티의 필드 값을 수정하고 반영하는데 변경 감지 혹은 벌크 수정 쿼리를 사용할 수 있다.예시로 Waiting 엔티티의 필드를 수정해 보며 둘의 차이점을 알아보자.1.  영속성 컨텍스트와 DB 간 불일치 가능성변경 감지에서는 영속성 컨텍스트와 DB가 항상 일치한다.반면 벌크 수정 쿼리는 상황에 따라 영속성 컨텍스트와 DB가 불일치 할 수 있다. 변경 감지엔티티를 repository에 저장하면 해당 엔티티가 영속화되어 영속성 컨텍스트에서 관리된다. 따라서 setStatus()로 status 필드를 PROGRESS에서 CANCELED로 수정했을 때영속성 컨텍스트는 변경 감지를 하여 엔티티의 수정 사항을 반영한다.참고로 update 쿼리와 h2 필드를 확인하기 위해 @Rollback(false)를 추가하였다...
도입 배경웨이팅 로직을 구현하며 웨이팅 취소, 지연, 입장에 따라 웨이팅 순서를 갱신해줘야 했다.초기에는 웨이팅 순서를 DB에 저장하고, 아래의 상황들에서 벌크 연산으로 웨이팅 순서를 업데이트하고자 했다. 웨이팅 순서를 rank라고 했을 때특정 고객이 웨이팅을 취소하거나 대기를 맨 뒤로 미룸 -> 해당 고객 뒤 고객들의 rank 1 감소시키기고객 입장 -> 다른 고객들의 rank 1 감소시키기 rank는 실시간으로 변화하는 데이터라 매번 벌크 연산을 진행하고 DB에 반영하면 테이블 부하가 심해지는 문제가 있었다. 이에 Redis의 list 자료 구조를 활용해 대기열 큐를 구현하기로 하였다.Redis는 인메모리 데이터베이스로 빠른 읽기, 쓰기 작업이 가능하다는 장점이 있다. 설정Build.gradleSpr..
2차 프로젝트를 진행하며 Redis가 동시성 처리 등 다방면에 활용될 수 있다는 것을 알게 되었다.나는 Redis를 활용해 대기 생성, 지연, 입장을 처리하고 싶었으나 Redis의 이해가 선행되어야 했다. 그래서 Redis의 기본 개념인 데이터 타입과 해당 데이터 타입이 어디에 활용되는지부터 살펴보고자 하였다. 위 두 가지를 살펴보기에 앞서, Redis가 무엇인지 간략하게 살펴보자.Redis(Remote Dictionary Server)Redis는 다수의 서버가 공유하는 해시 테이블이다.해시맵처럼 key-value 형태로 되어 있다.특징인메모리에 모든 데이터를 저장한다.기본적으로 휘발성 데이터지만 영속성 옵션(RDB, AOF)을 통해 데이터를 영속적으로 관리할 수 있다.단일 스레드에서 모든 작업을 수행하..
도입 API 명세서는 각 API가 어떻게 동작하는지 설명하는 문서로, 프론트엔드와 서버 간 협업에서 필수적이다. 나는 기존 프로젝트들에서 명세서 작성 도구로 Swagger를 사용했었다. 그러다 최근에 Spring Rest Docs로도 API 명세서를 작성할 수 있음을 알게 되었다. Spring Rest Docs는 스프링 프레임워크에서 제공하는 API 문서 자동화 도구이다. Swagger VS Rest Docs Swagger와 Rest Docs는 각각 장단점이 존재한다. Swagger는 적용이 쉽고, 해당 문서에서 API 호출 테스트를 직접 해볼 수 있다. 그러나 프로덕션 코드에 Swagger 문서 관련 코드가 포함되어 가독성이 떨어진다. Rest Docs는 Swagger에 비해 적용이 어렵지만 프로덕션 ..
# 2023/5/15에 작성했던 글입니다.# 해당 인스턴스는 삭제한 상태입니다. EC2 인스턴스를 생성해보자우분투를 선택하였다.AMI는 프리티어 중에서 선택하였다. 인스턴스 유형은 따로 건들지 않았다. 키 페어는 인스턴스에 접속할 때 필요하다.새로운 키페어를 생성하거나 기존 키페어를 사용할 수 있는데 나는 새로 만들었다. 키 페어 이름만 입력하고, 나머지 설정은 건들지 않았다. 키페어 생성을 누르면 내가 생성한 키페어가 다운로드된다.키페어를 저장하고, 해당 경로를 기억하자.명령 프롬프트에서 해당 경로로 이동해 EC2 서버에 접속하게 된다. 새 보안 그룹을 생성해주자. 스토리지는 50GB로 설정하였다.용량이 부족하면 나중에 깃에서 프로젝트를 클론할 때 문제 생길 수 있다. (경험담) 보안 그룹 편집하기..
@MappedSuperClass는 공통 매핑 정보가 필요할 때 사용한다. 테이블에 매핑되지 않고, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할을 한다. 예를 들어 모든 엔티티에 생성 시간, 수정 시간이 들어간다고 해보자. 각 엔티티에 해당 필드를 추가한다면 코드 중복이 발생한다. 이때 부모 클래스를 선언하고 속성만 상속받아 사용할 수 있다. BaseEntity에 @MappedSuperClass를 선언 후 필드들을 넣고 다른 엔티티들이 상속받도록 하자. BaseEntity는 상속해주는 클래스라 단독으로 쓰지 않으므로 추상 클래스로 만드는 것이 좋다. 객체와 테이블의 필드명을 다르게 사용하고 싶다면 @Column의 name 속성을 사용하면 된다. @MappedSuperClass public a..
상속관계 매핑 정의 관계형 데이터베이스는 상속관계가 존재하지 않는다. 대신 DB의 슈퍼-서브타입 모델링 기법이 객체 상속 관계와 유사하기 때문에 매핑해서 쓸 수 있다. 한 마디로 상속 관계 매핑은 상속 관계와 슈퍼-서브 타입 관계를 매핑하는 것이다. 아래 그림처럼 음반, 영화, 책에서 공통적인 속성을 뽑아내어 물품을 만들 수 있다. 슈퍼-서브타입 논리 모델을 실제 물리 모델로 구현하는 방법은 총 3가지가 있다. 아래에서 하나씩 살펴보자. 조인 전략 조인으로 데이터를 정규화하여 구성하는 전략이다. 공통 속성인 name, price는 Item 테이블에 저장되고, 나머지 속성들은 각 테이블에 저장된다. 코드 각 엔티티를 생성해준다. Item엔티티는 상속해 주는 용도로만 쓰이므로 추상 클래스로 정의했다. @Di..
다대다 매핑 관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다. 중간에 테이블을 추가해서 일대다, 다대일 관계로 풀어내야 한다. 이와 달리 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계를 표현할 수 있다. Member는 productList를 가지고, Product는 memberList를 가진다. 다대다는 @ManyToMany를 사용하고, @JoinTable로 연결 테이블을 지정한다. 양쪽 테이블의 PK가 FK가 된다. //Member.java @ManyToMany @JoinTable(name = "MEMBER_PRODUCT") private List products = new ArrayList(); 다대다 매핑도 단방향, 양방향 매핑이 모두 가능하다. 양방향 매핑을 하고 싶..
일대일 관계 일대일 관계는 대칭적이다. 따라서 주 테이블이나 대상 테이블 중에 외래키를 넣을 곳을 선택할 수 있다. 예를 들어, 주테이블인 Member에 외래키를 넣을 수 있고, 대상 테이블인 Team에 외래키를 넣을 수 있다. 외래키에 데이터베이스 유니크 제약 조건을 추가해야 한다. 유니크의 유무가 일대일과 다대일을 구분 짓는 차이점이 된다. 일대일 - 주 테이블에 외래키 단방향 Member를 주 테이블로 설정했기 때문에 Member에 외래키를 놓았다. Locker 테이블을 주 테이블로 정할 수도 있다. 그때는 Locker 테이블에 MEMBER_ID(FK, UNI)를 추가해야 한다 다대일 단방향 매핑과 유사하며, 어노테이션 차이만 있다. 아래는 주 테이블에 일대일 단방향을 설정하는 코드이다. //Mem..
hyun_12
hyunDev