Skip to content

Commit fa0c69a

Browse files
committed
2 parents dffce25 + 1d84fe9 commit fa0c69a

File tree

7 files changed

+132
-29
lines changed

7 files changed

+132
-29
lines changed

README.md

Lines changed: 114 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,130 @@
1-
# BlockGuard-server
2-
3-
본 레포지토리는 **BlockGuard**의 서버 애플리케이션입니다.
4-
Spring Boot 기반으로 개발되었으며, AI 서버와 연동하여 사기 유형을 분석하고, 사용자 신고 과정을 단계별로 관리합니다.
1+
# 🌎 BlockGuard-server
2+
![img_1.png](img_1.png)
3+
AI를 활용한 보이스피싱 사전예방 통합 서비스 **BlockGuard**의 Spring 서버 레포지토리입니다.
54

65
---
76

8-
## 📌 ERD (Entity Relationship Diagram)
7+
## 📌 Package Structure
8+
```
9+
├── 📄 Dockerfile
10+
├── 📄 PULL_REQUEST_TEMPLATE.md
11+
├── 📄 README.md
12+
├── 📄 build.gradle
13+
├── 📂 gradle
14+
│ └── 📂 wrapper
15+
│ ├── 📦 gradle-wrapper.jar
16+
│ └── ⚙️ gradle-wrapper.properties
17+
├── ⚙️ gradlew
18+
├── ⚙️ gradlew.bat
19+
├── 📄 settings.gradle
20+
└── 📂 src/main/java/com/blockguard/server
21+
├── 🚀 ServerApplication.java
22+
├── 📂 domain
23+
│ ├── 📂 admin
24+
│ │ └── 📂 api
25+
│ ├── 📂 analysis
26+
│ │ ├── 📂 api
27+
│ │ ├── 📂 application
28+
│ │ ├── 📂 dao
29+
│ │ ├── 📂 domain
30+
│ │ └── 📂 dto
31+
│ │ ├── 📂 request
32+
│ │ └── 📂 response
33+
│ ├── 📂 auth
34+
│ │ ├── 📂 api
35+
│ │ ├── 📂 application
36+
│ │ ├── 📂 domain
37+
│ │ ├── 📂 dto
38+
│ │ ├── 📂 enhancer
39+
│ │ ├── 📂 enums
40+
│ │ ├── 📂 infra
41+
│ │ └── 📂 interceptor
42+
│ ├── 📂 fraud
43+
│ │ ├── 📂 api
44+
│ │ ├── 📂 application
45+
│ │ ├── 📂 dao
46+
│ │ ├── 📂 domain
47+
│ │ └── 📂 dto
48+
│ ├── 📂 guardian
49+
│ │ ├── 📂 api
50+
│ │ ├── 📂 application
51+
│ │ ├── 📂 dao
52+
│ │ ├── 📂 domain
53+
│ │ └── 📂 dto
54+
│ ├── 📂 news
55+
│ │ ├── 📂 api
56+
│ │ ├── 📂 application
57+
│ │ ├── 📂 dao
58+
│ │ ├── 📂 domain
59+
│ │ ├── 📂 dto
60+
│ │ └── 📂 scheduler
61+
│ ├── 📂 report
62+
│ │ ├── 📂 api
63+
│ │ ├── 📂 application
64+
│ │ ├── 📂 dao
65+
│ │ ├── 📂 domain
66+
│ │ └── 📂 dto
67+
│ └── 📂 user
68+
│ ├── 📂 api
69+
│ ├── 📂 application
70+
│ ├── 📂 dao
71+
│ ├── 📂 domain
72+
│ └── 📂 dto
73+
├── 📂 global
74+
│ ├── 📂 common
75+
│ │ ├── 📂 codes
76+
│ │ ├── 📂 entity
77+
│ │ └── 📂 response
78+
│ ├── 📂 config
79+
│ │ ├── 📂 S3
80+
│ │ ├── 📂 resolver
81+
│ │ └── 📂 swagger
82+
│ └── 📂 exception
83+
│ ├── 🛠️ BusinessExceptionHandler.java
84+
│ └── 🛠️ GlobalExceptionHandler.java
85+
└── 📂 infra
86+
├── 📂 crawler
87+
├── 📂 google
88+
├── 📂 gpt
89+
├── 📂 importer
90+
├── 📂 naver
91+
│ └── 📂 ocr
92+
└── 📂 number
93+
```
994

10-
서비스에서 사용하는 주요 도메인 구조를 ERD로 정리했습니다.
1195

96+
## 📌 ERD (Entity Relationship Diagram)
1297
- [ERD Diagram Link](https://dbdiagram.io/d/BlockGuard_ERD-686d1997f413ba3508d99080)
13-
<img width="1920" height="994" alt="image" src="https://github.com/user-attachments/assets/54a18ee7-f831-45a4-b4bb-173986c8708c" />
14-
98+
![img_4.png](img_4.png)
99+
<details>
100+
<summary> 테이블 별 용도</summary>
101+
<div markdown="1">
102+
103+
- **User**: 서비스의 기본 사용자 정보를 저장 (계정, 개인정보, 상태 관리)
104+
- **Guardian**: 사용자의 보호자(연락망) 정보를 저장, 다수 가능
105+
- **NewsArticle**: 보이스피싱/사기 관련 뉴스 기사 수집 및 조회용 데이터
106+
- **FraudPhoneNumber**: 사기 의심 전화번호 저장 및 API 검증 기록
107+
- **FraudUrl**: 사기 의심 URL 저장 및 감지 시각 관리
108+
- **UserReportRecord**: 사용자가 진행 중인 신고 프로세스의 전체 레코드
109+
- **ReportStepProgress**: 신고 프로세스 각 단계의 진행 상황 기록
110+
- **ReportStepCheckbox**: 단계별 필수/권장 체크박스 항목의 완료 여부 기록
111+
- **FraudAnalysisRecord**: AI 분석 결과(사기 유형, 점수, 위험도)를 저장
112+
113+
</div>
114+
</details>
15115

16116
---
17117

18118
## 📌 API 명세서
19-
20-
REST API 엔드포인트 및 스펙은 아래 문서를 참고하세요.
21-
22119
- [API 명세서 (Swagger 링크)](https://www.blockguard.shop/swagger-ui/index.html)
23-
- 여기 API 명세서 노션 문서 추가
120+
- [API 명세서 (Notion 링크)](https://breezy-index-18b.notion.site/API-253ec5aa3e1a8014a18dc53ee1d1c5c8)
24121

25122
---
26123

27-
## 📌 아키텍처 다이어그램
28-
29-
서비스 전체 아키텍처 다이어그램입니다.
30-
31-
<img width="1368" height="1002" alt="image" src="https://github.com/user-attachments/assets/a2ab4818-0240-48ef-b9b5-ffb099068bc8" />
124+
## 📌 Architecture Diagram
32125

126+
- 서비스 전체 아키텍처 다이어그램
127+
![img_2.png](img_2.png)
33128

34-
구성 요소:
35-
- AWS EC2: 서버 애플리케이션 컨테이너 실행 (Docker)
36-
- AWS RDS (MySQL): 영속성 데이터 저장
37-
- AWS S3: 사용자 업로드 파일 및 리소스 저장
38-
- AI Server: GPT 모델 기반 사기 유형 분석
39-
- CI/CD (Docker, GitHub Actions): 자동 빌드 및 배포 파이프라인
129+
- 서버 아키텍처 다이어그램
130+
![img_3.png](img_3.png)

img.png

39.1 KB
Loading

img_1.png

1.41 MB
Loading

img_2.png

913 KB
Loading

img_3.png

758 KB
Loading

img_4.png

199 KB
Loading

src/main/java/com/blockguard/server/domain/news/scheduler/NewsSaveScheduler.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
import org.springframework.scheduling.annotation.Scheduled;
99
import org.springframework.stereotype.Component;
1010

11+
import java.util.EnumSet;
1112
import java.util.List;
1213
import java.util.Map;
14+
import java.util.Set;
1315

1416
@Component
1517
@Slf4j
@@ -25,7 +27,7 @@ public class NewsSaveScheduler {
2527
Map.entry(Category.LOAN_FRAUD, List.of("대출 사기", "저금리 대출 사기", "대출 빙자 사기")),
2628
Map.entry(Category.CARD_IMPERSONATION, List.of("카드사 사칭", "카드사 피싱", "신용카드 사칭")),
2729
Map.entry(Category.FAMILY_IMPERSONATION, List.of("가족 사칭", "지인 사칭")),
28-
Map.entry(Category.EVENT_IMPERSONATION, List.of("경조사 사칭", "경조사 문자 사기", "모바일 청첩장 사기", "부고장 스미싱","온라인 부고장 사기","청첩장 스미싱")),
30+
Map.entry(Category.EVENT_IMPERSONATION, List.of("경조사 사칭", "경조사 문자 사기", "모바일 청첩장 사기", "부고장 스미싱", "온라인 부고장 사기", "청첩장 스미싱")),
2931
Map.entry(Category.PUBLIC_IMPERSONATION, List.of("공공기관 사칭", "국세청 사칭", "경찰 출석 요구 사칭", "검찰 사칭", "과태료 사칭")),
3032
Map.entry(Category.PART_TIME_SCAM, List.of("알바 사기", "부업 사기", "구인 사기")),
3133
Map.entry(Category.GOVERNMENT_GRANT_SCAM, List.of("정부지원금 사기", "보조금 사기", "지원금 사칭")),
@@ -37,7 +39,11 @@ public class NewsSaveScheduler {
3739

3840
@Async
3941
public void crawlingForAdmin() {
40-
crawlAll();
42+
crawlByCategories(EnumSet.of(
43+
Category.VOICE_PHISHING,
44+
Category.SMISHING,
45+
Category.MESSAGE_VOICE_PHISHING
46+
));
4147
}
4248

4349
@Async
@@ -47,16 +53,22 @@ public void saveNewsArticles() {
4753
}
4854

4955
private void crawlAll() {
50-
log.info("뉴스 크롤링 스케줄링 시작");
51-
KEYWORDS_PER_CATEGORY.forEach((category, keywords) -> {
56+
crawlByCategories(KEYWORDS_PER_CATEGORY.keySet());
57+
}
58+
59+
private void crawlByCategories(Set<Category> categories) {
60+
log.info("뉴스 크롤링 시작 (targets={})", categories);
61+
categories.forEach(category -> {
62+
List<String> keywords = KEYWORDS_PER_CATEGORY.getOrDefault(category, List.of());
5263
for (String keyword : keywords) {
5364
try {
5465
daumNewsCrawler.fetchNewsFromDaum(keyword, category);
5566
} catch (Exception e) {
56-
log.warn("크롤 실패: category={}, keyword={}", category, keyword, e);
67+
log.warn("크롤링 실패: category={}, keyword={}", category, keyword, e);
5768
}
5869
}
5970
});
60-
log.info("뉴스 크롤링 스케줄링 완료");
71+
log.info("뉴스 크롤링 완료");
6172
}
73+
6274
}

0 commit comments

Comments
 (0)