Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ out/

/docker/localstack/
/grafana-data/**

/sample_data/**
!/sample_data/.gitkeep
13 changes: 13 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 베이스 이미지
FROM openjdk:17-jdk-alpine

# 작업 디렉토리 설정
WORKDIR /app

EXPOSE 8080

# JAR 파일 복사
COPY /build/libs/mywork-be-0.0.1-SNAPSHOT.jar app.jar

# 프로파일 설정하여 실행
ENTRYPOINT ["java", "-jar", "app.jar", "--spring.profiles.active=local"]
23 changes: 21 additions & 2 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
version: '3.8'
services:
mywork-application:
build:
context: ../
dockerfile: docker/Dockerfile
container_name: mywork-application
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=local
deploy:
resources:
limits:
cpus: "1.00"
memory: 1GB
networks:
mywork-network:
ipv4_address: 172.10.0.14
depends_on:
- mysql
mysql:
container_name: 'mywork_rdb'
image: mysql:8.0
Expand Down Expand Up @@ -44,13 +63,12 @@ services:
- "/var/run/docker.sock:/var/run/docker.sock"
- "./init-scripts:/etc/localstack/init/ready."
grafana:
image: grafana/grafana:latest
image: grafana/grafana:11.5.6
container_name: grafana
ports:
- "3000:3000"
volumes:
- ../grafana-data:/var/lib/grafana
- ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
Expand All @@ -75,6 +93,7 @@ services:
ipv4_address: 172.10.0.7
depends_on:
- mysqld-exporter
- mywork-application
mysqld-exporter:
image: prom/mysqld-exporter:latest
ports:
Expand Down
8 changes: 8 additions & 0 deletions docker/prometheus/config/prometheus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ scrape_configs:
static_configs:
- targets:
- 172.10.0.5:9104
- job_name: mywork-instance01
honor_timestamps: true
scrape_interval: 10s
scrape_timeout: 10s
metrics_path: /actuator/prometheus
scheme: http
static_configs:
- targets: ['172.10.0.14:8080']
11 changes: 11 additions & 0 deletions k6/api/MemberApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import http from 'k6/http';
import baseUrl from '../base/baseUrl.js';

export function loginMember(member) {
let headers = {
'Content-Type': 'application/json'
};

const url = `${baseUrl}/api/login`;
return http.post(url, JSON.stringify(member), { headers: headers });
}
3 changes: 3 additions & 0 deletions k6/base/BaseUrl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const baseUrl = "http://localhost:8080";

export default baseUrl;
20 changes: 20 additions & 0 deletions k6/base/UserSampleReader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// CSV 파일을 읽고 파싱하는 함수
export function loadMemberFromCSV() {
const file = open('../../sample_data/member.csv'); // CSV 파일을 읽기
const lines = file.split('\n'); // 각 줄을 구분자로 나누기
const data = [];

// 첫 번째 줄은 헤더이므로 건너뛰고 나머지 데이터 처리
for (let i = 1; i < lines.length; i++) {
const line = lines[i].trim(); // 빈 줄을 처리하기 위해 trim() 사용
if (line) {
const fields = line.split(','); // 쉼표로 구분된 항목을 배열로 변환
data.push({
id: fields[0],
email: fields[3],
password: fields[8]
});
}
}
return data; // 데이터를 반환
}
29 changes: 29 additions & 0 deletions k6/member/MemberLoadTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { check, group, sleep } from 'k6';
import { loginMember } from '../api/MemberApi.js';
import {loadMemberFromCSV} from "../base/UserSampleReader.js";

export let options = {
rps: 10,
// iterations: 100,
vus: 100,
duration: '3m',
}

const memberLoginData = loadMemberFromCSV()

export default function() {

group('Member Login Load Test', function() {
const userIndex = __VU - 1;
const user = memberLoginData[userIndex];

let response = loginMember({
email: user.email,
password: user.password
});

check(response, {
'[member login] status code 200': (r) => r.status === 200
})
})
}
14 changes: 14 additions & 0 deletions k6/member/MemberSmokeTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import http from 'k6/http';
import {check} from 'k6';
import { loginMember } from '../api/MemberApi.js';

const member = {
email: 'admin@example.com',
password: 'password1234'
}

export default function () {
let response = loginMember(member);
check(response, { 'status code 200': (r) => r.status === 200 });

}
Empty file added sample_data/.gitkeep
Empty file.
2 changes: 1 addition & 1 deletion src/main/java/kr/mywork/common/aws/S3Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;

@Profile("default")
@Profile("default | local")
@Configuration
public class S3Config {

Expand Down
85 changes: 85 additions & 0 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
spring:
application:
name: mywork-be
jpa:
show-sql: true
open-in-view: false
hibernate:
ddl-auto: create-drop
defer-datasource-initialization: true
sql:
init:
mode: always
datasource:
url: jdbc:mysql://mywork_rdb:3306/mywork_db
username: root
password: mywork2503
driver-class-name: com.mysql.cj.jdbc.Driver
messages:
basename: messages/messages
fallback-to-system-locale: false
cloud:
aws:
s3:
region: us-east-1 # TODO 운영용은 별도로 선언
credentials:
access-key: test # TODO 운영용은 별도로 선언
secret-key: test # TODO 운영용은 별도로 선언
output:
ansi:
enabled: never
management:
endpoints:
web:
exposure:
include: "metrics,health,prometheus" # 혹은 "*"로 모든 엔드포인트 오픈 가능
company:
page:
size: 10
upload:
duration: 3m
member:
page:
size: 10
post:
page:
size: 10
upload:
bucket-name: mywork-upload-bucket
duration: 3m
endpoint: http://localstack:4566
attachment:
max-count: 3
issued-id:
created-limit-hour: 24
delete:
cron: 0 0 4 * * *
project:
page:
size: 10
review:
page:
size: 10
dashboard:
page:
size: 5
activityLog:
page:
size: 10
notification:
page:
size: 10
jwt:
access-token:
private-key: 126cab8a5d9087a27be4e2a0599682e2bab38e80201d1befa2dd9d55ecbdeac58bab0c84301ad9f9f8a71836825e5a7214e7a9fb17a8578418de6cfe9a15cbc7
expiration: 3600000
refresh-token:
private-key: 408a96ae4affd8bce03d11385d9a8dfbd4c0cbc9c5a83675864192dbb50eaa965acf2ef84e60bb1a38798f612caed4f383466a4be14957bf87370b62be71c2e1
expiration: 86400000

server:
servlet:
encoding:
charset: UTF-8
enabled: true
force: true
Loading