AI-Ready 홈페이지 API 서버
1. 프로젝트 개요
이 프로젝트는 AI-Ready의 공식 홈페이지에 필요한 데이터를 제공하는 백엔드 API 서버입니다. Spring WebFlux 기반의 비동기/논블로킹 방식으로 구현되어 높은 성능과 확장성을 목표로 합니다.
주요 기능은 블로그(기술, 연구, 소식 등) 컨텐츠 관리, 사용자 인증, 문의사항 처리, 파일 관리 등을 포함합니다.
2. 기술 스택
- 언어: Java 17
- 프레임워크: Spring Boot 3.x, Spring WebFlux (Reactive-Stack)
- 데이터베이스: RDBMS (MySQL, PostgreSQL 등)
- 데이터베이스 연동: R2DBC (Reactive Relational Database Connectivity)
- 인증: JWT (JSON Web Token)
- 빌드 도구: Gradle
- 기타: Lombok, Logback
3. 아키텍처: 왜 Spring WebFlux를 선택했는가?
이 프로젝트는 전통적인 Spring MVC 방식이 아닌 Spring WebFlux 기반의 리액티브(Reactive) 프로그래밍 모델을 채택했습니다. 그 이유는 AI 시대의 서비스가 요구하는 특성에 더 잘 부합하기 때문입니다.
전통적인 MVC 방식의 한계
- Thread-Per-Request 모델: 사용자의 요청마다 하나의 스레드가 할당됩니다. 만약 데이터베이스 조회나 외부 API 호출과 같은 I/O 작업이 길어지면, 해당 작업이 끝날 때까지 스레드는 **블로킹(Blocking)**되어 다른 일을 하지 못하고 대기합니다.
- 리소스 비효율성: 동시 접속자가 많아지고, 각 요청의 처리 시간이 길어질수록(예: LLM 호출), 스레드 풀의 스레드가 빠르게 고갈됩니다. 이는 서버 전체의 응답성 저하와 리소스 낭비로 이어집니다.
WebFlux (Reactive) 방식의 장점
- 이벤트 루프(Event-Loop) 기반 논블로킹(Non-Blocking): 최소한의 스레드(일반적으로 CPU 코어 수와 동일)를 사용하여 모든 요청을 처리합니다. I/O 작업이 발생하면 스레드가 결과를 기다리지 않고 즉시 다른 요청을 처리하러 갑니다. 작업이 완료되면 콜백(Callback)을 통해 결과를 받아 후속 처리를 이어갑니다.
- 높은 동시성과 확장성: 스레드가 블로킹되지 않으므로, 적은 리소스로도 훨씬 많은 동시 요청을 효율적으로 처리할 수 있습니다. 이는 수많은 동시 사용자를 가정해야 하는 최신 웹 서비스에 필수적입니다.
AI 시대에 WebFlux가 필수적인 이유
AI 서비스, 특히 외부 LLM(거대 언어 모델) API를 호출하는 작업은 네트워크 지연 시간으로 인해 수 초 이상이 소요될 수 있는 대표적인 고지연(High-Latency) 작업입니다.
- 효율적인 리소스 관리: WebFlux를 사용하면 LLM API가 응답을 기다리는 동안 스레드는 다른 수십, 수백 개의 요청을 처리할 수 있습니다. 이는 서버 리소스를 극적으로 아끼고, 높은 트래픽 상황에서도 안정적인 서비스를 제공하는 핵심 요소가 됩니다.
- 스트리밍 응답에 최적화: AI 모델이 생성하는 텍스트를 실시간으로 사용자에게 보여주는 것과 같은 스트리밍(Streaming) 응답을 자연스럽게 지원합니다.
💡 결론적으로, Spring WebFlux는 AI 연동과 같이 예측 불가능하고 긴 I/O 작업이 빈번한 환경에서 서버의 반응성과 확장성을 극대화하는 최적의 아키텍처입니다.
4. 프로젝트 구조
.
├── build.gradle # Gradle 빌드 스크립트
├── gradlew # Gradle Wrapper
├── settings.gradle # Gradle 설정
├── start.sh # 애플리케이션 실행 스크립트
├── stop.sh # 애플리케이션 중지 스크립트
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com/aiready
│ │ │ ├── Application.java # 메인 애플리케이션 실행 클래스
│ │ │ ├── aspect # AOP 관련 클래스 (파라미터 유효성 검증 등)
│ │ │ ├── config # 애플리케이션 주요 설정 (보안, DB, CORS 등)
│ │ │ ├── controller # API 엔드포인트 정의
│ │ │ ├── exception # 전역 예외 처리
│ │ │ ├── model # 데이터 모델 (DTO, Entity 등)
│ │ │ ├── repository # 데이터베이스 접근 로직 (R2DBC)
│ │ │ ├── service # 비즈니스 로직
│ │ │ └── util # 유틸리티 클래스 (JWT 토큰 생성 등)
│ │ └── resources
│ │ ├── application.yml # 공통 설정 파일
│ │ ├── application-dev.yml # 개발 환경 설정 파일
│ │ ├── application-prod.yml # 운영 환경 설정 파일
│ │ ├── i18n # 다국어 메시지 프로퍼티
│ │ ├── logback-spring.xml # 로깅 설정
│ │ └── mapper # SQL 쿼리 XML 파일
│ └── test # 테스트 코드
└── hep
├── scheme.sql # 데이터베이스 테이블 생성 스키마
└── ERD-homepage-*.erwin # ERD 파일
5. 개발 환경 설정
-
사전 요구사항
- Java 17 (JDK 17) 설치
- IDE (IntelliJ IDEA 또는 Eclipse) 설치
- 데이터베이스 (MySQL, PostgreSQL 등) 설치 및 실행
-
프로젝트 클론
git clone [저장소 URL] cd 2025_aiready_homepage_api -
데이터베이스 설정
hep/scheme.sql파일을 사용하여 프로젝트에서 사용할 데이터베이스에 테이블을 생성합니다.- 데이터베이스 사용자 계정을 생성합니다.
-
애플리케이션 설정
src/main/resources/application-dev.yml파일을 엽니다.spring.r2dbc섹션에 자신의 로컬 데이터베이스 접속 정보를 입력합니다.spring: profiles: active: dev # 개발 시 'dev' 프로파일 활성화 r2dbc: url: r2dbc:mysql://{DB_HOST}:{DB_PORT}/{DB_NAME} username: {DB_USERNAME} password: {DB_PASSWORD}- (선택) JWT 토큰 생성에 사용될
jwt.secret값을 변경합니다.
6. 빌드 및 실행
IDE에서 직접 실행
- IntelliJ IDEA에서
Application.java파일을 엽니다. main메소드 옆의 실행 버튼을 클릭하여 애플리케이션을 시작합니다.
Gradle을 사용하여 실행
터미널에서 아래 명령어를 실행하여 애플리케이션을 빌드하고 실행할 수 있습니다.
# 프로젝트 빌드
./gradlew build
# 애플리케이션 실행
./gradlew bootRun
애플리케이션이 정상적으로 실행되면 localhost:8080 (또는 application-dev.yml에 설정된 포트)에서 API 서버가 활성화됩니다.
7. 주요 기능 및 API 엔드포인트
- AuthController: 회원가입, 로그인 등 사용자 인증 관련 API
- UserController: 사용자 정보 조회 및 수정 API
- TechBlogController: 기술 블로그 게시물 CRUD API
- NewsBlogController: 소식 블로그 게시물 CRUD API
- LabBlogController: 연구 블로그 게시물 CRUD API
- InquiryController: 문의사항 등록 및 조회/답변 API
- FileStorageController: 파일 업로드/다운로드 API
💬 상세한 API 명세는 Postman 컬렉션이나 API 문서를 참고하세요.
8. 데이터베이스
- 본 프로젝트는 R2DBC를 사용하여 비동기적으로 데이터베이스와 통신합니다.
- SQL 쿼리는
src/main/resources/mapper디렉토리의.xml파일에 정의되어 있습니다. com.farm패키지는 XML에 정의된 동적 SQL을 파싱하고 실행하는 커스텀 SQL 매퍼 엔진입니다. 이를 통해 MyBatis와 유사한 방식으로 동적 쿼리를 관리할 수 있습니다.
9. 인증
- API 접근 제어는 JWT(JSON Web Token)를 통해 이루어집니다.
- 사용자가 로그인을 성공하면 서버는 Access Token과 Refresh Token을 발급합니다.
- 인증이 필요한 API를 호출할 때는 HTTP 헤더에
Authorization: Bearer {Access_Token}형식으로 토큰을 포함해야 합니다. JwtTokenProvider클래스에서 토큰 생성 및 검증 로직을 확인할 수 있으며,SecurityConfig에서 라우트별 접근 권한을 설정합니다.
10. 서비스 배포
start.sh,stop.sh,hp_api.service파일들은 Linux 환경에서 서비스를 배포하고 관리하기 위한 스크립트입니다.hp_api.service는systemd서비스로 등록하여 서버 부팅 시 자동으로 애플리케이션을 실행하도록 설정하는 데 사용될 수 있습니다.