천체 관측 사진을 업로드하고 관리하는 백엔드 API 서버
- EXIF 메타데이터를 자동으로 추출하여 촬영 정보를 체계적으로 관리
- 위치 기반 검색을 통해 특정 지역에서 촬영한 사진을 쉽게 찾기
- 카메라 프리셋을 통해 천체 촬영에 최적화된 설정값 제공
- 광해 정보 및 별 관측 가능성을 제공하여 촬영 장소 선택 지원
- Java 21
- Spring Boot 3.5.4
- Spring Security - 인증/인가
- Spring Data JPA - 데이터베이스 ORM
- Spring OAuth2 Client - 소셜 로그인
- JWT (jjwt 0.11.5) - 토큰 기반 인증
- Metadata Extractor 2.18.0 - EXIF 메타데이터 추출
- SpringDoc OpenAPI 2.8.9 - API 문서화 (Swagger)
- Lombok - 보일러플레이트 코드 감소
- WebFlux - 비동기 HTTP 클라이언트 (WebClient)
- MySQL 8.0
- Kakao Map API - 좌표를 주소로 변환 (역지오코딩)
- 광해 정보 API - 위치 기반 광해 정보 조회
- 별 관측 가능성 API - 구름량 및 광해량 기반 관측 가능성 계산
- Gradle - 의존성 관리 및 빌드
[Frontend]
↓ HTTP/REST
[Spring Boot Backend]
↓
[MySQL Database] [Kakao Map API] [광해/관측 API]
Controller Layer (REST API)
↓
Service Layer (비즈니스 로직)
↓
Repository Layer (데이터 접근)
↓
Domain Layer (엔티티)
주요 패키지 구조:
photo- 사진 관리 (업로드, 조회, 수정, 삭제)camera- 카메라 프리셋 조회 및 모델 관리location- 위치 정보 관리 및 주소 변환user- 사용자 프로필 및 위치 관리oauth2- OAuth2 소셜 로그인 (Google, Naver, Kakao)light- 광해 정보 조회visible- 별 관측 가능성 조회common- 공통 기능 (JWT, Security, Exception Handler)infra- 외부 서비스 연동 (Kakao Map API)
- 소셜 로그인:
GET /oauth2/authorization/{provider}(Google, Naver, Kakao) - 사용자 정보 조회:
GET /api/user/me - 로그아웃:
POST /api/user/logout - JWT 토큰 기반 인증
- 사진 업로드:
POST /api/photos(EXIF 자동 추출) - 사진 메타데이터 조회:
GET /api/photos/{id} - 사진 목록 조회 (시/도 기반):
GET /api/photos?sido={시도명} - 사진 위치 수정:
PATCH /api/photos/{id} - 사진 댓글 수정:
PATCH /api/photos/{id}/comment - 사진 삭제:
DELETE /api/photos/{id}
- 카메라 모델 목록 조회:
GET /api/cameras/models - 카메라 프리셋 조회:
GET /api/cameras/models/{id}?target={TARGET} - Samsung 모델 코드 자동 변환 (SM-G991 → Galaxy S21)
- 사용자 위치 업데이트:
PATCH /api/users/location - 사용자 위치 조회:
GET /api/users/location
- 광해 정보 조회:
GET /api/lightpollution?lat={lat}&lon={lon}
- 별 관측 가능성 조회:
GET /api/stars/visibility?lat={lat}&lon={lon}&hoursAhead={hours}
- EXIF 메타데이터 자동 추출: 사진 업로드 시 촬영 설정값, GPS 좌표, 카메라 정보 자동 추출
- 위치 정보 자동 변환: GPS 좌표를 카카오 맵 API를 통해 주소로 자동 변환
- Samsung 모델 코드 변환: 정규표현식과 매핑 테이블을 활용한 스마트한 모델명 변환
- OAuth2 소셜 로그인: Google, Naver, Kakao 소셜 로그인 지원
- JWT 기반 인증: Access Token 및 Refresh Token을 통한 인증/인가
- 권한 검증: 사용자별 리소스 접근 권한 검증
- 전역 예외 처리: 일관된 에러 응답 형식 제공
실행 방법 상세 가이드 (클릭하여 펼치기)
- Java 21 이상
- Gradle 7.x 이상 (또는 Gradle Wrapper 사용)
- MySQL 8.0 이상
프로젝트 루트에 .env 파일 생성:
# MySQL
LOCAL_DB_HOST=localhost
LOCAL_DB_PORT=3306
LOCAL_DB_NAME=your_database_name
LOCAL_DB_USERNAME=your_username
LOCAL_DB_PASSWORD=your_password
# JWT
JWT_SECRET_KEY=your-secret-key-min-256-bits
JWT_ACCESS_EXPIRATION=3600000
JWT_REFRESH_EXPIRATION=86400000
# OAuth2 - Google
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# OAuth2 - Naver
NAVER_CLIENT_ID=your_naver_client_id
NAVER_CLIENT_SECRET=your_naver_client_secret
# OAuth2 - Kakao
KAKAO_CLIENT_ID=your_kakao_client_id
KAKAO_CLIENT_SECRET=your_kakao_client_secret
# Kakao Map API
KAKAO_APP_SECRET=your_kakao_app_secret
# Base URL
BASE_URL=http://localhost:8080/CREATE DATABASE your_database_name;./gradlew build
java -jar build/libs/backend-0.0.1-SNAPSHOT.jar애플리케이션은 http://localhost:8080에서 실행됩니다.
애플리케이션 실행 후 다음 URL에서 API 문서 확인:
http://localhost:8080/swagger-ui.html
사진 파일은 기본적으로 ./uploads 디렉토리에 저장됩니다.
application.yml의 app.storage.base-dir 설정으로 변경 가능합니다.
real/
├── src/
│ ├── main/
│ │ ├── java/com/meamappacaelestis/backend/
│ │ │ ├── camera/ # 카메라 및 프리셋 관리
│ │ │ │ ├── domain/ # Device, CameraPreset, Brand, Target
│ │ │ │ ├── dto/ # CameraModel, CameraModelList, CameraPresetResponse
│ │ │ │ ├── repository/ # DeviceRepository, CameraPresetRepository
│ │ │ │ ├── DeviceController.java
│ │ │ │ ├── DeviceService.java
│ │ │ │ ├── SamsungModelMapper.java
│ │ │ │ └── SamsungDeviceProps.java
│ │ │ │
│ │ │ ├── photo/ # 사진 관리
│ │ │ │ ├── domain/ # Photo 엔티티
│ │ │ │ ├── dto/ # PhotoUploadResponse, PhotoMetadataDto, PhotoSimpleDto
│ │ │ │ ├── exception/ # PhotoNotFoundException, PhotoExceptionHandler
│ │ │ │ ├── infra/ # ExifExtractor, ParsedMeta
│ │ │ │ ├── PhotoController.java
│ │ │ │ ├── PhotoService.java
│ │ │ │ └── PhotoRepository.java
│ │ │ │
│ │ │ ├── location/ # 위치 정보 관리
│ │ │ │ ├── domain/ # Location 엔티티
│ │ │ │ ├── dto/ # LocationResult
│ │ │ │ ├── exception/ # LocationNotFoundException, LocationExceptionHandler
│ │ │ │ ├── LocationService.java
│ │ │ │ └── LocationRepository.java
│ │ │ │
│ │ │ ├── user/ # 사용자 관리
│ │ │ │ ├── domain/ # User, UserRole
│ │ │ │ ├── dto/ # LocationRequestDto, LocationResponseDto
│ │ │ │ ├── exception/ # UserNotFoundException
│ │ │ │ ├── repository/ # UserRepository
│ │ │ │ ├── UserController.java
│ │ │ │ └── UserService.java
│ │ │ │
│ │ │ ├── oauth2/ # OAuth2 인증
│ │ │ │ ├── controller/ # AuthController
│ │ │ │ ├── handler/ # OAuth2LoginSuccessHandler, OAuth2LoginFailureHandler
│ │ │ │ ├── service/ # CustomOAuth2UserService, JwtService
│ │ │ │ ├── principal/ # PrincipalDetails, CustomUserDetails
│ │ │ │ ├── userinfo/ # OAuth2UserInfo, GoogleOAuth2UserInfo, NaverOAuth2UserInfo, KakaoOAuth2UserInfo
│ │ │ │ ├── CustomOAuth2User.java
│ │ │ │ └── OAuthAttributes.java
│ │ │ │
│ │ │ ├── light/ # 광해 정보 조회
│ │ │ │ ├── controller/ # LightPollutionController
│ │ │ │ ├── dto/ # LightPollutionApiResponse, LightPollutionInfo
│ │ │ │ └── service/ # LightPollutionService
│ │ │ │
│ │ │ ├── visible/ # 별 관측 가능성 조회
│ │ │ │ ├── controller/ # StarVisibilityController
│ │ │ │ ├── dto/ # StarVisibilityResponse
│ │ │ │ └── service/ # StarVisibilityService
│ │ │ │
│ │ │ ├── infra/ # 외부 서비스 연동
│ │ │ │ └── kakaoMap/ # KakaoLocationService, KakaoLocationResponse, Document, Meta
│ │ │ │
│ │ │ ├── common/ # 공통 기능
│ │ │ │ ├── config/ # SecurityConfig, SwaggerConfig, RestTemplateConfig, WebClientConfig
│ │ │ │ ├── filter/ # JwtAuthenticationFilter, JwtAuthenticationProcessingFilter
│ │ │ │ ├── util/ # JwtUtil, PasswordUtil
│ │ │ │ ├── ErrorResponse.java
│ │ │ │ ├── GlobalExceptionHandler.java
│ │ │ │ └── SocialType.java
│ │ │ │
│ │ │ └── BackendApplication.java
│ │ │
│ │ └── resources/
│ │ └── application.yml
│ │
│ └── test/
│ └── java/com/meamappacaelestis/backend/
│ └── BackendApplicationTests.java
│
├── build.gradle
├── settings.gradle
├── gradlew
├── gradlew.bat
└── README.md