Files
bio_backend/README.md
2025-08-13 17:02:40 +09:00

199 lines
6.0 KiB
Markdown

# Bio Backend
## 기술 스택
- **Framework**: Spring Boot
- **Database**: PostgreSQL
- **ORM**: Spring Data JPA + QueryDSL
- **Security**: Spring Security + JWT
- **Build Tool**: Gradle
- **Container**: Docker + Kubernetes
- **API Documentation**: Swagger (SpringDoc OpenAPI)
## 개발 가이드
### 1. 프로젝트 구조
```
src/main/java/com/bio/bio_backend/
├── domain/ # 도메인별 패키지
│ └── user/
│ └── member/ # 회원 도메인
│ ├── controller/ # API 엔드포인트
│ ├── service/ # 비즈니스 로직
│ ├── repository/ # 데이터 접근
│ ├── entity/ # JPA 엔티티
│ └── dto/ # 데이터 전송 객체
├── global/ # 공통 설정
│ ├── config/ # 설정 클래스
│ ├── security/ # 보안 설정
│ ├── exception/ # 예외 처리
│ └── utils/ # 유틸리티
└── BioBackendApplication.java
```
### 2. API 응답 표준화 (CustomApiResponse)
#### 응답 구조
모든 API 응답은 `CustomApiResponse<T>` 형태로 표준화되어 있습니다.
```java
public class CustomApiResponse<T> {
private int code; // HTTP 상태 코드
private String message; // 응답 메시지 (ApiResponseCode enum 값)
private String description; // 응답 설명
private T data; // 실제 데이터 (제네릭 타입)
}
```
#### 응답 예시
**성공 응답 (201 Created)**
```json
{
"code": 201,
"message": "COMMON_SUCCESS_CREATED",
"description": "Created successfully",
"data": {
"seq": 1,
"userId": "user123",
"name": "홍길동"
}
}
```
**실패 응답 (409 Conflict)**
```json
{
"code": 409,
"message": "USER_ID_DUPLICATE",
"description": "User ID already exists",
"data": null
}
```
#### 사용 방법
**Controller에서 응답 생성**
```java
@PostMapping("/members")
public ResponseEntity<CustomApiResponse<CreateMemberResponseDto>> createMember(@RequestBody CreateMemberRequestDto requestDto) {
// ... 비즈니스 로직 ...
// 성공 응답
CustomApiResponse<CreateMemberResponseDto> apiResponse =
CustomApiResponse.success(ApiResponseCode.COMMON_SUCCESS_CREATED, responseDto);
return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
}
```
**공용 응답 코드 사용**
```java
// ApiResponseCode.java
public enum ApiResponseCode {
// 공용 성공 코드
COMMON_SUCCESS_CREATED(HttpStatus.CREATED.value(), "Created successfully"),
COMMON_SUCCESS_UPDATED(HttpStatus.OK.value(), "Updated successfully"),
COMMON_SUCCESS_DELETED(HttpStatus.OK.value(), "Deleted successfully"),
COMMON_SUCCESS_RETRIEVED(HttpStatus.OK.value(), "Retrieved successfully"),
// 공용 오류 코드
COMMON_BAD_REQUEST(HttpStatus.BAD_REQUEST.value(), "Required request body is missing or Error"),
COMMON_UNAUTHORIZED(HttpStatus.UNAUTHORIZED.value(), "Unauthorized"),
COMMON_FORBIDDEN(HttpStatus.FORBIDDEN.value(), "Access is denied"),
COMMON_NOT_FOUND(HttpStatus.NOT_FOUND.value(), "Resource is not found"),
COMMON_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An error occurred on the server")
}
```
#### 핵심 규칙
- **모든 API 응답**: `CustomApiResponse<T>`로 감싸서 반환
- **공용 응답 코드**: `COMMON_` 접두사로 시작하는 범용 코드 사용
- **일관된 구조**: `code`, `message`, `description`, `data` 필드로 표준화
- **제네릭 활용**: `<T>`를 통해 다양한 데이터 타입 지원
### 3. API 문서화 (Swagger)
#### Swagger UI 접속
- **URL**: `http://localhost:8080/service/swagger-ui.html`
- **API Docs**: `http://localhost:8080/service/api-docs`
#### 주요 어노테이션
```java
@Tag(name = "Member", description = "회원 관리 API")
@Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "회원 가입 성공",
content = @Content(schema = @Schema(implementation = CustomApiResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터",
content = @Content(schema = @Schema(implementation = CustomApiResponse.class))),
@ApiResponse(responseCode = "409", description = "중복된 사용자 정보",
content = @Content(schema = @Schema(implementation = CustomApiResponse.class)))
})
```
#### 설정 파일
- **SwaggerConfig.java**: OpenAPI 기본 정보 설정
- **application.properties**: Swagger UI 커스터마이징
### 4. 트랜잭션 관리
#### 기본 설정
```java
@Service
@Transactional(readOnly = true) // 클래스 레벨: 읽기 전용 기본값
public class MemberServiceImpl {
// 읽기 전용 메서드 (별도 어노테이션 불필요)
public MemberDto selectMember(long seq) { ... }
// 쓰기 작업 메서드 (개별 @Transactional 적용)
@Transactional
public MemberDto createMember(MemberDto dto) { ... }
}
```
#### 핵심 규칙
- **클래스 레벨**: `@Transactional(readOnly = true)` 기본 설정
- **메서드별**: 데이터 수정 시에만 `@Transactional` 개별 적용
- **설정**: `spring.jpa.open-in-view=false` (성능 최적화)
### 5. 오류 등록 및 사용
#### 오류 코드 등록
```java
// ApiResponseCode.java
public enum ApiResponseCode {
USER_ID_DUPLICATE(HttpStatus.CONFLICT.value(), "User ID already exists"),
}
```
#### 오류 사용 방법
```java
// Service에서 예외 발생
throw new ApiException(ApiResponseCode.USER_ID_DUPLICATE);
// Controller에서 예외 처리 (자동)
// GlobalExceptionHandler가 ApiException을 잡아서 응답 변환
```
#### 핵심 규칙
- **오류 코드**: `ApiResponseCode` enum에 모든 오류 정의
- **예외 클래스**: `ApiException`으로 비즈니스 로직 예외 처리
- **자동 처리**: `GlobalExceptionHandler`가 일관된 응답 형태로 변환