JAVA 17, Spring Boot 3.0.2, Gradle, MySQL, Redis로 만드는
'오늘의코딩' 메일링 서비스
데이터베이스 연결방식
이번 프로젝트의 큰 목표는 Redis와 MySQL을 둘 다 사용하는 부분이기 때문에 Redis Cache를 Write-Through 방식으로 사용하기로 했다. 프로젝트에서 두 데이터베이스에 업데이트를 한다고 해도 그 비중이 크지 않고, 예상되는 타겟층도 크지 않아서 성능상에 무리가 없을 것으로 예측하고 진행했다.
서비스 리스트를 한 번에 가져와서 Redis Cache를 이용하는게 RDB를 거치지 않아도 빠르게 접근가능한 부분을 많이 만들고 싶었고, 그 외에도 Cache에 두지 않고 RDB에 접근해야 하는 부분들도 있었기에 Write-Through 방식이 적합했다.
MySQL, Redis Connection Test
MySQL과 Redis 연결 test를 진행했다. 둘 다 잘 연결이 되어 있는지 확인하기 위해서 다음 코드들을 사용했고, 나와 같은 고민이 있던 사람들에게 도움이 되었으면 좋겠다.
build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
runtimeOnly 'com.mysql:mysql-connector-j'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
MySQL Connection Test
package com.toco.trialService.databaseTest;
import org.junit.jupiter.api.*;
import java.sql.Connection;
import java.sql.DriverManager;
public class DatabaseConnectionTest {
private static final String URL = "jdbc:mysql://127.0.0.1:3306/world";
private static final String User = "root";
private static final String Password = "0000"; // 임의의 패스워드
@Test
public void rdbConnectionTest() {
try(Connection conn = DriverManager.getConnection(URL, User, Password)) {
System.out.println(conn);
// com.mysql.cj.jdbc.ConnectionImpl@3697186
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
Redis Connection Test
package com.toco.trialService.databaseTest;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import org.junit.jupiter.api.*;
import static org.springframework.test.util.AssertionErrors.assertTrue;
public class RedisConnectionTest {
private RedisClient redisClient;
private StatefulRedisConnection<String, String> connection;
private RedisCommands<String, String> redisCommands;
@BeforeEach
public void beforeConnectDatabase(){
redisClient = RedisClient.create("redis://localhost:6379");
connection = redisClient.connect();
redisCommands = connection.sync();
}
@AfterEach
public void afterConnectDatabase(){
connection.close();
redisClient.shutdown();
}
@Test
public void inMemoryConnectionTest() {
assertTrue("Redis connection test failed", redisCommands.ping().equals("PONG"));
}
}
※
Lettuce version 3.0.5에서는 더 이상 DefaultClientResources 클래스를 사용하지 않고, 새 Redis 클라이언트 객체 생성으로 RedisClient를 사용한다. 생성시에는 위 코드와 같이 create([url])을 사용하고, 사용이 끝난 시점에서는 shutdown(); 처리를 해주자.
Redis Caching 전략에 따른 고찰
Caching 전략으로 이걸 사용하는게 맞을까?
프로젝트를 만들면서 이런 고민을 제일 많이 했던 것 같다.
Redis Caching을 어떻게 활용할 것인가에 대한 고민이 많았다. 현업과 서비스에 따라 방식이 달라져야겠지만, 지금 만들고자 하는 프로젝트는 동시성을 제공해야 하며 데이터 유실을 최대한 막고 싶었고 그래서 선택하게 된 방식이 Write-Through 였다.
하지만 Write-Around 방식도 있고, 이 경우에는 대용량 서비스 처리에서는 유실가능성을 고려해야한다. RDBMS Data가 최신이 아닐 수 있기 때문에 RDBMS Data를 in-memory 로 정기적으로 Pushing 처리해주는 방식을 같이 사용된다.
Caching 전략에 따라 불필요한 캐쉬 데이터를 가지고 있는 건 메모리 낭비로 이어질 수 있기 때문에 오히려 성능을 떨어뜨릴 수 있다.
따라서 적절한 TTL처리와 성능 개선에 필요한 주요데이터(UPDATE가 많이 발생하지 않는)만을 @RedisCache 처리해서 사용했다. 이번 프로젝트에서는 Program, ProgramDetail, Categories 처럼 update가 많지 않을 것으로 예상되는 항목만에만 적용했다.
'Project > 오늘의 코딩 서비스 프로그램' 카테고리의 다른 글
[오늘의코딩] Step6. 백엔드 - Swagger 적용 및 ERD 수정 (0) | 2023.03.08 |
---|---|
[오늘의코딩] Step5. 프론트엔드 - 메인페이지 Carousel 만들기 (0) | 2023.03.08 |
[오늘의코딩] Step4. 프론트엔드 - Thymeleaf Layout 설정하기 (0) | 2023.03.07 |
[오늘의코딩] Step2. 기획 - 프로젝트 설계와 구상 (0) | 2023.02.24 |
[오늘의코딩] Step1. 프로젝트의 시작 (0) | 2023.02.02 |
- filezila
- 개발도서
- IT 5분 잡학사전
- LifecycleException
- spring
- 북클럽
- AWS
- git연동
- SQLD
- java
- 오늘의코딩
- gradle
- 호스팅영역
- 노마드코더
- ubuntu
- jdbc
- putty
- gradle build
- 웹페이지만들기
- 기술블로그
- 노개북
- 독서후기
- 실용주의프로그래머
- 배포
- JIRA
- intellij
- 정보처리기사
- 정보처리기사 실기
- EC2
- 정보처리기사 필기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |