요금제

아키텍처 개요

관련 소스 파일

이 페이지의 내용은 다음 소스 파일을 기반으로 생성되었습니다:

시스템 아키텍처 개요

nbcio-boot 프로젝트는 엔터프라이즈급 비즈니스 애플리케이션 개발을 위한 Java 기반 오픈 소스 프레임워크이다. Spring Boot를 핵심 프레임워크로 채택하고, MyBatis-Plus, Apache Shiro, Redis 등 검증된 오픈 소스 기술을 통합하여 안정적이고 확장 가능한 백엔드 시스템을 구축하는 것을 목표로 한다.

이 아키텍처는 특히 다중 데이터베이스 지원(MySQL, Oracle, SqlServer, PostgreSQL 및 국산 데이터베이스)과 고성능 캐싱, 보안 인증을 강조하여 다양한 비즈니스 시나리오에 대응할 수 있도록 설계되었다 (README.md:24-53).

백엔드 기술 스택

핵심 프레임워크 계층

백엔드 시스템은 Spring Boot 2.3.5.RELEASE를 기반으로 구축되어, 의존성 주입(DI), 관점 지향 프로그래밍(AOP), 자동 설정(Auto-configuration) 등 현대적 Java 애플리케이션 개발의 표준을 따른다. 이 버전은 안정성과 생태계 호환성이 검증된 LTS 성격의 릴리스로, 엔터프라이즈 환경에서의 장기 운영에 적합하다 (README.md:24-37).

기술버전용도선정 근거
Spring Boot2.3.5.RELEASE기반 프레임워크생태계 성숙도, 자동 설정, 마이크로서비스 대응
MyBatis-Plus3.4.3.1ORM/퍼시스턴스SQL 제어력 유지, 복잡 쿼리 대응, 생산성 향상
Apache Shiro1.7.0보안 프레임워크경량성, 유연한 권한 모델, 세션 관리
JWT3.11.0토큰 기반 인증Stateless 인증, 분산 시스템 호환
Druid1.1.22DB 커넥션 풀모니터링, SQL 방화벽, 성능 최적화
Redis-분산 캐시고성능, 데이터 구조 다양성, 클러스터 지원
Logback-로깅Spring Boot 기본값, 성능, 유연한 설정
Quartz-작업 스케줄링클러스터링, 영속성, Cron 표현식 지원

보안 및 데이터 처리 계층

보안 아키텍처는 Apache Shiro와 JWT의 결합으로 구성된다. Shiro는 인증, 권한 부여, 암호화, 세션 관리를 포괄하는 포괄적 보안 프레임워크로, RBAC(Role-Based Access Control) 모델을 통해 세밀한 권한 제어를 가능하게 한다. JWT는 클라이언트 측 상태 비저장(Stateless) 토큰으로, 분산 환경에서 세션 동기화 오버헤드 없이 인증 정보를 전달할 수 있게 한다 (README.md:24-37).

데이터 액세스 계층에서 MyBatis-Plus는 MyBatis의 강력한 SQL 매핑 기능에 코드 생성기, 페이징 플러그인, 조건 래퍼(Wrapper) 등의 생산성 도구를 추가한다. 이는 복잡한 비즈니스 쿼리를 직접 작성하면서도 단순 CRUD 작업은 자동화하는 하이브리드 접근을 가능하게 한다.

正在加载图表渲染器...

아키텍처 다이어그램 핵심 포인트:

  1. 계층 분리 원칙: 프레젠테이션(Controller) → 비즈니스(Service) → 퍼시스턴스(Mapper)로 명확한 의존성 방향 유지
  2. 보안 선제 필터: 모든 요청이 Shiro-JWT 인증을 거쳐 비즈니스 계층 보호
  3. 캐시 전략: Redis를 Service 계층에서 직접 활용하여 DB 부하 감소 및 응답 속도 향상
  4. 다중 DB 지원: Druid 커넥션 풀을 통해 MySQL, Oracle, PostgreSQL 등 투명 전환 가능 (README.md:41-53)

개발 및 인프라 환경

Java 개발 환경

프로젝트는 Java 8을 표준 런타임으로 지정하여, 레거시 시스템과의 호환성과 넓은 서버 지원 범위를 보장한다. IDE는 STS(Spring Tool Suite) 또는 IntelliJ IDEA를 권장하며, Lombok 플러그인 설치가 필수적이다. Lombok은 getter/setter, 생성자, 로거 선언 등의 보일러플레이트 코드를 컴파일 타임에 자동 생성하여 코드 가독성과 유지보수성을 크게 향상시킨다 (README.md:41-53).

의존성 관리는 Maven을 통해 수행되며, 표준 디렉토리 구조와 라이프사이클 관리를 통해 빌드, 테스트, 배포 과정을 자동화한다.

데이터베이스 및 캐시 인프라

데이터베이스 전략의 핵심 특징은 다중 데이터베이스 지원이다. MySQL 5.7+를 기본으로 하되, Oracle 11g, SQL Server, PostgreSQL 및 다양한 국산 데이터베이스(Kingbase, Oscar, HighGo 등)와의 호환성을 제공한다. 이는 정부/공공기관 프로젝트에서 요구되는 국산 소프트웨어 의무 사용 정책이나 기존 레거시 시스템과의 통합 시나리오에 대응하기 위함이다 (README.md:41-53).

Redis는 필수 캐시 인프라로, 세션 클러스터링, 데이터 캐싱, 분산 락, 발행/구독(Pub/Sub) 메시징 등 다목적으로 활용된다. 특히 다중 인스턴스 배포 시 세션 일관성 유지를 위한 Spring Session과의 통합에 핵심적인 역할을 수행한다.

핵심 모듈 구조

모듈 1: 보안 인증 모듈 (Security Module)

책임 경계:

  • 사용자 신원 확인 및 권한 검증
  • JWT 토큰 발급, 갱신, 폐기
  • API 엔드포인트 접근 제어
  • 세션 및 권한 캐시 관리

진입점 및 핵심 API:

  • AuthController.login(): 사용자 로그인 및 JWT 발급
  • ShiroConfig.securityManager(): Shiro 보안 관리자 구성
  • JwtFilter: 모든 요청에 대한 토큰 검증 필터
  • UserRealm: 사용자 인증 및 권한 조회 영역

핵심 데이터 구조:

java
1// JWT 페이로드 구조 (추정)
2{
3  "userId": "사용자 ID",
4  "username": "로그인명",
5  "roles": ["ROLE_ADMIN", "ROLE_USER"],
6  "permissions": ["sys:user:list", "sys:user:edit"],
7  "exp": 1234567890  // 만료 시간
8}
9
10// Shiro 인증 토큰
11UsernamePasswordToken token = new UsernamePasswordToken(username, password);

주요 호출 체인:

  1. 클라이언트 → JwtFilter.isAccessAllowed() → 토큰 추출
  2. JwtUtil.verify() → 서명 검증 및 만료 확인
  3. UserRealm.doGetAuthenticationInfo() → DB 사용자 조회
  4. UserRealm.doGetAuthorizationInfo() → 권한/역할 로드
  5. 권한 캐시를 Redis에 저장 후 Subject에 바인딩

오류 처리 및 경계 조건:

  • 토큰 만료 시 401 Unauthorized + 갱신 안내
  • 잘못된 서명 시 403 Forbidden + 로깅
  • 존재하지 않는 사용자 시 계정 잠금 방지를 위한 일정 시간 지연 (타이밍 공격 방어)
  • Redis 장애 시 DB 직접 조회로 폴백 (성능 저하 허용)

모듈 2: 데이터 액세스 모듈 (Data Access Module)

책임 경계:

  • SQL 실행 및 결과 매핑
  • 트랜잭션 경계 관리
  • 다중 데이터소스 라우팅
  • 페이징 및 정렬 처리

진입점 및 핵심 API:

  • BaseMapper<T>: MyBatis-Plus 제공 기본 CRUD 인터페이스
  • ServiceImpl<M, T>: 비즈니스 로직 포함 서비스 기반 클래스
  • Page&lt;T&gt;: 페이징 결과 래퍼
  • QueryWrapper&lt;T&gt; / LambdaQueryWrapper&lt;T&gt;: 동적 쿼리 빌더

핵심 데이터 구조:

java
1// 페이징 요청 파라미터
2public class PageQuery {
3    private Integer pageNo = 1;
4    private Integer pageSize = 10;
5    private String sortField;
6    private String sortOrder;
7}
8
9// Druid 데이터소스 설정
10spring.datasource.druid.initial-size=5
11spring.datasource.druid.max-active=20
12spring.datasource.druid.stat-view-servlet.enabled=true

주요 호출 체인:

  1. Controller → Service.page(pageQuery) 호출
  2. Service → PageHelper.startPage() 또는 MyBatis-Plus Page 객체 생성
  3. Mapper → XML 또는 어노테이션 기반 SQL 실행
  4. Druid 커넥션 풀에서 연결 획득
  5. 결과 매핑 후 Page 객체로 래핑하여 반환

오류 처리 및 경계 조건:

  • DB 연결 실패 시 재시도(최대 3회) 후 예외 발생
  • 쿼리 타임아웃(기본 30초) 초과 시 자동 롤백
  • 낙관적 락 충돌 시 OptimisticLockerInterceptor가 버전 검증
  • 대량 데이터 조회 시 스트리밍 모드로 OOM 방지

모듈 3: 캐시 관리 모듈 (Cache Module)

책임 경계:

  • Redis 연결 및 작업 추상화
  • 캐시 무효화 전략 수행
  • 분산 락 제공
  • 세션 클러스터링 지원

진입점 및 핵심 API:

  • RedisTemplate<String, Object>: Spring Data Redis 핵심 템플릿
  • @Cacheable, @CacheEvict: 선언적 캐싱 어노테이션
  • RedissonClient: 분산 락 및 고급 기능
  • CacheManager: 캐시 생명주기 관리자

핵심 데이터 구조:

java
1// 캐시 키 네이밍 컨벤션
2String cacheKey = "sys:user:" + userId + ":permissions";
3
4// 분산 락 획득
5RLock lock = redissonClient.getLock("lock:order:" + orderId);
6lock.lock(10, TimeUnit.SECONDS);
7try {
8    // 임계 영역
9} finally {
10    lock.unlock();
11}

주요 호출 체인:

  1. Service 메서드 호출 → @Cacheable AOP 인터셉트
  2. CacheAspectSupport.execute() → 캐시 키 생성
  3. RedisTemplate.opsForValue().get(key) → Redis 조회
  4. 캐시 미스 시 원본 메서드 실행 → 결과를 Redis에 저장
  5. TTL 만료 또는 @CacheEvict 시 캐시 삭제

오류 처리 및 경계 조건:

  • Redis 연결 실패 시 CacheErrorHandler가 예외를 로깅하고 원본 호출 폴백
  • 캐시 직렬화 실패 시 JSON/FST 등 대체 직렬화기 자동 전환
  • 캐시 스탬피드 방지를 위한 락 기반 갱신 또는 소프트 만료(soft expiration)
  • 메모리 부족 시 LRU/LFU 알고리즘에 의한 자동 퇴거(eviction)

모듈 4: 작업 스케줄링 모듈 (Scheduling Module)

책임 경계:

  • Cron 표현식 기반 작업 예약
  • 클러스터 환경에서 작업 중복 실행 방지
  • 작업 실행 이력 및 로그 관리
  • 동적 작업 추가/수정/삭제

진입점 및 핵심 API:

  • @Scheduled: 선언적 작업 정의 어노테이션
  • SchedulerFactoryBean: Quartz 스케줄러 빈
  • JobDetail: 작업 메타데이터 정의
  • CronTrigger: Cron 기반 트리거

핵심 데이터 구조:

java
1// 작업 정의 예시
2@Bean
3public JobDetail sampleJobDetail() {
4    return JobBuilder.newJob(SampleJob.class)
5        .withIdentity("sampleJob")
6        .storeDurably()
7        .usingJobData("param", "value")
8        .build();
9}
10
11// Cron 트리거
12@Bean
13public Trigger sampleJobTrigger() {
14    return TriggerBuilder.newTrigger()
15        .forJob(sampleJobDetail())
16        .withSchedule(CronScheduleBuilder.cronSchedule("0 0 2 * * ?"))
17        .build();
18}

주요 호출 체인:

  1. Quartz 스케줄러가 Cron 표현식에 따라 트리거 발화
  2. Job.execute() → 트랜잭션 시작
  3. 대상 Service 메서드 호출 (예: ReportService.generateDailyReport())
  4. 작업 결과를 DB 로그 테이블에 저장
  5. 트랜잭션 커밋 및 알림 발송 (선택적)

오류 처리 및 경계 조건:

  • 작업 실행 실패 시 재시도 정책(최대 횟수, 간격) 적용
  • 클러스터 모드에서 DB 락을 통한 작업 선점
  • 작업 실행 시간이 다음 트리거 시간을 넘길 경우 미실행 또는 병렬 실행 정책 적용
  • 시스템 종료 시 waitForJobsToComplete로 진행 중 작업 완료 대기

데이터 흐름 및 호출 체인

인증 요청 처리 흐름

사용자 로그인부터 API 호출까지의 전체 데이터 흐름은 다음과 같다. 이 과정에서 보안 검증, 캐시 활용, 데이터베이스 조회가 유기적으로 결합된다.

正在加载图表渲染器...

데이터 흐름 핵심 포인트:

  1. 이중 검증 구조: JWT의 서명 검증(변조 방지)과 Shiro의 권한 검증(접근 제어)이 순차 수행
  2. 캐시 우선 전략: 권한 정보를 Redis에 캐시하여 DB 부하 최소화, TTL 만료 시 자동 갱신
  3. 무상태 설계: JWT에 필수 정보를 포함하여 세션 저장소 의존도 감소, 수평 확장 용이
  4. 감사 로깅: 모든 인증/권한 이벤트를 Logback을 통해 파일 및 콘솔에 기록 (README.md:35)

비즈니스 트랜잭션 처리 흐름

일반적인 CRUD 작업의 데이터 흐름은 다음과 같다. MyBatis-Plus의 자동화 기능과 Druid의 모니터링이 결합된다.

正在加载图表渲染器...

트랜잭션 처리 핵심 포인트:

  1. 선언적 트랜잭션: @Transactional 어노테이션으로 ACID 보장, 전파 속성 및 격리 수준 설정 가능
  2. 캐시 일관성: 트랜잭션 커밋 후에만 캐시 갱신하여 더티 리드 방지
  3. 연결 풀 최적화: Druid가 유휴 연결을 재사용하여 연결 생성 오버헤드 제거
  4. SQL 모니터링: Druid의 StatViewServlet이 느린 쿼리, 실행 계획, 테이블 스캔 등을 실시간 모니터링 (README.md:31)

모듈 간 의존성 관계

시스템의 핵심 모듈 간 의존성 방향과 결합도를 시각화하면 다음과 같다.

正在加载图表渲染器...

의존성 구조 핵심 포인트:

  1. 단방향 의존: 상위 계층만 하위 계층을 참조, 순환 의존 금지
  2. 보안 계층 독립성: 인증 로직이 비즈니스 로직과 분리되어 재사용성 향상
  3. 데이터 계층 추상화: MyBatis-Plus와 Druid가 DB 벤더 차이를 흡수
  4. 횡단 관심사 분리: 로깅, 캐싱이 AOP를 통해 핵심 로직에서 분리 (README.md:37)

핵심 설계 결정 및 트레이드오프

1. Spring Boot 2.3.5 vs 최신 버전

결정: Spring Boot 2.3.5.RELEASE 채택
근거: 안정성 검증, 서드파티 라이브러리 호환성, 장기 지원
트레이드오프: 최신 기능(가상 스레드, 네이티브 컴파일) 사용 불가
대안: Spring Boot 3.x (Java 17+ 요구, 마이그레이션 비용 높음)

2. MyBatis-Plus vs JPA/Hibernate

결정: MyBatis-Plus 선정
근거: SQL 제어력, 복잡 쿼리 대응, 기존 MyBatis 자산 활용
트레이드오프: 객체 그래프 탐색의 편의성 부족, 1차 캐시 미제공
대안: Spring Data JPA (도메인 주도 설계에 유리, N+1 문제 주의)

3. Apache Shiro vs Spring Security

결정: Apache Shiro 선택
근거: 경량성, 설정 단순성, Spring에 종속되지 않는 이식성
트레이드오프: Spring 생태계 통합도 낮음, 커뮤니티 규모 작음
대안: Spring Security (Spring Boot 자동 설정, OAuth2/SAML 내장 지원)

4. Druid vs HikariCP

결정: Druid 커넥션 풀 사용
근거: 강력한 모니터링, SQL 방화벽, 슬로우 쿼리 분석
트레이드오프: HikariCP보다 약간 무거움, 설정 복잡도 증가
대안: HikariCP (Spring Boot 기본값, 최고 성능, 모니터링 기능 제한적)

5. 다중 데이터베이스 지원 전략

결정: MyBatis-Plus + Druid로 다중 DB 추상화
근거: 공공기관 국산 DB 의무 사용 대응, 레거시 시스템 통합
트레이드오프: DB별 SQL 방언 관리 복잡, 기능 제약 (예: 시퀀스 vs 자동 증가)
대안: 단일 DB 전용 최적화 (성능 향상, 이식성 저하)

6. JWT 세션 전략

결정: Stateless JWT + Redis 권한 캐시
근거: 수평 확장 용이, 세션 동기화 오버헤드 제거
트레이드오프: 토큰 폐기의 즉시성 부족, 페이로드 크기 제약
대안: 세션 기반 인증 (서버 메모리/DB 부하, 스티키 세션 필요)

7. 캐시 무효화 전략

결정: TTL 만료 + 이벤트 기반 무효화
근거: 구현 단순성, 일관성과 성능의 균형
트레이드오프: 짧은 시간 내 데이터 불일치 가능성
대안: Write-through 캐시 (강한 일관성, 쓰기 성능 저하)

기술 스택 선정 비교표

기술 카테고리선정 기술대안 기술선정 이유제약 사항
기반 프레임워크Spring Boot 2.3.5Spring Boot 3.x, Quarkus안정성, 생태계, 레퍼런스 풍부Java 8 제약
ORMMyBatis-Plus 3.4.3JPA/Hibernate, jOOQSQL 제어력, 복잡 쿼리, 학습 곡선 낮음객체 매핑 수동
보안Apache Shiro 1.7.0Spring Security, Pac4j경량성, 유연성, Spring 독립성커뮤니티 규모
인증 토큰JWT 3.11.0OAuth2, Session CookieStateless, 분산 시스템 적합폐기 지연
DB 커넥션 풀Druid 1.1.22HikariCP, C3P0모니터링, SQL 방화벽, 통계성능은 Hikari 우세
캐시RedisEhcache, Hazelcast분산 캐시, 데이터 구조 다양성인프라 복잡도 증가
로깅LogbackLog4j2, SLF4J+JulSpring Boot 기본값, 성능 균형설정 유연성 보통
스케줄러QuartzSpring Scheduler, XXL-Job클러스터링, 영속성, Cron 지원DB 테이블 필요
API 문서화Swagger-uiSpringDoc, Redoc인터랙티브 UI, 테스트 가능어노테이션 중복
JSON 처리FastjsonJackson, Gson성능, 중국 커뮤니티 선호보안 이슈 주의
빌드 도구MavenGradle표준성, 레거시 호환성설정 장황함
코드 간소화LombokDelombok, 수작성보일러플레이트 제거, 가독성IDE 플러그인 필수

핵심 설정 및 시작 프로세스

필수 설정 항목

시스템 구동을 위한 핵심 설정은 application.yml 또는 application.properties에 정의된다.

yaml
1# Spring Boot 핵심 설정
2spring:
3  datasource:
4    type: com.alibaba.druid.pool.DruidDataSource
5    driver-class-name: com.mysql.cj.jdbc.Driver
6    url: jdbc:mysql://localhost:3306/nbcio?useUnicode=true&characterEncoding=utf8
7    username: root
8    password: ${DB_PASSWORD}
9    druid:
10      initial-size: 5
11      max-active: 20
12      min-idle: 5
13      max-wait: 60000
14      stat-view-servlet:
15        enabled: true
16        url-pattern: /druid/*
17  redis:
18    host: ${REDIS_HOST:localhost}
19    port: 6379
20    password: ${REDIS_PASSWORD:}
21    timeout: 5000
22    lettuce:
23      pool:
24        max-active: 8
25        max-idle: 8
26
27# MyBatis-Plus 설정
28mybatis-plus:
29  mapper-locations: classpath*:mapper/**/*.xml
30  type-aliases-package: com.nbcio.modules.*.entity
31  configuration:
32    map-underscore-to-camel-case: true
33    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
34
35# Shiro 설정
36shiro:
37  token:
38    secret: ${JWT_SECRET:nbcio-secret-key}
39    expire-time: 7200

애플리케이션 시작 프로세스

  1. Spring Boot 초기화: @SpringBootApplication 진입점 실행, 컴포넌트 스캔 시작
  2. 데이터소스 구성: Druid 빈 생성, 커넥션 풀 초기화, DB 연결 테스트
  3. Redis 연결: Lettuce 클라이언트 구성, 연결 풀 생성, ping 테스트
  4. Shiro 보안 초기화: ShiroConfig 실행, SecurityManager, Realm, FilterChain 정의
  5. MyBatis-Plus 스캔: Mapper 인터페이스 프록시 생성, XML 매퍼 로드
  6. Quartz 스케줄러 시작: SchedulerFactoryBean 초기화, 작업 로드, 트리거 활성화
  7. Swagger 문서화: API 엔드포인트 스캔, UI 페이지 생성
  8. 내장 서버 시작: Tomcat/Undertow 포트 바인딩, 요청 대기 상태 진입

시작 실패 시나리오 및 대응:

  • DB 연결 실패: 드라이버 클래스 확인, 네트워크/방화벽 점검, 인증 정보 검증
  • Redis 연결 실패: Redis 서버 상태 확인, 비밀번호/포트 설정 검토
  • 포트 충돌: server.port 변경 또는 기존 프로세스 종료
  • 순환 의존: @Lazy 어노테이션으로 지연 초기화 또는 구조 재설계

아키텍처 확장성 및 제약사항

수평 확장 지원

현재 아키텍처는 다음과 같은 수평 확장 시나리오를 지원한다:

  • Stateless API 서버: JWT 기반 인증으로 세션 동기화 불필요, 로드 밸런서 뒤에 다중 인스턴스 배치 가능
  • Redis 클러스터링: Redis Sentinel 또는 Cluster 모드로 캐시 고가용성 확보
  • DB 읽기 복제: MyBatis-Plus의 다중 데이터소스 라우팅으로 읽기/쓰기 분리 가능
  • 분산 스케줄링: Quartz 클러스터 모드로 작업 중복 실행 방지

알려진 제약사항

  1. Java 8 종속: 가상 스레드(Virtual Threads), 레코드(Records), 패턴 매칭 등 Java 17+ 기능 사용 불가
  2. 단일 모놀리식 구조: 마이크로서비스 분리를 위해서는 추가 아키텍처 리팩토링 필요
  3. 동기식 I/O 모델: WebFlux/Reactive 스택이 아니므로 높은 동시성에서는 스레드 풀 튜닝 필수
  4. Fastjson 보안 이슈: 과거 취약점 이력이 있으므로 최신 버전 유지 또는 Jackson 마이그레이션 권장
  5. 국산 DB 호환성: 일부 고급 기능(예: JSON 타입, CTE)은 DB 벤더마다 지원 차이 존재

권장 개선 방향

  • Spring Boot 3.x 마이그레이션: Java 17+ 전환, 네이티브 컴파일, 가상 스레드 활용
  • Spring Security 전환: OAuth2, SAML, OIDC 등 현대적 인증 프로토콜 지원 강화
  • 모듈화: 도메인 기반 멀티모듈 구조로 전환, 경계 컨텍스트(Bounded Context) 명확화
  • 관찰 가능성 강화: Micrometer, Prometheus, Grafana로 메트릭/트레이싱/로깅 통합
  • 컨테이너 네이티브: Docker/Kubernetes 친화적 설정, 헬스 체크, 그레이스풀 셧다운 구현