노후하우(KnowWhoHow)의 메인 백엔드 서버입니다.
사용자의 자산과 재무 목표를 바탕으로 포트폴리오를 진단하고, 금융 상품 시뮬레이션·일자리 탐색·MyData 연동·디지털 유산(영상 편지) 관리를 제공하는 REST API 서버입니다.
| 도메인 | 제공 기능 |
|---|---|
| 인증 | 일반 회원가입/로그인, Kakao OAuth2 로그인, JWT 재발급·로그아웃, CoolSMS 휴대폰 인증 |
| 사용자 | 프로필, 관심 키워드, 투자 성향, 보유 자산·연금 자산 관리, 회원 탈퇴 |
| 자산 관리 | 재무 설문 저장, 포트폴리오 진단, 예금·적금 만기 금액 시뮬레이션, 금융 상품 조회 |
| MyData | Authorization Code 기반 연동, 토큰 관리, 외부 Resource Server의 자산 데이터 조회 |
| 일자리 | 공공 Open API 기반 채용 공고 검색·상세 조회, Redis 캐시 |
| 디지털 유산 | 상속 계획, S3 영상 멀티파트 업로드, 수신인 등록, 예약 이메일 발송 및 영상 열람 |
- Java 17
- Spring Boot 3.2.5
- Spring Web MVC, Validation
- Spring Data JPA
- Spring Security
- Spring WebFlux
WebClient - Gradle
- Lombok
- MySQL: 서비스 영속 데이터
- Redis: 인증 코드, 임시 OAuth 정보, MyData Access Token, 채용 API 캐시
- AWS S3: 영상 편지 저장 및 Presigned URL 기반 멀티파트 업로드
- SMTP: 예약 영상 편지 링크 발송
- CoolSMS(Solapi): 휴대폰 본인 인증
- Docker, Docker Compose, Nginx
- JJWT 0.12.5
- Kakao OAuth2
- springdoc-openapi / Swagger UI
- JUnit 5
- Spring Boot Test
- Spring Security Test
- H2
- JaCoCo
프로젝트는 도메인 단위 패키지와 계층형 구조를 함께 사용합니다.
Client
│
▼
Spring Security / JWT Filter
│
▼
Controller ── DTO / Validation
│
▼
Service ──── Transaction / Business Logic
│
├── Repository ── JPA ── MySQL
├── Redis
└── External Services
├── Kakao / CoolSMS
├── MyData AS·RS
├── 공공 일자리 Open API
├── AWS S3
└── SMTP
- 공개 API를 제외한 요청은
JwtAuthFilter에서 Bearer Access Token을 검증합니다. - 인증된 사용자 엔티티는
@AuthenticationPrincipal을 통해 컨트롤러에 전달됩니다. - 컨트롤러는 입력 검증과 HTTP 응답을 담당하고, 서비스가 트랜잭션과 비즈니스 규칙을 처리합니다.
- 일반 응답은 아래의 공통 포맷을 사용합니다.
{
"isSuccess": true,
"data": {},
"error": null
}실패 시에는 GlobalExceptionHandler가 HTTP 상태와 서비스 에러 코드를 포함한 응답으로 변환합니다.
{
"isSuccess": false,
"data": null,
"error": {
"code": "AUTH_015",
"message": "사용자를 찾을 수 없습니다."
}
}- Access Token과 Refresh Token은 서로 다른 Secret과 만료 시간을 사용합니다.
- 비밀번호는 BCrypt로 단방향 암호화합니다.
- 서버 세션을 생성하지 않는 Stateless 방식입니다.
- Refresh Token은 DB에 저장하며, 로그아웃 시 토큰을 무효화합니다.
- 로그인·회원가입·토큰 재발급·OAuth 콜백·Swagger·영상 편지 공개 링크 등만 인증 없이 접근할 수 있습니다.
인증이 필요한 API는 다음 헤더를 사용합니다.
Authorization: Bearer <access-token>- 서버가 MyData Authorization Server의 인가 URL을 생성합니다.
- 사용자가 동의하면 Callback의 Authorization Code를 토큰으로 교환합니다.
- 짧게 유지되는 Access Token은 TTL과 함께 Redis에 저장합니다.
- Refresh Token과 Scope는 MySQL의
my_data테이블에 저장합니다. - 자산 조회 시 Access Token이 없거나 만료되었다면 Refresh Token으로 갱신한 뒤 Resource Server를 호출합니다.
JobOpenApiClient가 공공 Open API를 호출하고 응답을 내부 DTO로 변환합니다. 목록 조회 결과의 부가 정보는 Redis에 캐시하며, 상세 조회 시 목록 정보와 상세 응답을 조합합니다.
- 대용량 영상은 서버를 경유하지 않고 S3 Presigned URL로 멀티파트 업로드합니다.
- 업로드 초기화 → Part URL 발급 → 업로드 완료 순서로 동작합니다.
- 수신인별 일회성 접근 링크와 발송 예정 시간을 저장합니다.
- 매분 실행되는
InheritanceScheduler가 발송 대상자를 조회해 SMTP로 영상 링크를 전송합니다. - 공개 영상 링크는 접근 토큰을 검증한 뒤 제한된 시간의 S3 조회 URL로 연결됩니다.
src
├── main
│ ├── java/com/know_who_how/main_server
│ │ ├── auth # 회원가입, 로그인, SMS, Kakao OAuth2
│ │ ├── user # 사용자·자산·키워드 관리
│ │ ├── asset_management # 포트폴리오와 금융 시뮬레이션
│ │ ├── mydata # MyData 인증 및 자산 조회
│ │ ├── job # 일자리 Open API 연동
│ │ ├── inheritance # 상속 계획, 영상, 수신인, 예약 발송
│ │ └── global
│ │ ├── config # Security, Redis, AWS, WebClient 설정
│ │ ├── dto # 공통 API 응답
│ │ ├── entity # JPA 엔티티
│ │ ├── exception # 전역 예외 처리와 에러 코드
│ │ ├── jwt # JWT 생성·검증·필터
│ │ └── util # Redis, Cookie 유틸리티
│ └── resources
│ └── data.sql # 초기 기준 데이터
└── test # 도메인별 단위·통합 테스트
- JDK 17
- MySQL
- Redis
- 사용할 외부 서비스의 인증 정보
- Kakao OAuth2
- CoolSMS
- 공공 일자리 Open API
- MyData Authorization/Resource Server
- AWS S3
- SMTP
애플리케이션 실행 후 Swagger UI에서 요청·응답 스키마와 각 API의 상세 설명을 확인할 수 있습니다.
- Swagger UI:
http://localhost:8080/swagger-ui/index.html - OpenAPI JSON:
http://localhost:8080/v3/api-docs
주요 엔드포인트는 다음과 같습니다.
| Method | Endpoint | 설명 | 인증 |
|---|---|---|---|
POST |
/api/v1/auth/signup/submit |
회원가입 | 불필요 |
POST |
/api/v1/auth/login |
일반 로그인 | 불필요 |
POST |
/api/v1/auth/reissue |
Access Token 재발급 | 불필요 |
GET |
/login/oauth2/code/{registrationId} |
소셜 로그인 Callback | 불필요 |
GET/PATCH |
/api/v1/user/... |
사용자·자산·키워드 관리 | 필요 |
GET |
/api/v1/asset-management/portfolio |
포트폴리오 진단 | 필요 |
POST |
/api/v1/asset-management/simulate/saving |
적금 시뮬레이션 | 필요 |
POST |
/api/v1/asset-management/simulate/deposit |
예금 시뮬레이션 | 필요 |
GET |
/api/v1/my-data/authorize |
MyData 연동 시작 | 필요 |
GET |
/api/v1/resource/my-data |
MyData 자산 조회 | 필요 |
GET |
/api/v1/jobs |
채용 공고 검색 | 필요 |
GET |
/api/v1/jobs/{jobId} |
채용 공고 상세 | 필요 |
POST/GET |
/api/v1/inheritance/plan |
상속 계획 저장·조회 | 필요 |
POST |
/api/v1/inheritance/{id}/video/upload/init |
영상 업로드 초기화 | 필요 |
GET |
/api/v1/inheritance/video-letter |
수신인 영상 열람 | 접근 토큰 |
전체 테스트:
./gradlew test테스트 완료 후 JaCoCo HTML 보고서는 다음 위치에 생성됩니다.
build/reports/jacoco/test/html/index.html
테스트는 application-test.yml과 H2의 MySQL 호환 모드를 사용합니다. 외부 인프라에 의존하는 객체는 테스트별 Mock 구성이 필요합니다.
JAR 이미지 빌드:
./gradlew clean bootJar
docker build -f docker/Dockerfile -t knowwhohow-main .저장소의 docker-compose.yml은 다음 구성을 전제로 합니다.
${DOCKER_USERNAME}/knowwhohow-main:latest백엔드 이미지- 비밀번호가 설정된 Redis
- 외부 MySQL 및 외부 서비스 설정
./nginx/conf에 준비된 Nginx 설정
docker compose up -d