Developer Manual · 개발 매뉴얼

backend — REST API 서버 (Historian)

historian (제품명 Factory Sight) 백엔드. 공장(Machine)→공정(Process)→태그(Tag) 계층의 시계열 데이터를 수집·집계·분석하고, 알람·알림·대시보드·에디터·모니터링·Excel 입출력을 제공하는 Spring Boot 애플리케이션.

☕ Java 21 🍃 Spring Boot 3.4.4 📦 Maven 🗄 MyBatis + JPA 🗓 작성일 2026-06-29

1개요

정체성. pom.xml<description>LSITC Historian</description> — LS ITC가 개발한 제조 설비 데이터 히스토리안/모니터링·분석 플랫폼의 백엔드. README는 개발 환경 셋업 위주로, 비즈니스 개요 문서는 부재하여 정체성은 코드로 확인.

Java 소스
830 개
REST 컨트롤러
65 개
MyBatis XML
67 개
JPA 엔티티
48 개
테스트 클래스
121 개
DB 테이블
38 (+2)

2빠른 시작 · 실행

./mvnw setup            # (initialize) Git Hook 설치 — 단, Windows(setup-hooks.cmd) 하드코딩 주의
./mvnw clean verify     # 빌드 + 테스트 + JaCoCo
./mvnw spring-boot:run  # 로컬 실행 → http://localhost:8080
./mvnw spotless:apply   # Google Java Style 포맷
서버 포트
8080
프로파일
local / dev / prod
멀티파트 최대
1 GB
비동기 타임아웃
600 s
ℹ️ 프로파일 오버레이
Maven이 src/main/resources-${environment}(local/dev/prod)를 필터링 리소스로 오버레이한다. Flyway/Liquibase 없이 db/V1/*.sql을 수작업 적용해야 스키마가 준비된다(ddl-auto: validate라 불일치 시 기동 실패).

3아키텍처 — 두 스타일 공존

⚠️ 마이그레이션 과도기
동일 코드베이스에 레거시 MVC(MyBatis, 빈약 도메인)헥사고날(JPA, 리치 도메인)이 혼재한다.

3.1 레거시 MVC api.* (다수)

api/{도메인}/ controller/ @RestController service/impl/ ServiceImpl (대부분 DAO로 1:1 위임 — 비즈니스 로직 빈약) dao/ @Mapper (MyBatis) vo/ POJO (입력·출력 겸용, 영속성 애너테이션 없음)

도메인: factory·dashboard·analytics·alarm·editor·monitoring·excel·system·user·login·influxdb·custom 등.

3.2 헥사고날/클린 menu · user · notification · role · thirdParty (신규)

{도메인}/ domain/ 리치 도메인 모델 + 값 객체(VO) application/service/ UseCase 구현, port 의존 adapter/in/web/ 컨트롤러(어댑터) adapter/out/persistence/ JPA 엔티티 + Repository + 도메인↔엔티티 매퍼

user 도메인은 Password·PasswordPolicy·LoginAttempts·Email·Username·UserStatus 값 객체로 풍부하게 모델링.

3.3 공통/횡단

config/(Security·Jpa·Mybatis·Influxdb·JdbcTemplates·Web) · aop/(CommonResponseBodyAdvice 응답 래핑, TransactionAspect) · exception/(GlobalExceptionHandler) · interceptor/(감사 필드 주입) · security/ · common/(response, DatabaseMessageSource i18n).

4데이터베이스

스키마 · 명명 규칙

  • 버전 관리 도구 없음 — Flyway/Liquibase 미사용, db/V1/Factory Sight v1.0.0-DDL/DML.sql 수작업 관리.
  • 문자셋 전 테이블 utf8mb4_unicode_ci. PK {ENTITY}_NO(AUTO_INC), 비즈니스 키 {ENTITY}_ID(UUID 추정), 코드 {도메인}_CD.
  • 소프트 삭제 IS_DELETED + 감사 컬럼(CREATED_BY/DATE 등).
⚠️ 일관성 부족
Boolean 표현이 레거시 'Y'/'N'(char)와 신규 0/1(tinyint)로 혼재.

주요 테이블 도메인 (v1.0.0, 38개)

도메인테이블(예)
공장/설비h_machine, h_process(계층), h_tag(LSL/USL/LCL/UCL)
알람h_tag_alarm_rule, h_tag_alarm_log, h_multi_alarm_rule(표현식), alarm_status
사용자/권한/메뉴h_user(BCrypt), h_auth, h_user_auth, h_auth_menu, h_menu(계층), h_user_conn_hist
데이터셋/프리셋h_dataset, h_preset, h_file
시각화h_editor, h_editor_layer, h_monitoring, h_user_monitoring
시스템h_code_type, h_code, h_language, system_env, tag_unit

v1.0.1 추가: api_token(외부 API 토큰), external_api_log(호출 감사).

🔴 이중 트랜잭션 매니저
MyBatis transactionManager(@Primary)와 JPA jpaTransactionManager 2개가 동일 DataSource에 존재. 레거시·신규 모듈을 한 논리 트랜잭션에서 호출 시 롤백 동기화가 보장되지 않을 수 있다.

5API 엔드포인트

65개 컨트롤러. 내부 API와 외부(X-API-KEY) API로 나뉜다.

내부 API

영역대표 컨트롤러
인증AuthController, LoginController (login, loginByXApiKey, refresh-token)
공장Machine/Process/Tag Controller + Mgmt
분석RawData, TagTrend, CorrelationRegression, HistogramBoxPlot, MultiHistogram, ParallelCoordinate
알람/알림TagAlarm, MultiAlarm, SopAlarm, Alert, Channel
모니터링/에디터Dashboard, MonitoringMgmt/Viewer, Editor, EditorLayerCondition
시스템User·AuthMgmt·CodeMgmt·Language·ApiToken·SystemEnv
Excel/커스텀ExcelExport/Upload, Gnp*, SbCpkDetlRead, QueryExplorer

외부 API /external/api/v1/** — X-API-KEY

  • ExternalRawDataController(원시 시계열), ExternalAggrController(집계 mean/min/max/median, windowPeriod 10s~12h)
  • 마스터: Machine/Tags/Process/VirtualTag/TagAlarms/AlarmEvents. 응답은 ExternalResponse(내부 CommonResponse와 별도) + 전용 예외 핸들러 + Swagger 그룹(X-API-KEY).
ℹ️ 응답 표준화
CommonResponseBodyAdvice가 모든 성공 응답을 CommonResponse(true,"SUCCESS",...)로 래핑. 단 swagger·/external/api·/api/v1/alerts/notify·byte[]·ErrorResponse는 제외.

6인증 · 보안 중요

SecurityConfig

STATELESS 세션, CSRF/formLogin 비활성. 필터 순서 XApiKeyFilter → JwtAuthFilter → UsernamePasswordAuthenticationFilter. permitAll: /auth/login·logout·refresh-token, swagger, 공통 파일, /api/v1/system/codes, /api/v1/alerts/notify, /external/api/**.

🔴 CRITICAL — 권한 우회
JwtAuthFilter모든 인증 사용자에게 ROLE_ADMIN을 일괄 부여(SimpleGrantedAuthority("ROLE_ADMIN") 고정). DB에 h_auth/h_user_auth/h_auth_menu 권한 모델이 있으나 시큐리티 인가에 연결되지 않는다. QueryExplorer의 임의 SQL 실행과 결합 시 위험 증폭.
🔴 CRITICAL — 시크릿 평문 하드코딩
모든 프로파일 YML에 DB 비밀번호·JWT 시크릿(128자 hex, 전 프로파일 동일)·InfluxDB 토큰·내부 IP가 평문 커밋됨. Jasypt 의존성은 있으나 ENC() 미적용. 본 매뉴얼엔 값 미기재. → 환경변수/Vault 분리 + 즉시 로테이션.
⚠️ HIGH — JWT 만료 하드코딩
JwtProvider에서 만료가 상수로 박혀 application.ymljwt.*Expiration무시된다. 액세스 =24시간(설정은 1시간), 리프레시 ≈48일(설정은 3일). 설정-구현 불일치.
⚠️ HIGH — 리프레시 토큰 인메모리
security/token/RefreshTokenstatic ConcurrentHashMap 저장 → 재시작 시 소실, 다중 인스턴스 불가, 정리 부재(누수). removeUserRefreshTokenentry.getValue() == userId 참조 비교 버그(.equals() 미사용)로 제거가 사실상 무동작. 토큰 회전 로직은 주석 처리됨.
✅ 상대적 양호 — 비밀번호/잠금
BCrypt 해시, LoginAttempts.MAX_ATTEMPTS=5 5회 실패 시 계정 잠금(관리자 수동 해제). 검증 로직이 user 헥사고날 도메인에 잘 캡슐화됨.

7외부 연동

대상용도 / 특징
InfluxDBOkHttp 풀(40, 5분), raw/aggr/custom 버킷별 클라이언트. Flux DSL 필터, windowPeriod에 따라 버킷 자동 선택. InfluxdbUtil: 보간·이상치 제거·8종 기초통계.
Teams 알림WebClient(Reactor Netty) Incoming Webhook. ⚠️ InsecureTrustManagerFactory로 SSL 검증 비활성 — 보안 약점.
외부 알람 서버alarm.address: http://10.123.202.120:8082 (edge-processor 알림 수신 측)
멀티 데이터소스
(thirdParty)
JdbcTemplatesConfig 동적 DS(MySQL/MariaDB/PG/MSSQL/Oracle/SQLite). QueryExplorer가 임의 SQL 실행 — 인가 통제 필수.

8설정 · 프로파일

  • Maven 프로파일 local/dev/prodresources-${env} 오버레이. test는 H2(application-test.yml).
  • JPA ddl-auto: validate, open-in-view: false(권장), default_batch_fetch_size: 2000.
  • MyBatis map-underscore-to-camel-case, default-executor-type: reuse, stdout SQL 로깅. PageHelper(mysql), springdoc Swagger.
  • WebConfig 비동기 응답 타임아웃 600초(대용량 Excel/파일 스트리밍 대비).

9빌드 · 배포

  • Maven Wrapper, ${revision}${changelist} CI 버전(flatten-maven-plugin). Spotless(Google Style) 강제, Git Hook 자동 설치.
  • CI(.gitlab-ci.yml): test(mvn verify + JaCoCo) → build(develop/tags) → deploy(수동).
  • 배포: jar 백업 후 /opt/factorysight/backend 복사, 소유자 fsuser, systemctl restart factorysight-backend.service. systemd 단일 서버 방식(컨테이너 아님).
⚠️ 이식성
Git Hook 설치가 cmd /c setup-hooks.cmd Windows 전용 하드코딩. README는 setup-hooks.sh를 안내하나 해당 파일은 저장소에 부재.

10기술 부채 · 개선 과제

#항목심각도
1모든 사용자 ROLE_ADMIN 일괄 부여 제거 → DB 권한 모델과 인가 연동CRITICAL
2평문 비밀정보(DB PW·JWT·Influx 토큰) YML 분리 + 로테이션CRITICAL
3리프레시 토큰 인메모리→Redis(TTL), == 버그 수정, 회전 활성화HIGH
4외부 API 로그의 API 키 평문 저장 → 마스킹/해시HIGH
5Teams Webhook InsecureTrustManagerFactory 제거(SSL 검증)MEDIUM
6JWT 만료 하드코딩 상수 제거 → 설정값 일치MEDIUM
7이중 트랜잭션 매니저 → 단일(JPA)로 수렴MEDIUM
8수작업 SQL → Flyway/Liquibase, Boolean(Y/N vs 0/1) 표준화MEDIUM

11신규 개발자 가이드

읽는 순서

  1. config/SecurityConfig.java + security/filter/{JwtAuthFilter,XApiKeyFilter}.java — 인증 흐름(그리고 §6 결함 인지)
  2. config/{MybatisConfig,JpaConfig,InfluxdbConfig}.java — 이중 ORM·트랜잭션 구조
  3. aop/CommonResponseBodyAdvice.java + exception/GlobalExceptionHandler.java — 응답·예외 표준
  4. 레거시 예: api/factory/machine/* (Controller→ServiceImpl→Mapper→Vo)
  5. 헥사고날 예: menu/ 또는 user/ (domain→application→adapter)
  6. api/external/** — 외부 API·X-API-KEY
  7. db/V1/*.sql — 스키마 전체
✅ 강점
신규 모듈의 헥사고날+리치 도메인+값 객체 설계, 표준 응답 래핑·전역 예외·DB 기반 i18n·감사 필드 자동 주입 등 횡단 관심사 정리, Spotless·CI·JaCoCo·테스트 121개로 품질 기반 마련.