Skip to content

Commit f225f27

Browse files
authored
Merge pull request #82 from ces0135-hub/refactor/ElasticSearch
Feat: MySQL VS ElasticSearch Performance Test Comparison - 기존 코드 fork 후 이동
2 parents b1dc5f7 + 4f0da44 commit f225f27

31 files changed

+1913
-115
lines changed

build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ dependencies {
104104
// AOP
105105
implementation("org.springframework.boot:spring-boot-starter-aop")
106106

107+
// JMX 및 시스템 모니터링
108+
implementation("org.springframework.boot:spring-boot-starter-actuator")
109+
implementation("io.micrometer:micrometer-core")
110+
107111
}
108112

109113
tasks.withType<Test> {
@@ -134,3 +138,7 @@ tasks.withType<JavaCompile> {
134138
tasks.withType<Test> {
135139
systemProperty("file.encoding", "UTF-8")
136140
}
141+
142+
tasks.named<org.springframework.boot.gradle.tasks.run.BootRun>("bootRun") {
143+
mainClass.set("org.com.stocknote.StockNoteApplication")
144+
}

docker-compose.yml

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,71 @@
1-
version: '3.4'
1+
version: '3.8'
22

33
services:
4-
influxdb:
5-
image: influxdb:1.8
4+
# Redis
5+
redis:
6+
image: redis:7-alpine
7+
container_name: stocknote-redis
8+
restart: always
69
ports:
7-
- "8086:8086"
10+
- "6379:6379"
11+
command: >
12+
redis-server
13+
--appendonly yes
14+
--maxmemory 256mb
15+
--maxmemory-policy allkeys-lru
16+
volumes:
17+
- redis_data:/data
18+
healthcheck:
19+
test: ["CMD", "redis-cli", "ping"]
20+
interval: 10s
21+
timeout: 5s
22+
retries: 3
23+
24+
# ElasticSearch
25+
elasticsearch:
26+
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
27+
container_name: stocknote-elasticsearch
28+
restart: always
829
environment:
9-
- INFLUXDB_HTTP_AUTH_ENABLED=false
10-
- INFLUXDB_DB=k6
30+
- node.name=stocknote-es
31+
- cluster.name=stocknote-cluster
32+
- discovery.type=single-node
33+
- bootstrap.memory_lock=true
34+
- "ES_JAVA_OPTS=-Xms1g -Xmx1g"
35+
- xpack.security.enabled=false
36+
- xpack.security.enrollment.enabled=false
37+
ulimits:
38+
memlock:
39+
soft: -1
40+
hard: -1
41+
ports:
42+
- "9200:9200"
43+
- "9300:9300"
44+
volumes:
45+
- es_data:/usr/share/elasticsearch/data
46+
healthcheck:
47+
test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"]
48+
interval: 30s
49+
timeout: 10s
50+
retries: 5
1151

12-
grafana:
13-
image: grafana/grafana:latest
52+
# Kibana (선택사항 - ElasticSearch 관리도구)
53+
kibana:
54+
image: docker.elastic.co/kibana/kibana:8.12.0
55+
container_name: stocknote-kibana
56+
restart: always
1457
ports:
15-
- "3000:3000"
58+
- "5601:5601"
1659
environment:
17-
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
18-
- GF_AUTH_ANONYMOUS_ENABLED=true
19-
- GF_AUTH_BASIC_ENABLED=false
20-
volumes:
21-
- ./grafana:/etc/grafana/provisioning/
60+
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
61+
depends_on:
62+
elasticsearch:
63+
condition: service_healthy
64+
profiles:
65+
- monitoring # 필요할 때만 실행
66+
67+
volumes:
68+
redis_data:
69+
driver: local
70+
es_data:
71+
driver: local

src/main/java/org/com/stocknote/StockNoteApplication.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
56
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
7+
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
68
import org.springframework.scheduling.annotation.EnableScheduling;
79

810
@SpringBootApplication
911
@EnableJpaAuditing
1012
@EnableScheduling
13+
@EnableElasticsearchRepositories(basePackages = "org.com.stocknote.domain.searchDoc.repository")
14+
@EnableJpaRepositories(basePackages = "org.com.stocknote.domain")
1115
public class StockNoteApplication {
1216

13-
public static void main (String[] args) {
17+
public static void main(String[] args) {
1418
SpringApplication.run(StockNoteApplication.class, args);
1519
}
1620
}
17-
18-

src/main/java/org/com/stocknote/config/RedisConfig.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.fasterxml.jackson.databind.ObjectMapper;
44
import com.fasterxml.jackson.databind.SerializationFeature;
55
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
6-
import org.springframework.beans.factory.annotation.Value;
6+
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
77
import org.springframework.context.annotation.Bean;
88
import org.springframework.context.annotation.Configuration;
99
import org.springframework.data.redis.connection.RedisConnectionFactory;
@@ -16,30 +16,23 @@
1616

1717
@Configuration
1818
public class RedisConfig {
19-
@Value("${spring.data.redis.host}")
20-
private String redisHost;
21-
@Value("${spring.data.redis.port}")
22-
private int redisPort;
19+
20+
private final RedisProperties redisProperties;
21+
22+
public RedisConfig(RedisProperties redisProperties) {
23+
this.redisProperties = redisProperties;
24+
}
2325

2426
@Bean
2527
public RedisConnectionFactory redisConnectionFactory() {
26-
return new LettuceConnectionFactory(redisHost, redisPort);
28+
return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
2729
}
2830

2931
@Bean
3032
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
3133
return new StringRedisTemplate(connectionFactory);
3234
}
3335

34-
@Bean
35-
public RedisTemplate<Object, Object> redisObjectTemplate() {
36-
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
37-
redisTemplate.setConnectionFactory(redisConnectionFactory());
38-
redisTemplate.setKeySerializer(new StringRedisSerializer());
39-
redisTemplate.setValueSerializer(new StringRedisSerializer());
40-
return redisTemplate;
41-
}
42-
4336
@Bean
4437
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
4538
RedisTemplate<String, Object> template = new RedisTemplate<>();

src/main/java/org/com/stocknote/config/WebConfig.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
public class WebConfig implements WebMvcConfigurer {
99
@Override
1010
public void addCorsMappings(CorsRegistry registry) {
11-
1211
registry.addMapping("/**").allowedOrigins(AppConfig.getSiteFrontUrl())
1312
.allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")
1413
.allowedHeaders("*").allowCredentials(true);
1514
}
16-
}
15+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.com.stocknote.config.elasticsearch;
2+
3+
import org.springframework.context.annotation.Configuration;
4+
5+
@Configuration
6+
public class ElasticsearchConfig {
7+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.com.stocknote.config.jpa;
2+
3+
import org.springframework.context.annotation.Configuration;
4+
5+
@Configuration
6+
//@EnableJpaRepositories(
7+
// basePackages = {
8+
// "org.com.stocknote.domain.post.repository",
9+
// "org.com.stocknote.domain.comment.repository",
10+
// "org.com.stocknote.domain.member.repository",
11+
// "org.com.stocknote.domain.portfolio",
12+
// "org.com.stocknote.domain.keyword.repository",
13+
// "org.com.stocknote.domain.stock.repository",
14+
// "org.com.stocknote.domain.like.repository",
15+
// "org.com.stocknote.domain.notification.repository"
16+
// }
17+
//)
18+
public class JpaConfig {
19+
}

src/main/java/org/com/stocknote/domain/keyword/repository/KeywordRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
public interface KeywordRepository extends JpaRepository<Keyword, Long> {
1010
void deleteByMemberId(Long id);
1111

12-
List<org.com.stocknote.domain.keyword.entity.Keyword> findByMemberId(Long id);
12+
List<Keyword> findByMemberId(Long id);
1313

1414
List<Keyword> findAllByPostCategory(PostCategory category);
1515
}

src/main/java/org/com/stocknote/domain/post/repository/PostRepository.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@
1414

1515
@Repository
1616
public interface PostRepository extends JpaRepository<Post, Long> {
17+
// PerformanceTestService에서 사용하는 메서드 추가
18+
@Query("SELECT DISTINCT p FROM Post p " +
19+
"WHERE (p.title LIKE %:title% OR p.body LIKE %:body%) " +
20+
"AND p.deletedAt IS NULL " +
21+
"ORDER BY p.createdAt DESC")
22+
Page<Post> findByTitleContainingOrBodyContaining(
23+
@Param("title") String title,
24+
@Param("body") String body,
25+
Pageable pageable
26+
);
27+
28+
// 또는 Spring Data JPA 자동 메서드 사용
29+
Page<Post> findByTitleContainingOrBodyContainingAndDeletedAtIsNull(
30+
String title, String body, Pageable pageable
31+
);
32+
1733
@Query("SELECT DISTINCT p FROM Post p " +
1834
"LEFT JOIN FETCH p.member m " +
1935
"LEFT JOIN FETCH p.comments c " +

src/main/java/org/com/stocknote/domain/post/repository/PostSearchRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@
1010
@Repository
1111
public interface PostSearchRepository {
1212
Page<Post> search(PostSearchConditionDto condition, Pageable pageable);
13+
14+
1315
}

0 commit comments

Comments
 (0)