Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a18adf8
feat: 모듈 분리를 위한 설정 파일 추가 및 수정(websocket 모듈용 application.yml, build.gr…
waitAmhee Nov 10, 2025
29f58bf
refactor: 기존의 코드 infra 모듈에서 websocket 모듈로 이동
waitAmhee Nov 10, 2025
10cb821
feat : LiveStockPriceWebSocketService 클래스 분리
waitAmhee Nov 10, 2025
2f469b5
refactor: 필요없는 코드 삭제 및 수정
waitAmhee Nov 10, 2025
cf61267
refactor: 기존에는 같은 서버 내에서만 이벤트를 발행/구독 -> Redis Pub/Sub을 통해 서버 간 통신이 가능…
waitAmhee Nov 10, 2025
86e9d37
refactor: 서버-클라, 증권사-서버 패키지 분리
waitAmhee Nov 10, 2025
f874696
refactor: 로그정리 및 서버-클라, 증권사-서버 패키지 분리 이후 -> 자동 패키지 리팩토링된 클래스
waitAmhee Nov 10, 2025
3da425e
fix: predestroy 실행 전에 redis가 닫혀버려서 redisTemplate 접근 중 에러 발생 -> Redis …
waitAmhee Nov 10, 2025
1598640
feature: websocket 용 build.gradle파일 추가
waitAmhee Nov 10, 2025
987fc74
refactor: DockerFile 이름 변경
waitAmhee Nov 10, 2025
29e6ade
fix: ecr repository를 fintory로 통일, 태그로 구분
waitAmhee Nov 10, 2025
2947c97
fix: ecr repository를 fintory-child로 통일
waitAmhee Nov 10, 2025
13705a0
fix: application.yml -> 프로필명 통일
waitAmhee Nov 10, 2025
307d8dd
refactor: 필요없는 코드 삭제
waitAmhee Nov 10, 2025
c9be4ba
fix : EC2 간 Bean 의존성 분리 (Service/Repository 직접 참조 제거)
waitAmhee Nov 10, 2025
7ce27f3
fix : child 모듈에서 websocket 모듈 삭제
waitAmhee Nov 11, 2025
9abb802
fix : appcliation.yml 변수 활용 방식 변경
waitAmhee Nov 11, 2025
7e989e2
fix : 들여쓰기 에러 수정
waitAmhee Nov 11, 2025
9c091df
fix : 빈 의존성 수정
waitAmhee Nov 11, 2025
3743bc7
fix : WebSocket 종료 시 Redis 연결 에러 해결
waitAmhee Nov 11, 2025
58fb44c
fix : @EnableJpaAuditing 추가
waitAmhee Nov 11, 2025
eb7fa26
fix : actuator 의존성 추가 + 토큰 발급 주기 23시간 -> 8시간으로 변경
waitAmhee Nov 12, 2025
393e3ab
fix : SecurityConfig 추가 -> 그라파나 대시보드 추가를 위해서.
waitAmhee Nov 12, 2025
0d613a5
fix : dependson 제거
waitAmhee Nov 13, 2025
f3b7092
fix : redis replica 설정 해제
waitAmhee Nov 14, 2025
3b381d5
fix : redis replica 설정 추가(테스트)
waitAmhee Nov 14, 2025
978d9e2
fix : websocket stomp 설정 옮김
waitAmhee Nov 16, 2025
2c63ba5
fix : app-child에서 websocket 모듈 참조 x
waitAmhee Nov 16, 2025
98ce9dd
refactor: 사용하지 않는 코드 삭제
waitAmhee Nov 16, 2025
5aaddec
refactor: webflux 의존성 설정
waitAmhee Nov 19, 2025
525fdbe
refactor: 아웃바운드 증권사 WebSocket 클라이언트를 WebFlux Reactor로 전환
waitAmhee Nov 19, 2025
107ede5
refactor: WebSocket을 SSE + WebFlux로 전환하여 단방향 스트리밍 + 기존의 metric 수집 방식 …
waitAmhee Nov 19, 2025
c8b9e51
refactor: DB 증권 최대 분당 횟수 제한 해결을 위해 delayElements 추가
waitAmhee Nov 19, 2025
dc36c59
refactor: sentTimestamp 추가 (테스트용)
waitAmhee Nov 21, 2025
6229bae
refactor: 삭제했던 priceChange 추가(중복 체크용)
waitAmhee Nov 21, 2025
1309e7a
refactor: sentTimestamp 제거
waitAmhee Nov 21, 2025
8dc8ffb
refactor: 테스트를 위해 중복 stock 데이터 필터링 로직 삭제
waitAmhee Nov 21, 2025
2e52ca1
refactor: 중복 messageSent 해결
waitAmhee Nov 21, 2025
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
99 changes: 99 additions & 0 deletions .github/workflows/deploy-websocket.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Fintory Websocket Module CI/CD
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]

env:
AWS_REGION: ap-northeast-2

jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'

- name: Grant permission to gradlew
run: chmod +x ./gradlew

- name: Cache Gradle
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build and push websocket
run: |
./gradlew :websocket:clean build
docker build -t websocket:latest ./websocket
docker tag websocket:latest ${{ steps.login-ecr.outputs.registry }}/fintory-child:websocket-latest
docker push ${{ steps.login-ecr.outputs.registry }}/fintory-child:websocket-latest

deploy-websocket:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Deploy fintory-websocket to EC2
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.FINTORY_WEBSOCKET_HOST }}
username: ubuntu
key: ${{ secrets.EC2_WEBSOCKET_SSH_KEY }}
script: |
export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}
export RDS_URL=${{ secrets.RDS_URL }}
export RDS_USERNAME=${{ secrets.RDS_USERNAME }}
export RDS_PASSWORD=${{ secrets.RDS_PASSWORD }}
export AWS_REDIS_HOST=${{ secrets.FINTORY_CHILD_PRIVATE_HOST }}
export AWS_REDIS_PASSWORD=${{ secrets.AWS_REDIS_PASSWORD }}
export HANTU_APPKEY=${{ secrets.HANTU_APPKEY}}
export HANTU_APPSECRET=${{ secrets.HANTU_APPSECRET}}
export DB_APPKEY=${{ secrets.DB_APPKEY}}
export DB_APPSECRET=${{ secrets.DB_APPSECRET}}
export EOS_API_KEY=${{ secrets.EOS_API_KEY}}


aws ecr get-login-password --region ap-northeast-2 | \
docker login --username AWS --password-stdin ${{ steps.login-ecr.outputs.registry }}

docker pull ${{ steps.login-ecr.outputs.registry }}/fintory-child:websocket-latest

docker compose down
docker compose up -d

docker image prune -f

5 changes: 3 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,16 @@ jobs:
export OPENAI_MODEL=${{ secrets.OPENAI_MODEL}}
export OPENAI_TEMPERATURE=${{secrets.OPENAI_TEMPERATURE}}
export OPENAI_MAX_TOKENS=${{secrets.OPENAI_MAX_TOKENS}}
export WEBSOCKET_PRIVATE_HOST=${{secrets.WEBSOCKET_PRIVATE_HOST}}
export FIREBASE_CONFIG='${{secrets.FIREBASE_CONFIG}}'

aws ecr get-login-password --region ap-northeast-2 | \
docker login --username AWS --password-stdin ${{ steps.login-ecr.outputs.registry }}
docker login --username AWS --password-stdin ${{ steps.login-ecr.outputs.registry }}

docker pull ${{ steps.login-ecr.outputs.registry }}/fintory-child:latest

docker compose down
docker compose up -d

docker image prune -f

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@SpringBootApplication(scanBasePackages = {
"com.fintory.infra",
"com.fintory.auth",
"com.fintory.child"
"com.fintory.child",
})
@ConfigurationPropertiesScan(basePackages = {
"com.fintory.auth"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import com.fintory.domain.stock.dto.korean.response.StockSearchResponse;
import com.fintory.domain.stock.dto.websocket.MarketStatusResponse;
import com.fintory.domain.stock.service.common.CommonStockService;
import com.fintory.domain.stock.service.websocket.LiveStockPriceWebsocketService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

Expand All @@ -20,22 +21,27 @@
public class CommonStockControllerImpl implements CommonStockController {

private final CommonStockService commonStockService;
private final LiveStockPriceWebsocketService websocketService;
private final RestTemplate restTemplate;

@Value("${websocket.server.url}")
private String websocketServerUrl;


//주식 종목 검색
@Override
@GetMapping("/search")
public ResponseEntity<ApiResponse<List<StockSearchResponse>>> searchStock(@RequestParam String keyword) {
List<StockSearchResponse> stockSearchRespons = commonStockService.searchStock(keyword);
return ResponseEntity.ok(ApiResponse.ok(stockSearchRespons));
List<StockSearchResponse> stockSearchResponse = commonStockService.searchStock(keyword);
return ResponseEntity.ok(ApiResponse.ok(stockSearchResponse));
}

//장시간 리턴
@Override
@GetMapping("/opened-market")
public ResponseEntity<ApiResponse<MarketStatusResponse>> getMarketStatus(){
return ResponseEntity.ok(ApiResponse.ok(websocketService.getMarketStatus()));
String url = "http://"+websocketServerUrl+":8080" + "/api/websocket/market/status";
MarketStatusResponse response = restTemplate.getForObject(url, MarketStatusResponse.class);
return ResponseEntity.ok(ApiResponse.ok(response));
}

}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public ResponseEntity<ExceptionResponse> handleHandlerMethodValidation(HandlerMe
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ExceptionResponse> handleUnhandledException(Exception e, HttpServletRequest request) {
public ResponseEntity<ExceptionResponse> handleUnhandledException(Exception e) {
log.error("Unknown server error", e);
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
Expand Down
9 changes: 5 additions & 4 deletions app-child/src/main/resources/application-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ spring:
activate:
on-profile: deploy

websocket:
stomp:
stats-log-period: 30000

datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
Expand Down Expand Up @@ -96,4 +93,8 @@ eos:
api-key: ${EOS_API_KEY}

firebase:
config: ${FIREBASE_CONFIG}
config: ${FIREBASE_CONFIG}

websocket:
server:
url: ${WEBSOCKET_PRIVATE_HOST}
3 changes: 3 additions & 0 deletions app-child/src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ db-openapi:
firebase:
config: ${FIREBASE_CONFIG}

websocket:
server:
url: http://localhost:8081



Expand Down
Loading
Loading