Backend

[Backend] 백엔드 API 구현

teddy bear 2026. 7. 5. 13:17
반응형

공통 백엔드 API를 만나다 — 인증·공간데이터·나의 지역을 하나의 Spring Boot로

common-api 프로젝트 소개
Java 15 · Spring Boot 2.7 · PostgreSQL(PostGIS) · Redis


들어가며

3D 공간정보 서비스를 운영하다 보면, 프론트엔드가 호출해야 할 API가 자연스럽게 여러 갈래로 나뉩니다. 로그인과 권한, 사용자가 직접 올린 Shapefile, 관심 지역(나의 지역) 이미지까지 — 각각 별도 서비스로 쪼개면 배포·인증·공통 응답 형식을 매번 맞춰야 합니다.

gygo-svc3d-back-common-api는 이런 요구를 단일 Spring Boot 애플리케이션으로 묶은 GYGO 3D 서비스의 공통 백엔드입니다. 설정상 서비스명은 auth-service이지만, 실제로는 인증·권한뿐 아니라 UserForge(사용자 맞춤 데이터셋)user-loc(나의 지역) 까지 함께 제공합니다.

이 글에서는 이 프로젝트가 무엇을 하는지, 어떻게 구성되어 있는지, 개발자 관점에서 어떤 점이 특징적인지 정리합니다.


한눈에 보는 역할

영역Base Path설명

인증·권한 /auth-service JWT 로그인/로그아웃/토큰 검증, WeLand·지자체 Key SSO, 역할·메뉴·API 권한
UserForge /api/user-datasets Shapefile/ZIP 업로드, GeoJSON 미리보기, 레코드 CRUD, 셰이프파일 다운로드
나의 지역 /user-loc-service 사용자 관심 장소 등록·조회·수정·삭제, 이미지 첨부
템플릿 /template-service 템플릿 연동용 엔드포인트

진입점은 lx.svcauth.SvcAuthApplication 하나이며, lx.svcauth, lx.gygo, gygo 패키지를 스캔합니다.

@SpringBootApplication(scanBasePackages = {"lx.svcauth", "lx.gygo", "gygo"})
public class SvcAuthApplication {
    public static void main(String[] args) {
        SpringApplication.run(SvcAuthApplication.class, args);
    }
}

아키텍처 개요

┌─────────────────────────────────────────────────────────────┐
│              gygo-svc3d-back-common-api (Spring Boot)        │
├──────────────┬────────────────────┬───────────────────────────┤
│ lx.svcauth   │ lx.gygo.userdataset│ lx.gygo.userloc          │
│ Auth/Security│ UserForge API      │ 나의 지역 API             │
│ 공통 ResStd  │ Shapefile·GeoJSON  │ 이미지 스토리지           │
└──────┬───────┴─────────┬──────────┴───────────┬─────────────┘
       │                 │                      │
       ▼                 ▼                      ▼
   PostgreSQL         파일 스토리지            NAS/로컬 경로
   (PostGIS, gygo)    (userforge.storage)     (userloc.storage)
       │
       ▼
     Redis (캐시·세션)

왜 모놀리식인가?

  • 공통 응답·예외 처리를 AbstractRestHandler 한 곳에서 통일
  • 사용자 식별(UserIdResolver)을 JWT·개발용 헤더로 일관되게 적용
  • 3D 포탈·운영포탈이 이미 reqId 기반 단일 엔드포인트(/auth-service/auth)에 익숙함
  • Shapefile 처리처럼 DB + 파일 I/O가 섞인 작업을 트랜잭션 경계 안에서 다루기 쉬움

마이크로서비스로 쪼개는 것보다 운영 포탈·3D 사용자 포탈이 실제로 쓰는 API 묶음에 맞춘 실용적인 선택에 가깝습니다.


1. 인증·권한 — reqId 하나로 20가지 이상의 업무

인증 API의 특징은 URL 하나, 본문의 reqId로 분기한다는 점입니다.

POST /auth-service/auth
Content-Type: application/json

{
  "reqId": "AUTH_REQ001",
  "reqData": { ... }
}

AuthController는 reqId 값에 따라 로그인, 로그아웃, 토큰 검증, SSO, 역할·메뉴·API 권한 조회 등을 라우팅합니다.

reqId (예)역할

AUTH_REQ001 로그인 및 JWT 발급
AUTH_REQ002 로그아웃
AUTH_REQ003 리프레시/액세스 토큰 검증·재발급
AUTH_REQ004 WeLand SSO
AUTH_REQ005 지자체 Key SSO (RSA 복호화)
AUTH_REQ007 ~ AUTH_REQ020 역할, 메뉴, API 권한, 3D 전용 메뉴 등
AUTH_REQ101 ~ AUTH_REQ104 개발지원(SPTDEV) 전용 변형

SSO 연동

  • WeLand SSO: ssoToken 기반 포탈 연동 (AUTH_REQ004)
  • Key SSO: 지자체에 RSA 공개키를 제공하고, 암호화된 사용자 ID를 복호화 (AUTH_REQ005)
  • WiseAccess(WAJavaAPI), lxkeyiden JAR을 exlibs/에서 로컬 의존성으로 참조

JWT + Redis

  • JJWT로 액세스·리프레시 토큰 발급
  • Spring Security + 커스텀 AuthenticationEntryPoint / AccessDeniedHandler
  • Redis 캐시로 세션·토큰 관련 상태 관리

레거시 포탈과의 호환을 유지하면서, Spring Security 생태계의 필터 체인을 그대로 활용하는 구조입니다.


2. UserForge — 사용자 맞춤 공간 데이터셋

3D 포탈에서 사용자가 직접 Shapefile/ZIP을 올려 지도 위에 올리고, 속성을 편집하는 기능이 UserForge입니다. 패키지는 lx.gygo.userdataset, API prefix는 /api/user-datasets입니다.

할 수 있는 일

  • 데이터셋 목록·검색·상세·즐겨찾기
  • Shapefile ZIP 업로드 → 미리보기 → 본 저장 2단계 플로우
  • DBF 속성 스키마 조회, geometry만 또는 geometry+속성 미리보기
  • 필드 추가·삭제·이름 변경·순서 변경, 레코드 CRUD
  • 저장된 Shapefile을 ZIP으로 재다운로드

공간 데이터 처리 흐름 (개념)

[클라이언트] ZIP 업로드
      │
      ▼
[서버] ZIP 해제 → .shp/.dbf/.shx 검증
      │
      ├─► 미리보기: geometry → GeoJSON (DB 저장 전)
      │
      └─► 본 저장: 메타 DB + 파일 스토리지 + PostGIS EWKT/GeoJSON

주요 서비스 클래스:

  • UserDatasetService — 데이터셋 생명주기
  • UserDatasetRecordService — 레코드(행) 단위 CRUD
  • ShapefileDbfAttributesService — DBF 스키마·미리보기
  • UserDatasetShapefileImportService — Shapefile 임포트
  • LocalFileStorageService — 로컬/NAS 파일 저장

PostGIS search_path는 "GYGO", public으로 설정되어, 앱 스키마와 PostGIS 함수를 함께 사용합니다. 대표 geometry는 EWKT에서 GeoJSON으로 변환하는 RprsGeomEwktToGeoJson 같은 전용 컴포넌트가 있습니다.

API 규모

데이터셋 API 17개 + 레코드 API 6개 수준으로, Swagger 태그는 UserForge, UserForge Records로 구분됩니다. multipart 업로드(최대 64MB 파일, 1GB 요청)를 전제로 Tomcat post size도 넉넉히 잡혀 있습니다.


3. user-loc — 나의 지역(관심 장소)

lx.gygo.userloc 패키지는 사용자가 자주 보는 지역·장소를 등록하고 이미지를 붙이는 API입니다.

  • Base path: /user-loc-service
  • 헬스 체크: GET /user-loc-service/health
  • CRUD: /list, /create, /update, /delete 등
  • 이미지는 userloc.storage.path 아래 {login}/{plcId}/ 구조로 저장
  • 브라우저 노출 URL은 public-base-url 설정으로 /user-loc-service/files/... 형태

UserForge와 마찬가지로 UserIdResolver로 로그인 사용자를 식별하고, 타 사용자 리소스 접근 시 NotAuthorizedException으로 막습니다.


공통 API 설계 — ResStd와 전역 예외 처리

UserForge·user-loc뿐 아니라 대부분의 API가 ResStd 래퍼로 응답합니다.

{
  "reqId": null,
  "resCode": "P000",
  "resData": { },
  "errCode": null,
  "errMsg": null
}
  • resCode: P000(성공) / P001(실패)
  • errCode: E001(요청값 오류), E005(미인증), E006(미인가), E009(데이터 없음) 등

AbstractRestHandler의 @ControllerAdvice가 예외를 HTTP 상태와 별개로 본문의 errCode로 변환합니다. 클라이언트(운영포탈·3D 포탈)는 오래전부터 이 형식에 맞춰져 있어, 새 도메인 API도 같은 패턴을 따릅니다.

사용자 식별 우선순위

  1. X-User-Id 헤더 — 로컬·통합 테스트용
  2. Spring Security JWT의 username

둘 다 없으면 E005(인증되지 않음)입니다.


기술 스택 정리

분류기술

언어·프레임워크 Java 15, Spring Boot 2.7, Spring Cloud Config/Bus/Sleuth
Spring MVC, WebFlux(WebClient), WebSocket, Validation
데이터 PostgreSQL + PostGIS, JPA + QueryDSL, MyBatis(듀얼 datasource)
캐시 Redis, EhCache
보안 Spring Security, JJWT
문서 SpringDoc OpenAPI (Swagger UI)
품질 SpotBugs, SonarQube Gradle 플러그인
기타 egovframe RTE 일부, javadbf(Shapefile), logstash-logback-encoder

빌드는 Gradle Wrapper, 사내 Nexus Maven 저장소를 사용합니다. 로컬에서 의존성을 받으려면 VPN·사내망 접속이 필요할 수 있습니다.


로컬에서 띄워보기

준비물

  1. JDK 15
  2. Redis — docker compose up -d (프로젝트 루트 docker-compose.yml)
  3. PostgreSQL — 팀 DB 또는 로컬 PostGIS
  4. exlibs/ SSO JAR
  5. 파일 저장 경로 — userforge.storage.path, userloc.storage.path를 본인 환경에 맞게 수정

실행

./gradlew bootRun

기본 프로필은 local (application-local.yml 적용). 기본 포트는 8029입니다.

확인 항목URL 예시

헬스 http://localhost:8029/user-loc-service/health
Swagger UI http://localhost:8029/swagger-ui/index.html
OpenAPI JSON http://localhost:8029/v3/api-docs
인증 POST http://localhost:8029/auth-service/auth

IDE에서는 SvcAuthApplication 실행 + Active profile local이면 됩니다.


배포

Dockerfile은 UBI8 + JDK 15 베이스 이미지 위에 JAR을 올리고, ENV로 Spring profile을 주입합니다.

ENTRYPOINT ["sh", "-c", "java -Dspring.profiles.active=${ENV} -jar /home/gygo-svc3d-back-common-api-0.1.jar"]

프로필은 local, dev, prod, lxdev, lxprod 등 환경별 application-*.yml로 분리되어 있습니다.


개발하면서 느낀 포인트

1. 레거시 호환과 신규 REST의 공존

인증은 reqId 단일 POST, UserForge·user-loc은 RESTful path + HTTP method — 스타일이 다르지만 ResStd·UserIdResolver·예외 코드로 표면을 맞춥니다. 기존 포탈을 깨지 않으면서 3D 전용 기능을 붙이기 좋은 타협입니다.

2. 파일 + DB + 공간 타입

Shapefile은 “파일 시스템 문제”이면서 동시에 “DB geometry 문제”입니다. ZIP 해제, DBF 파싱, EWKT↔GeoJSON, 소유권 검증이 한 서비스 안에서 이어집니다. 이런 도메인은 MSA로 쪼개기보다 한 프로세스에서 트랜잭션·롤백을 명확히 하는 편이 유지보수에 유리한 경우가 많습니다.

3. 문서화

Swagger(SpringDoc) 외에 docs/api-spec.md처럼 운영포탈 API 정의서 양식을 보완한 Markdown 명세도 함께 관리합니다. docs/build_api_docx.py로 Word 정의서 생성까지 자동화할 수 있습니다.

4. 정적 분석

SpotBugs(NP_* 등 null 관련 패턴)와 SonarQube 연동이 Gradle에 포함되어 있습니다. SvcAuthApplication.main에는 CWE-489(Leftover Debug Code) 오탐을 설명하는 주석까지 — 보안 스캔과 실무를 같이 가져가는 흔적이 보입니다.


마치며

gygo-svc3d-back-common-api는 이름과 달리 “인증만 하는 서비스”가 아닙니다. GYGO 3D 생태계에서 반복적으로 필요한 인증·권한·사용자 공간데이터·나의 지역을 한 Spring Boot 앱에 모은 공통 백엔드 허브에 가깝습니다.

  • 포탈 개발자에게는 reqId + ResStd라는 익숙한 계약
  • 3D·지도 기능 개발자에게는 Shapefile·GeoJSON·PostGIS 파이프라인
  • 운영자에게는 Redis·듀얼 DB·프로필 기반 배포

처음 코드베이스를 열었다면 AuthController → UserDatasetController → UserLocController 순으로 훑고, Swagger UI에서 실제 요청 형태를 확인하는 것을 추천합니다.


참고


이 문서는 프로젝트 README·소스 코드·API 명세를 바탕으로 작성되었습니다. 운영 환경의 DB 접속 정보·JWT secret 등은 저장소에 커밋하지 않고 외부 설정으로 주입하는 것을 권장합니다.