전체 글 38

[Spring] could not initialize proxy [...] - no Session 오류

#1. Event @DisplayName("사용자가 리뷰 좋아요를 누른다.") @Test void likeReview() { //given User user = userRepository.save(createUser("1")); Book book = bookRepository.save(createBook()); Review review = reviewRepository.save(createReview(user, book)); //when reviewLikeService.createReviewLike(user.getId(), review.getId()); //then List reviewLike = reviewLikeRepository.findAll(); assertThat(reviewLike).hasSi..

Spring 2024.04.02

QueryDSL 동적 정렬 쿼리 OrderSpecifier 구현하기

#1. Event#2. Feature@Repositorypublic interface ReviewRepository extends JpaRepository, ReviewRepositoryCustom { // 내용 생략 ...}@RequiredArgsConstructorpublic class ReviewRepositoryImpl implements ReviewRepositoryCustom { private final JPAQueryFactory queryFactory; // 내용 생략 ... } 상세한 구현을 위해 Custom, Impl 클래스를 생성했고 필요한 상속 관계를 추가했다.Impl은 QueryDSL로 구현하기 때문에 JPAQueryFactory가 필요하다. public e..

Spring 2024.03.28

Spring Security 없이 소셜 로그인 구현하기

들어가기 전 ✔ 기록을 통한 리마인드를 위해 남기는 글입니다. 기존 프로젝트에 구현하는 것이기 때문에 모든 코드보다는 추가되는 코드 위주로 다루겠습니다. 🤔 Spring Security 없이 소셜 로그인을 구현하는 이유 처음에는 시큐리티에 내장된 OAuth 2.0을 통해 구현하려고 했습니다. 하지만 구현을 하다 보니 커스터마이징에 한계가 존재했고, 스프링 시큐리티에 대한 의존성이 높았습니다. 그래서 직접 소셜 서버와 통신해서 코드와 토큰을 발급받는 로직을 구현하는 것으로 결정했습니다. 🐘 build.gradle // (1) implementation 'org.springframework.boot:spring-boot-starter-webflux' // (2) annotationProcessor "org...

Spring 2024.03.17

[MySQL] Order By, Group By, Distinct

MySQL 서버에 요청된 쿼리는 결과는 동일하지만 과정은 매우 다양하다. 여러 방법 중에서 최적의 방법은 옵티마이저가 담당한다. 대부분의 DBMS에서는 옵티마이저가 최적의 실행 계획을 수립하는 작업을 한다. 1. 쿼리 실행 절차와 옵티마이저의 종류 1-1. 쿼리 실행 절차 요청된 SQL 문장을 잘개 쪼개서 MySQL 서버가 이해할 수 있는 수준으로 분리(파스 트리)한다. 파싱 정보(파스 트리)를 확인하면서 어떤 테이블부터 어떤 인덱스로 테이블을 읽을지 선택한다. 두 번째 단계에서 결정된 읽기 순서나 인덱스를 활용해서 스토리지로부터 데이터를 가져온다. 첫 번째 단계를 SQL 파싱이라고 하며, SQL 파서라는 모듈로 처리한다. 문법이 잘못됐다면 여기서 걸러지고 아니라면 SQL 파스 트리를 생성한다. MySQ..

데이터베이스 2024.01.30

[MySQL] 전문 검색, 클러스터링, 유니크 인덱스

1. 전문 검색 인덱스 B-Tree 인덱스 같은 경우는 전체 일치나 좌측 일부 일치와 같은 검색만 가능하다. 전문 검색 인덱스는 문서 전체를 인덱스화해서 특정 키워드가 포함된 내용을 검색할 수 있다. 사용자에게 빠른 검색을 제공하기 위해 키워드로 인덱스를 구축한다. 1-1. 어근 분석 알고리즘 불용어 처리 : 별 가치가 없는 단어를 모두 필터링해서 제거하는 작업 불용어는 개수 자체가 많지 않아서 상수로 정의해서 사용한다. 사용자가 불용어를 직접 설정해서 적용할 수 있다. 어근 분석 : 검색어로 선정된 단어의 뿌리인 원형을 찾는 작업 형태소 분석 프로그램 MeCab이나 MongoDB에서 사용되는 Snowball이라는 오픈소스로 어근 분석을 한다. MeCab 같은 경우는 일본어 전용이기 때문에 한글에 맞게 ..

데이터베이스 2024.01.23

[MySQL] 인덱스와 B-Tree

일단 인덱스가 뭘까? 인덱스는 데이터베이스 쿼리의 성능을 언급하면서 빼놓을 수 없는 부분이다. 백엔드 개발자한테 중요한 개념이라고 생각한다. 각 인덱스의 특성과 차이는 상당히 중요하며, 데이터베이스 모델링을 할 때도 중요한 요소다. 이번 글에서는 B-Tree에 대해서 정리하고자 한다. 일단 인덱스에 관련된 설명을 위해서 디스크 읽기 방식에 대해 알아야한다. 디스크 읽기 방식 컴퓨터의 CPU나 메모리처럼 전기적 특성을 띤 장치는 매우 빠르게 발전했지만 데이터를 저장하는 디스크 같은 기계식 장치는 제한적으로 발전했다. 원판에 의존하는 하드 디스크보다 SSD 드라이브가 많이 활용되고 있지만, 여전히 컴퓨터에서 가장 느린 장치이다. 그래서 데이터베이스의 쿼리 성능은 튜닝을 통해 디스크 I/O를 줄이느냐가 관건이..

데이터베이스 2024.01.21

[MySQL] 트랜잭션, 잠금, 격리 수준이 뭘까 ?

트랜잭션: 데이터의 정합성을 보장한다. 잠금: 동시성을 제어한다. 격리 수준: 트랜잭션 간의 작업 내용을 어떻게 공유하고, 차단할 것인지 결정하는 레벨을 의미한다. 세가지 다 MySQL 동시성에 관련되어 있다. 각각 더 자세하게 살펴보자. 01 트랜잭션 스토리지 엔진: 서버 엔진이 필요한 물리적인 데이터를 가져오는 장치 일단 먼저 트랜잭션이 얼마나 편한 기능을 제공하는지 알아보기 위해 MyISAM과 InnoDB 스토리지 엔진을 비교해보자. 트랜잭션의 대표적인 기능 COMMIT: 작업이 정상적으로 되어서 트랜잭션을 종료하고 데이터가 업데이트 된다. ROLLBACK: 실행된 트랜잭션 작업에 문제가 발생해서 작업 이전의 상태로 되돌린다. 트랜잭션 왜 사용할까 ? MyISAM은 트랜잭션을 지원하지 않지만 In..

데이터베이스 2024.01.08