728x90
글을 쓰기 전에 항상 고민합니다,, 오늘은 어떤 잔망루피를 데려올까,,🥸
오늘은 R2DBC에서 쿼리를 작성하는 2가지 방법을 작성할 예정이기에 잔망루피 2명이 있는 짤을 데려왔습니다,,
잔망 루피 2명,, (+ 뒷모습의 잔망루피는 덤,,)과 함께하는 Custom Query를 정리해보고자 합니다,,
1. gradle.build
외부 라이브러리를 쓰기 위해 종속성을 추가해줍니다.
dependencies{
// r2dbc 설정
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc' // JDBC 대신 비동기 방식으로 DB와 통신할 수 있도록 지원
implementation 'io.asyncer:r2dbc-mysql:1.0.2' // R2DBC를 이용해 MySQL과 연결하기 위한 드라이버
// 비동기/리액티브 방식으로 MySQL과 데이터를 주고받을 수 있도록 하는 설정
// 리액티브(Reactive) 방식: 비동기(Asynchronous) + 논블로킹(Non-blocking) 프로그래밍 모델
}
2. application.yml
DB 설정을 추가해줍니다.
사용 DB: MySQL🐬
spring:
r2dbc:
url: r2dbc:mysql://localhost:3307/database_name
username: username
password: passworad
3. R2dbcConfig.java
R2DBC 설정 파일을 만들어줍니다.
@Component
@RequiredArgsConstructor
@Slf4j
@EnableR2dbcRepositories // 리액티브 리포지토리(ReactiveCrudRepository 등)를 자동으로 스캔하고, R2DBC를 통해 사용할 수 있도록 설정
@EnableR2dbcAuditing // R2DBC 엔터티의 자동 감사(Auditing) 기능을 활성화, createdAt, updatedAt 같은 값을 자동으로 입력
public class R2dbcConfig {
private final DatabaseClient databaseClient;
// MySQL 연결 시, 객체 생성은 하지만 Connection까지는 보장하지 않음
// application.properties 파일에서 비밀번호 틀려도 Spring 연결 O
}
4-1. Custom Repository 만들기 - @Query 버전
public interface UserR2dbcRepository extends ReactiveCrudRepository<User, Long> {
@Modifying
// @Query: 읽기 전용(SELECT 쿼리)으로 동작
// CREATE, UPDATE, DELETE 같은 데이터를 변경하는 쿼리를 실행하려면 @Modifying을 추가
@Query("DELETE FROM users WHERE name = :name")
Mono<Integer> deleteByName(String name);
}
4-2. Custom Repository 만들기 - DatabaseClient
@Repository
@RequiredArgsConstructor
public class PostR2dbcCustomRepositoryImpl implements PostR2dbcCustomRepository {
private final DatabaseClient databaseClient;
@Override
public Flux<Post> findAllByUserId(Long userId) {
String sql = """
SELECT p.id as pid, p.user_id as userId, p.title, p.content, p.created_at as pcreatedAt, p.updated_at as pupdatedAt,
u.id as uid, u.name, u.email, u.created_at as ucreatedAt, u.updated_at as uupdatedAt
FROM posts p
LEFT JOIN users u ON p.user_id = u.id
WHERE p.user_id = :userId
""";
return databaseClient.sql(sql)
.bind("userId", userId)
// :userId에 매핑 -> 오류나는 부분 IntelliJ 문제
.fetch()
// fetch().all()을 쓰면 Flux, fetch().one()을 쓰면 Mono를 반환
.all()
.map(row -> Post.builder()
.id((Long) row.get("pid"))
.userId((Long) row.get("userId"))
.title((String) row.get("title"))
.content((String) row.get("content"))
.user(User.builder()
.id((Long) row.get("uid"))
.name((String) row.get("name"))
.email((String) row.get("email"))
.createdAt(((ZonedDateTime) row.get("ucreatedAt")).toLocalDateTime())
.updatedAt(((ZonedDateTime) row.get("uupdatedAt")).toLocalDateTime())
.build())
.createdAt(((ZonedDateTime) row.get("pcreatedAt")).toLocalDateTime())
.updatedAt(((ZonedDateTime) row.get("pupdatedAt")).toLocalDateTime())
.build());
}
}
5. Custom Repository별 장단점 정리
비교 항목 | ReactiveCrudRepository | DatabaseClient |
특징 | ReactiveCrudRepository 기본 메서드 (save, findById, deleteById 등) 사용 가능 |
SQL 직접 작성 |
유연성 | @Query로 커스텀 쿼리 가능 복잡한 JOIN 처리 어려움 |
복잡한 JOIN 및 다양한 SQL 작성 가능 |
활용 | 기본적인 CRUD 및 간단한 조건 검색에 적합 | 직접 최적화가 가능하므로 복잡한 비즈니스 로직이 필요한 경우 적합 |
동적 쿼리 | 불가능(동적 쿼리 작성 시, Querydsl 필요) | 가능 |
📑
참고 자료
Chat GPT
https://fastcampus.co.kr/dev_online_traffic_data
728x90
'MinimiProject > 아이돌 티켓팅 접속자 대기열 시스템' 카테고리의 다른 글
[대기열 시스템] MVC vs Webflux - JMeter를 이용한 부하테스트 (1) | 2025.02.02 |
---|---|
[대기열 시스템] Redis와 Replication (0) | 2025.01.28 |
[대기열 시스템] Docker Compose로 Grafana와 Prometheus로 모니터링 시스템 구축하기 (0) | 2025.01.26 |
[대기열 시스템] RedisTemplate, RedisHash, @Cacheable (1) | 2025.01.25 |
[대기열 시스템] HTTP load testing tool, Vegeta 설치(Window) (0) | 2025.01.21 |