kmbin92_2025081302 #3
							
								
								
									
										103
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								README.md
									
									
									
									
									
								
							@@ -32,7 +32,94 @@ src/main/java/com/bio/bio_backend/
 | 
				
			|||||||
└── BioBackendApplication.java
 | 
					└── BioBackendApplication.java
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 2. API 문서화 (Swagger)
 | 
					### 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 접속
 | 
					#### Swagger UI 접속
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,8 +132,12 @@ src/main/java/com/bio/bio_backend/
 | 
				
			|||||||
@Tag(name = "Member", description = "회원 관리 API")
 | 
					@Tag(name = "Member", description = "회원 관리 API")
 | 
				
			||||||
@Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.")
 | 
					@Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.")
 | 
				
			||||||
@ApiResponses(value = {
 | 
					@ApiResponses(value = {
 | 
				
			||||||
    @ApiResponse(responseCode = "201", description = "회원 가입 성공"),
 | 
					    @ApiResponse(responseCode = "201", description = "회원 가입 성공",
 | 
				
			||||||
    @ApiResponse(responseCode = "400", 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)))
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -55,7 +146,7 @@ src/main/java/com/bio/bio_backend/
 | 
				
			|||||||
- **SwaggerConfig.java**: OpenAPI 기본 정보 설정
 | 
					- **SwaggerConfig.java**: OpenAPI 기본 정보 설정
 | 
				
			||||||
- **application.properties**: Swagger UI 커스터마이징
 | 
					- **application.properties**: Swagger UI 커스터마이징
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 3. 트랜잭션 관리
 | 
					### 4. 트랜잭션 관리
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 기본 설정
 | 
					#### 기본 설정
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -79,14 +170,14 @@ public class MemberServiceImpl {
 | 
				
			|||||||
- **메서드별**: 데이터 수정 시에만 `@Transactional` 개별 적용
 | 
					- **메서드별**: 데이터 수정 시에만 `@Transactional` 개별 적용
 | 
				
			||||||
- **설정**: `spring.jpa.open-in-view=false` (성능 최적화)
 | 
					- **설정**: `spring.jpa.open-in-view=false` (성능 최적화)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 4. 오류 등록 및 사용
 | 
					### 5. 오류 등록 및 사용
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 오류 코드 등록
 | 
					#### 오류 코드 등록
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```java
 | 
					```java
 | 
				
			||||||
// ApiResponseCode.java
 | 
					// ApiResponseCode.java
 | 
				
			||||||
public enum ApiResponseCode {
 | 
					public enum ApiResponseCode {
 | 
				
			||||||
    USER_ID_DUPLICATE("400", "이미 존재하는 사용자 ID입니다."),
 | 
					    USER_ID_DUPLICATE(HttpStatus.CONFLICT.value(), "User ID already exists"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.controller;
 | 
					package com.bio.bio_backend.domain.user.member.controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
 | 
					import com.bio.bio_backend.global.dto.CustomApiResponse;
 | 
				
			||||||
 | 
					import io.swagger.v3.oas.annotations.tags.Tag;
 | 
				
			||||||
import org.springframework.http.HttpStatus;
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
import org.springframework.http.ResponseEntity;
 | 
					import org.springframework.http.ResponseEntity;
 | 
				
			||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 | 
					import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 | 
				
			||||||
@@ -22,8 +23,9 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
 | 
				
			|||||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
 | 
					import io.swagger.v3.oas.annotations.responses.ApiResponses;
 | 
				
			||||||
import io.swagger.v3.oas.annotations.media.Content;
 | 
					import io.swagger.v3.oas.annotations.media.Content;
 | 
				
			||||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
					import io.swagger.v3.oas.annotations.media.Schema;
 | 
				
			||||||
 | 
					import com.bio.bio_backend.global.utils.ApiResponseCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Tag(name = "Member", description = "회원 관련 API")
 | 
				
			||||||
@RestController
 | 
					@RestController
 | 
				
			||||||
@RequiredArgsConstructor
 | 
					@RequiredArgsConstructor
 | 
				
			||||||
@Slf4j
 | 
					@Slf4j
 | 
				
			||||||
@@ -33,19 +35,21 @@ public class MemberController {
 | 
				
			|||||||
    private final MemberMapper memberMapper;
 | 
					    private final MemberMapper memberMapper;
 | 
				
			||||||
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
 | 
					    private final BCryptPasswordEncoder bCryptPasswordEncoder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.", tags = {"Member"})
 | 
					    @Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.")
 | 
				
			||||||
    @ApiResponses({
 | 
					    @ApiResponses({
 | 
				
			||||||
        @ApiResponse(responseCode = "201", description = "회원 가입 성공", content = @Content(schema = @Schema(implementation = CreateMemberResponseDto.class))),
 | 
					        @ApiResponse(responseCode = "201", description = "회원 가입 성공"),
 | 
				
			||||||
        @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content(schema = @Schema(implementation = CustomApiResponse.class))),
 | 
					        @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
 | 
				
			||||||
        @ApiResponse(responseCode = "409", description = "중복된 사용자 정보", content = @Content(schema = @Schema(implementation = CustomApiResponse.class)))
 | 
					        @ApiResponse(responseCode = "409", description = "중복된 사용자 정보")
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    @PostMapping("/members")
 | 
					    @PostMapping("/members")
 | 
				
			||||||
    public ResponseEntity<CreateMemberResponseDto> createMember(@RequestBody @Valid CreateMemberRequestDto requestDto) {
 | 
					    public ResponseEntity<CustomApiResponse<CreateMemberResponseDto>> createMember(@RequestBody @Valid CreateMemberRequestDto requestDto) {
 | 
				
			||||||
        MemberDto member = memberMapper.toMemberDto(requestDto);
 | 
					        MemberDto member = memberMapper.toMemberDto(requestDto);
 | 
				
			||||||
        MemberDto createdMember = memberService.createMember(member);
 | 
					        MemberDto createdMember = memberService.createMember(member);
 | 
				
			||||||
        CreateMemberResponseDto responseDto = memberMapper.toCreateMemberResponseDto(createdMember);
 | 
					        CreateMemberResponseDto responseDto = memberMapper.toCreateMemberResponseDto(createdMember);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return ResponseEntity.status(HttpStatus.CREATED).body(responseDto);
 | 
					        CustomApiResponse<CreateMemberResponseDto> apiResponse = CustomApiResponse.success(ApiResponseCode.COMMON_SUCCESS_CREATED, responseDto);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // @PostMapping("/member/list")
 | 
					    // @PostMapping("/member/list")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,10 +40,10 @@ public class CustomAuthenticationFailureHandler implements AuthenticationFailure
 | 
				
			|||||||
        if (exception instanceof UsernameNotFoundException) {
 | 
					        if (exception instanceof UsernameNotFoundException) {
 | 
				
			||||||
            apiResponse = CustomApiResponse.fail(ApiResponseCode.USER_NOT_FOUND, null);
 | 
					            apiResponse = CustomApiResponse.fail(ApiResponseCode.USER_NOT_FOUND, null);
 | 
				
			||||||
        } else if (exception instanceof BadCredentialsException) {
 | 
					        } else if (exception instanceof BadCredentialsException) {
 | 
				
			||||||
            apiResponse = CustomApiResponse.fail(ApiResponseCode.AUTHENTICATION_FAILED, null);
 | 
					            apiResponse = CustomApiResponse.fail(ApiResponseCode.COMMON_UNAUTHORIZED, null);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
 | 
					            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
 | 
				
			||||||
            apiResponse = CustomApiResponse.fail(ApiResponseCode.INTERNAL_SERVER_ERROR, null);
 | 
					            apiResponse = CustomApiResponse.fail(ApiResponseCode.COMMON_INTERNAL_SERVER_ERROR, null);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String jsonResponse = objectMapper.writeValueAsString(apiResponse);
 | 
					        String jsonResponse = objectMapper.writeValueAsString(apiResponse);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package com.bio.bio_backend.global.exception;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import java.util.Objects;
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
import org.springframework.http.converter.HttpMessageNotReadableException;
 | 
					import org.springframework.http.converter.HttpMessageNotReadableException;
 | 
				
			||||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
 | 
					import org.springframework.web.HttpRequestMethodNotSupportedException;
 | 
				
			||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
 | 
					import org.springframework.web.bind.annotation.ExceptionHandler;
 | 
				
			||||||
@@ -17,7 +18,6 @@ import io.jsonwebtoken.MalformedJwtException;
 | 
				
			|||||||
import io.jsonwebtoken.security.SignatureException;
 | 
					import io.jsonwebtoken.security.SignatureException;
 | 
				
			||||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
 | 
					import com.bio.bio_backend.global.dto.CustomApiResponse;
 | 
				
			||||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
 | 
					import com.bio.bio_backend.global.utils.ApiResponseCode;
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.exception.UserDuplicateException;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@RestControllerAdvice
 | 
					@RestControllerAdvice
 | 
				
			||||||
public class GlobalExceptionHandler {
 | 
					public class GlobalExceptionHandler {
 | 
				
			||||||
@@ -41,12 +41,12 @@ public class GlobalExceptionHandler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @ExceptionHandler(IllegalArgumentException.class)
 | 
					    @ExceptionHandler(IllegalArgumentException.class)
 | 
				
			||||||
    public CustomApiResponse<Void> handleIllegalArgumentException(IllegalArgumentException e){
 | 
					    public CustomApiResponse<Void> handleIllegalArgumentException(IllegalArgumentException e){
 | 
				
			||||||
        return CustomApiResponse.fail(ApiResponseCode.ARGUMENT_NOT_VALID, null);
 | 
					        return CustomApiResponse.fail(ApiResponseCode.COMMON_ARGUMENT_NOT_VALID, null);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ExceptionHandler(IndexOutOfBoundsException.class)
 | 
					    @ExceptionHandler(IndexOutOfBoundsException.class)
 | 
				
			||||||
    public CustomApiResponse<Void> handleIndexOutOfBoundsException(IndexOutOfBoundsException e){
 | 
					    public CustomApiResponse<Void> handleIndexOutOfBoundsException(IndexOutOfBoundsException e){
 | 
				
			||||||
        return CustomApiResponse.fail(ApiResponseCode.INDEX_OUT_OF_BOUND, null);
 | 
					        return CustomApiResponse.fail(ApiResponseCode.COMMON_INDEX_OUT_OF_BOUND, null);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ExceptionHandler(SignatureException.class)
 | 
					    @ExceptionHandler(SignatureException.class)
 | 
				
			||||||
@@ -71,7 +71,7 @@ public class GlobalExceptionHandler {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    @ExceptionHandler(JsonProcessingException.class)
 | 
					    @ExceptionHandler(JsonProcessingException.class)
 | 
				
			||||||
    public CustomApiResponse<Void> handleExpiredJwtException(JsonProcessingException e) {
 | 
					    public CustomApiResponse<Void> handleExpiredJwtException(JsonProcessingException e) {
 | 
				
			||||||
        return CustomApiResponse.fail(ApiResponseCode.JSON_PROCESSING_EXCEPTION, null);
 | 
					        return CustomApiResponse.fail(ApiResponseCode.COMMON_JSON_PROCESSING_EXCEPTION, null);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @ExceptionHandler(ApiException.class)
 | 
					    @ExceptionHandler(ApiException.class)
 | 
				
			||||||
@@ -86,20 +86,9 @@ public class GlobalExceptionHandler {
 | 
				
			|||||||
            .map(error -> new ValidationError(error.getField(), error.getDefaultMessage()))
 | 
					            .map(error -> new ValidationError(error.getField(), error.getDefaultMessage()))
 | 
				
			||||||
            .toList();
 | 
					            .toList();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return CustomApiResponse.fail(ApiResponseCode.ARGUMENT_NOT_VALID, errors);
 | 
					        return CustomApiResponse.fail(ApiResponseCode.COMMON_ARGUMENT_NOT_VALID, errors);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 검증 오류 상세 정보를 위한 내부 클래스
 | 
					    // 검증 오류 상세 정보를 위한 내부 클래스
 | 
				
			||||||
    private static class ValidationError {
 | 
					    private record ValidationError(String field, String message) { }
 | 
				
			||||||
        private final String field;
 | 
					 | 
				
			||||||
        private final String message;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        public ValidationError(String field, String message) {
 | 
					 | 
				
			||||||
            this.field = field;
 | 
					 | 
				
			||||||
            this.message = message;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        public String getField() { return field; }
 | 
					 | 
				
			||||||
        public String getMessage() { return message; }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,7 +83,7 @@ public class JwtTokenFilter extends OncePerRequestFilter {
 | 
				
			|||||||
                response.setHeader("Authorization", "Bearer " + newAccessToken);
 | 
					                response.setHeader("Authorization", "Bearer " + newAccessToken);
 | 
				
			||||||
                filterChain.doFilter(request, response);
 | 
					                filterChain.doFilter(request, response);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                sendJsonResponse(response, CustomApiResponse.fail(ApiResponseCode.All_TOKEN_INVALID, null));
 | 
					                sendJsonResponse(response, CustomApiResponse.fail(ApiResponseCode.ALL_TOKEN_INVALID, null));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (Exception e) {
 | 
					        } catch (Exception e) {
 | 
				
			||||||
            request.setAttribute("exception", e);
 | 
					            request.setAttribute("exception", e);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,43 +12,58 @@ import org.springframework.http.HttpStatus;
 | 
				
			|||||||
@AllArgsConstructor
 | 
					@AllArgsConstructor
 | 
				
			||||||
public enum ApiResponseCode {
 | 
					public enum ApiResponseCode {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // 200 OK
 | 
					 | 
				
			||||||
    LOGIN_SUCCESSFUL(HttpStatus.OK.value(), "Login successful"),
 | 
					 | 
				
			||||||
    LOGOUT_SUCCESSFUL(HttpStatus.OK.value(), "Logout successful"),
 | 
					 | 
				
			||||||
    USER_INFO_CHANGE(HttpStatus.OK.value(), "User info update successful"),
 | 
					 | 
				
			||||||
    USER_DELETE_SUCCESSFUL(HttpStatus.OK.value(),  "User delete is successful"),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 409 Conflict
 | 
					 | 
				
			||||||
    USER_ID_DUPLICATE(HttpStatus.CONFLICT.value(), "User ID already exists"),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /*공통 Code*/
 | 
					    /*공통 Code*/
 | 
				
			||||||
 | 
					    // 200 OK
 | 
				
			||||||
 | 
					    COMMON_SUCCESS(HttpStatus.OK.value(), "요청 성공"),
 | 
				
			||||||
 | 
					    COMMON_SUCCESS_CREATED(HttpStatus.CREATED.value(), "성공적으로 생성되었습니다"),
 | 
				
			||||||
 | 
					    COMMON_SUCCESS_UPDATED(HttpStatus.OK.value(), "성공적으로 수정되었습니다"),
 | 
				
			||||||
 | 
					    COMMON_SUCCESS_DELETED(HttpStatus.OK.value(), "성공적으로 삭제되었습니다"),
 | 
				
			||||||
 | 
					    COMMON_SUCCESS_RETRIEVED(HttpStatus.OK.value(), "성공적으로 조회되었습니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 400 Bad Request
 | 
					    // 400 Bad Request
 | 
				
			||||||
    COMMON_BAD_REQUEST(HttpStatus.BAD_REQUEST.value(), "Required request body is missing or Error"),
 | 
					    COMMON_BAD_REQUEST(HttpStatus.BAD_REQUEST.value(), "필수 요청 본문이 누락되었거나 오류가 발생했습니다"),
 | 
				
			||||||
    COMMON_FORMAT_WRONG(HttpStatus.BAD_REQUEST.value(), "Request format is incorrect"),
 | 
					    COMMON_FORMAT_WRONG(HttpStatus.BAD_REQUEST.value(), "요청 형식이 올바르지 않습니다"),
 | 
				
			||||||
    ARGUMENT_NOT_VALID(HttpStatus.BAD_REQUEST.value(), "Argument is not valid"),
 | 
					    COMMON_ARGUMENT_NOT_VALID(HttpStatus.BAD_REQUEST.value(), "인자가 유효하지 않습니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 401 Unauthorized
 | 
					    // 401 Unauthorized
 | 
				
			||||||
    COMMON_UNAUTHORIZED(HttpStatus.UNAUTHORIZED.value(), "Unauthorized"),
 | 
					    COMMON_UNAUTHORIZED(HttpStatus.UNAUTHORIZED.value(), "인증에 실패했습니다"),
 | 
				
			||||||
    USER_NOT_FOUND(HttpStatus.UNAUTHORIZED.value(), "User not found. Authentication failed"),
 | 
					 | 
				
			||||||
    AUTHENTICATION_FAILED(HttpStatus.UNAUTHORIZED.value(), "Password is invalid"),
 | 
					 | 
				
			||||||
    JWT_SIGNATURE_MISMATCH(HttpStatus.UNAUTHORIZED.value(), "JWT signature does not match. Authentication failed"),
 | 
					 | 
				
			||||||
    JWT_TOKEN_NULL(HttpStatus.UNAUTHORIZED.value(), "JWT token is null"),
 | 
					 | 
				
			||||||
    JWT_TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED.value(), "Token is Expired"),
 | 
					 | 
				
			||||||
    All_TOKEN_INVALID(HttpStatus.UNAUTHORIZED.value(), "Access and Refresh tokens are expired or invalid"),
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 403 Forbidden
 | 
					    // 403 Forbidden
 | 
				
			||||||
    COMMON_FORBIDDEN(HttpStatus.FORBIDDEN.value(), "Access is denied"),
 | 
					    COMMON_FORBIDDEN(HttpStatus.FORBIDDEN.value(), "접근이 거부되었습니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 404 Not Found
 | 
					    // 404 Not Found
 | 
				
			||||||
    COMMON_NOT_FOUND(HttpStatus.NOT_FOUND.value(), "Resource is not found"),
 | 
					    COMMON_NOT_FOUND(HttpStatus.NOT_FOUND.value(), "리소스를 찾을 수 없습니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 405 Method Not Allowed
 | 
					    // 405 Method Not Allowed
 | 
				
			||||||
    COMMON_METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED.value(), "Method not Allowed"),
 | 
					    COMMON_METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED.value(), "허용되지 않는 메소드입니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 409 Conflict
 | 
				
			||||||
 | 
					    COMMON_CONFLICT(HttpStatus.CONFLICT.value(), "충돌이 발생했습니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 500 Internal Server Error
 | 
					    // 500 Internal Server Error
 | 
				
			||||||
    INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An error occurred on the server"),
 | 
					    COMMON_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), "서버에서 오류가 발생했습니다"),
 | 
				
			||||||
    INDEX_OUT_OF_BOUND(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Index out of bounds for length"),
 | 
					    COMMON_INDEX_OUT_OF_BOUND(HttpStatus.INTERNAL_SERVER_ERROR.value(), "인덱스가 범위를 벗어났습니다"),
 | 
				
			||||||
	JSON_PROCESSING_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Check if it is a valid JSON format");
 | 
					    COMMON_JSON_PROCESSING_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR.value(), "유효한 JSON 형식인지 확인해주세요"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*사용자 관련 Code*/
 | 
				
			||||||
 | 
					    // 200 OK
 | 
				
			||||||
 | 
					    LOGIN_SUCCESSFUL(HttpStatus.OK.value(), "로그인에 성공했습니다"),
 | 
				
			||||||
 | 
					    LOGOUT_SUCCESSFUL(HttpStatus.OK.value(), "로그아웃에 성공했습니다"),
 | 
				
			||||||
 | 
					    USER_INFO_CHANGE(HttpStatus.OK.value(), "사용자 정보가 성공적으로 수정되었습니다"),
 | 
				
			||||||
 | 
					    USER_DELETE_SUCCESSFUL(HttpStatus.OK.value(), "사용자가 성공적으로 삭제되었습니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 409 Conflict
 | 
				
			||||||
 | 
					    USER_ID_DUPLICATE(HttpStatus.CONFLICT.value(), "이미 존재하는 사용자 ID입니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 401 Unauthorized
 | 
				
			||||||
 | 
					    USER_NOT_FOUND(HttpStatus.UNAUTHORIZED.value(), "사용자를 찾을 수 없습니다. 인증에 실패했습니다"),
 | 
				
			||||||
 | 
					    USER_PASSWORD_INVALID(HttpStatus.UNAUTHORIZED.value(), "비밀번호가 올바르지 않습니다"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // JWT 관련
 | 
				
			||||||
 | 
					    JWT_SIGNATURE_MISMATCH(HttpStatus.UNAUTHORIZED.value(), "JWT 서명이 일치하지 않습니다. 인증에 실패했습니다"),
 | 
				
			||||||
 | 
					    JWT_TOKEN_NULL(HttpStatus.UNAUTHORIZED.value(), "JWT 토큰이 null입니다"),
 | 
				
			||||||
 | 
					    JWT_TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED.value(), "토큰이 만료되었습니다"),
 | 
				
			||||||
 | 
					    ALL_TOKEN_INVALID(HttpStatus.UNAUTHORIZED.value(), "액세스 토큰과 리프레시 토큰이 모두 만료되었거나 유효하지 않습니다");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final int statusCode;
 | 
					    private final int statusCode;
 | 
				
			||||||
    private final String description;
 | 
					    private final String description;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user