kmbin92_2025081101 #1
							
								
								
									
										56
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								README.md
									
									
									
									
									
								
							@@ -1,2 +1,56 @@
 | 
				
			|||||||
# bio_backend
 | 
					# Bio Backend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 기술 스택
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- **Framework**: Spring Boot
 | 
				
			||||||
 | 
					- **Database**: PostgreSQL
 | 
				
			||||||
 | 
					- **ORM**: Spring Data JPA + QueryDSL
 | 
				
			||||||
 | 
					- **Security**: Spring Security + JWT
 | 
				
			||||||
 | 
					- **Build Tool**: Gradle
 | 
				
			||||||
 | 
					- **Container**: Docker + Kubernetes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 개발 가이드
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 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. 트랜잭션 관리
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 기본 설정
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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` (성능 최적화)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,8 +43,9 @@ dependencies {
 | 
				
			|||||||
	// Validation 추가
 | 
						// Validation 추가
 | 
				
			||||||
	implementation 'org.springframework.boot:spring-boot-starter-validation'
 | 
						implementation 'org.springframework.boot:spring-boot-starter-validation'
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// ModelMapper 추가
 | 
						// MapStruct 추가 (안정적인 버전으로 수정)
 | 
				
			||||||
	implementation 'org.modelmapper:modelmapper:3.0.0'
 | 
						implementation 'org.mapstruct:mapstruct:1.5.5.Final'
 | 
				
			||||||
 | 
						annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// MyBatis 추가
 | 
						// MyBatis 추가
 | 
				
			||||||
	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
 | 
						implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
 | 
				
			||||||
@@ -54,6 +55,8 @@ dependencies {
 | 
				
			|||||||
	
 | 
						
 | 
				
			||||||
	compileOnly 'org.projectlombok:lombok'
 | 
						compileOnly 'org.projectlombok:lombok'
 | 
				
			||||||
	annotationProcessor 'org.projectlombok:lombok'
 | 
						annotationProcessor 'org.projectlombok:lombok'
 | 
				
			||||||
 | 
						// Lombok과 MapStruct 함께 사용을 위한 바인딩
 | 
				
			||||||
 | 
						annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
 | 
				
			||||||
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
 | 
						testImplementation 'org.springframework.boot:spring-boot-starter-test'
 | 
				
			||||||
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
 | 
						testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    create table member (
 | 
					    create table st_member (
 | 
				
			||||||
        status varchar(1) not null,
 | 
					        use_flag boolean not null,
 | 
				
			||||||
        created_at timestamp(6) not null,
 | 
					        created_at timestamp(6) not null,
 | 
				
			||||||
 | 
					        created_oid bigint,
 | 
				
			||||||
        last_login_at timestamp(6),
 | 
					        last_login_at timestamp(6),
 | 
				
			||||||
        oid bigint not null,
 | 
					        oid bigint not null,
 | 
				
			||||||
        updated_at timestamp(6) not null,
 | 
					        updated_at timestamp(6) not null,
 | 
				
			||||||
        role varchar(40) not null,
 | 
					        updated_oid bigint,
 | 
				
			||||||
 | 
					        role varchar(40) not null check (role in ('MEMBER','ADMIN','USER','SYSTEM_ADMIN')),
 | 
				
			||||||
        password varchar(100) not null,
 | 
					        password varchar(100) not null,
 | 
				
			||||||
        user_id varchar(100) not null,
 | 
					        user_id varchar(100) not null,
 | 
				
			||||||
        refresh_token varchar(200),
 | 
					        refresh_token varchar(200),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.controller;
 | 
					package com.bio.bio_backend.domain.user.member.controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.modelmapper.ModelMapper;
 | 
					 | 
				
			||||||
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;
 | 
				
			||||||
@@ -14,6 +13,7 @@ import com.bio.bio_backend.domain.user.member.dto.MemberDto;
 | 
				
			|||||||
import com.bio.bio_backend.domain.user.member.dto.CreateMemberRequestDto;
 | 
					import com.bio.bio_backend.domain.user.member.dto.CreateMemberRequestDto;
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.dto.CreateMemberResponseDto;
 | 
					import com.bio.bio_backend.domain.user.member.dto.CreateMemberResponseDto;
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.service.MemberService;
 | 
					import com.bio.bio_backend.domain.user.member.service.MemberService;
 | 
				
			||||||
 | 
					import com.bio.bio_backend.domain.user.member.mapper.MemberMapper;
 | 
				
			||||||
import lombok.RequiredArgsConstructor;
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,30 +23,16 @@ import lombok.extern.slf4j.Slf4j;
 | 
				
			|||||||
public class MemberController {
 | 
					public class MemberController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final MemberService memberService;
 | 
					    private final MemberService memberService;
 | 
				
			||||||
    private final ModelMapper mapper;
 | 
					    private final MemberMapper memberMapper;
 | 
				
			||||||
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
 | 
					    private final BCryptPasswordEncoder bCryptPasswordEncoder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("/members")
 | 
				
			||||||
 | 
					    public ResponseEntity<CreateMemberResponseDto> createMember(@RequestBody @Valid CreateMemberRequestDto requestDto) {
 | 
				
			||||||
 | 
					        MemberDto member = memberMapper.toMemberDto(requestDto);
 | 
				
			||||||
 | 
					        MemberDto createdMember = memberService.createMember(member);
 | 
				
			||||||
 | 
					        CreateMemberResponseDto responseDto = memberMapper.toCreateMemberResponseDto(createdMember);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @GetMapping("/join")
 | 
					        return ResponseEntity.status(HttpStatus.CREATED).body(responseDto);
 | 
				
			||||||
    public ResponseEntity<String> createMember1() {
 | 
					 | 
				
			||||||
        return ResponseEntity.status(HttpStatus.CREATED).body("test");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @PostMapping("/join")
 | 
					 | 
				
			||||||
    public ResponseEntity<Long> createMember(@RequestBody @Valid CreateMemberRequestDto requestDto) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // RequestMember를 MemberDTO로 변환
 | 
					 | 
				
			||||||
        MemberDto member = new MemberDto();
 | 
					 | 
				
			||||||
        member.setId(requestDto.getUserId());
 | 
					 | 
				
			||||||
        member.setPw(requestDto.getPassword());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        long oid = memberService.createMember(member);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // 생성된 회원 정보를 조회하여 응답
 | 
					 | 
				
			||||||
        //MemberDto createdMember = memberService.selectMember(oid);
 | 
					 | 
				
			||||||
        //CreateMemberResponseDto responseDto = mapper.map(createdMember, CreateMemberResponseDto.class);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return ResponseEntity.status(HttpStatus.CREATED).body(oid);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // @PostMapping("/member/list")
 | 
					    // @PostMapping("/member/list")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,21 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.dto;
 | 
					package com.bio.bio_backend.domain.user.member.dto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonInclude;
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
import jakarta.validation.constraints.NotBlank;
 | 
					import lombok.Builder;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import jakarta.validation.constraints.NotBlank;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
 | 
					@Builder
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
public class CreateMemberRequestDto {
 | 
					public class CreateMemberRequestDto {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @NotBlank(message = "사용자 ID는 필수입니다")
 | 
					    @NotBlank(message = "아이디는 필수입니다.")
 | 
				
			||||||
    private String userId;
 | 
					    private String userId;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @NotBlank(message = "비밀번호는 필수입니다")
 | 
					    @NotBlank(message = "비밀번호는 필수입니다.")
 | 
				
			||||||
    private String password;
 | 
					    private String password;
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,23 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.dto;
 | 
					package com.bio.bio_backend.domain.user.member.dto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonInclude;
 | 
					import com.bio.bio_backend.domain.user.member.enums.MemberRole;
 | 
				
			||||||
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Builder;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.LocalDateTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
 | 
					@Builder
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
public class CreateMemberResponseDto {
 | 
					public class CreateMemberResponseDto {
 | 
				
			||||||
    private String id;
 | 
					    
 | 
				
			||||||
    private String pw;
 | 
					    private Long oid;
 | 
				
			||||||
 | 
					    private String userId;
 | 
				
			||||||
 | 
					    private MemberRole role;
 | 
				
			||||||
 | 
					    private Boolean useFlag;
 | 
				
			||||||
 | 
					    private LocalDateTime createdAt;
 | 
				
			||||||
 | 
					    private LocalDateTime updatedAt;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,21 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.dto;
 | 
					package com.bio.bio_backend.domain.user.member.dto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import jakarta.validation.constraints.NotNull;
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Builder;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import jakarta.validation.constraints.NotBlank;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
 | 
					@Builder
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
public class LoginRequestDto {
 | 
					public class LoginRequestDto {
 | 
				
			||||||
    @NotNull(message = "ID cannot be null")
 | 
					 | 
				
			||||||
    private String id;
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @NotNull(message = "Password cannot be null")
 | 
					    @NotBlank(message = "아이디는 필수입니다.")
 | 
				
			||||||
    private String pw;
 | 
					    private String userId;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private int loginLogFlag;
 | 
					    @NotBlank(message = "비밀번호는 필수입니다.")
 | 
				
			||||||
 | 
					    private String password;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,24 +1,19 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.dto;
 | 
					package com.bio.bio_backend.domain.user.member.dto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonFormat;
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonInclude;
 | 
					import lombok.Builder;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.sql.Date;
 | 
					import java.time.LocalDateTime;
 | 
				
			||||||
import java.sql.Timestamp;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
 | 
					@Builder
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
public class LoginResponseDto {
 | 
					public class LoginResponseDto {
 | 
				
			||||||
    private String id;
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    private String userId;
 | 
				
			||||||
    private String role;
 | 
					    private String role;
 | 
				
			||||||
 | 
					    private LocalDateTime lastLoginAt;
 | 
				
			||||||
    private String status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
 | 
					 | 
				
			||||||
    private Date regAt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
 | 
					 | 
				
			||||||
    private Timestamp lastLoginAt;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,108 +1,42 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.dto;
 | 
					package com.bio.bio_backend.domain.user.member.dto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.sql.Timestamp;
 | 
					import com.bio.bio_backend.domain.user.member.enums.MemberRole;
 | 
				
			||||||
import java.util.Collection;
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
import java.util.HashSet;
 | 
					import lombok.Builder;
 | 
				
			||||||
import java.util.Set;
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
import org.springframework.security.core.GrantedAuthority;
 | 
					import org.springframework.security.core.GrantedAuthority;
 | 
				
			||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
 | 
					import org.springframework.security.core.authority.SimpleGrantedAuthority;
 | 
				
			||||||
import org.springframework.security.core.userdetails.UserDetails;
 | 
					import org.springframework.security.core.userdetails.UserDetails;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.bio.bio_backend.global.constants.MemberConstants;
 | 
					import java.time.LocalDateTime;
 | 
				
			||||||
import lombok.Data;
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					import java.util.Collections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
/**
 | 
					@Builder
 | 
				
			||||||
 * 회원
 | 
					@NoArgsConstructor
 | 
				
			||||||
 */
 | 
					@AllArgsConstructor
 | 
				
			||||||
public class MemberDto implements UserDetails {
 | 
					public class MemberDto implements UserDetails {
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 시퀀스 (PK)
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private int seq;
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
	/**
 | 
					    private Long oid;
 | 
				
			||||||
	 * ID
 | 
					    private String userId;
 | 
				
			||||||
	 */
 | 
					    private String password;
 | 
				
			||||||
	private String id;
 | 
					    private MemberRole role;
 | 
				
			||||||
	
 | 
					    private Boolean useFlag;
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Password
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private String pw;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 권한
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private String role;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 회원 상태
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private String status;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 가입 일시
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private Timestamp regAt;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 등록자
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private int regSeq;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 수정 일시
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private Timestamp udtAt;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 수정자
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private int udtSeq;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 최근 로그인 일시
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private Timestamp lastLoginAt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Refresh Token
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
    private String refreshToken;
 | 
					    private String refreshToken;
 | 
				
			||||||
 | 
					    private LocalDateTime lastLoginAt;
 | 
				
			||||||
 | 
					    private LocalDateTime createdAt;
 | 
				
			||||||
 | 
					    private LocalDateTime updatedAt;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Collection<? extends GrantedAuthority> getAuthorities() {
 | 
					    public Collection<? extends GrantedAuthority> getAuthorities() {
 | 
				
			||||||
 | 
					        return Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + this.role.getValue()));
 | 
				
			||||||
		Set<GrantedAuthority> roles = new HashSet<>();
 | 
					 | 
				
			||||||
		String auth = "";
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		if(role.equals("SYSTEM_ADMIN")){
 | 
					 | 
				
			||||||
			auth = MemberConstants.ROLE_SYSTEM_ADMIN + "," + 
 | 
					 | 
				
			||||||
					MemberConstants.ROLE_ADMIN + "," + MemberConstants.ROLE_MEMBER;
 | 
					 | 
				
			||||||
		}else if(role.equals("ADMIN")){
 | 
					 | 
				
			||||||
			auth = MemberConstants.ROLE_ADMIN + "," + MemberConstants.ROLE_MEMBER;
 | 
					 | 
				
			||||||
		}else {
 | 
					 | 
				
			||||||
			auth = MemberConstants.ROLE_MEMBER;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (String x : auth.split(",")) {
 | 
					 | 
				
			||||||
			roles.add(new SimpleGrantedAuthority(x));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return roles;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Override
 | 
					 | 
				
			||||||
	public String getPassword() {
 | 
					 | 
				
			||||||
		return pw;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public String getUsername() {
 | 
					    public String getUsername() {
 | 
				
			||||||
		return id;
 | 
					        return this.userId;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
@@ -112,7 +46,7 @@ public class MemberDto implements UserDetails {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean isAccountNonLocked() {
 | 
					    public boolean isAccountNonLocked() {
 | 
				
			||||||
		return true;
 | 
					        return this.useFlag != null && this.useFlag;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
@@ -122,6 +56,6 @@ public class MemberDto implements UserDetails {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean isEnabled() {
 | 
					    public boolean isEnabled() {
 | 
				
			||||||
		return true;
 | 
					        return this.useFlag != null && this.useFlag;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,25 +1,23 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.entity;
 | 
					package com.bio.bio_backend.domain.user.member.entity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.time.LocalDateTime;
 | 
					import com.bio.bio_backend.domain.user.member.enums.MemberRole;
 | 
				
			||||||
 | 
					 | 
				
			||||||
import jakarta.persistence.Column;
 | 
					 | 
				
			||||||
import jakarta.persistence.Entity;
 | 
					 | 
				
			||||||
import jakarta.persistence.Table;
 | 
					 | 
				
			||||||
import jakarta.persistence.UniqueConstraint;
 | 
					 | 
				
			||||||
import com.bio.bio_backend.global.entity.BaseEntity;
 | 
					import com.bio.bio_backend.global.entity.BaseEntity;
 | 
				
			||||||
 | 
					import jakarta.persistence.*;
 | 
				
			||||||
import lombok.AllArgsConstructor;
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
import lombok.Builder;
 | 
					import lombok.Builder;
 | 
				
			||||||
import lombok.Getter;
 | 
					import lombok.Getter;
 | 
				
			||||||
import lombok.NoArgsConstructor;
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
import lombok.Setter;
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.LocalDateTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Entity
 | 
					@Entity
 | 
				
			||||||
@Getter @Setter
 | 
					@Getter @Setter
 | 
				
			||||||
@NoArgsConstructor
 | 
					@NoArgsConstructor
 | 
				
			||||||
@AllArgsConstructor
 | 
					@AllArgsConstructor
 | 
				
			||||||
@Builder
 | 
					@Builder
 | 
				
			||||||
@Table(
 | 
					@Table(
 | 
				
			||||||
    name = "member",
 | 
					    name = "st_member",
 | 
				
			||||||
    uniqueConstraints = {
 | 
					    uniqueConstraints = {
 | 
				
			||||||
        @UniqueConstraint(name = "uk_member_user_id", columnNames = "user_id")
 | 
					        @UniqueConstraint(name = "uk_member_user_id", columnNames = "user_id")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -32,15 +30,28 @@ public class Member extends BaseEntity {
 | 
				
			|||||||
    @Column(name = "password", nullable = false, length = 100)
 | 
					    @Column(name = "password", nullable = false, length = 100)
 | 
				
			||||||
    private String password;
 | 
					    private String password;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Enumerated(EnumType.STRING)
 | 
				
			||||||
    @Column(name = "role", nullable = false, length = 40)
 | 
					    @Column(name = "role", nullable = false, length = 40)
 | 
				
			||||||
    private String role;
 | 
					    private MemberRole role;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Column(name = "status", nullable = false, length = 1)
 | 
					    @Column(name = "use_flag", nullable = false)
 | 
				
			||||||
    private String status;
 | 
					    @Builder.Default
 | 
				
			||||||
 | 
					    private Boolean useFlag = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Column(name = "refresh_token", length = 200)
 | 
					    @Column(name = "refresh_token", length = 200)
 | 
				
			||||||
    private String refreshToken;
 | 
					    private String refreshToken;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Column(name = "last_login_at")
 | 
					    @Column(name = "last_login_at")
 | 
				
			||||||
    private LocalDateTime lastLoginAt;
 | 
					    private LocalDateTime lastLoginAt;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 엔티티 저장 후 실행되는 메서드
 | 
				
			||||||
 | 
					     * createdOid와 updatedOid를 자기 자신의 oid로 설정
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @PostPersist
 | 
				
			||||||
 | 
					    protected void onPostPersist() {
 | 
				
			||||||
 | 
					        if (this.getCreatedOid() == null) {
 | 
				
			||||||
 | 
					            this.setCreatedOid(this.getOid());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					package com.bio.bio_backend.domain.user.member.enums;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 회원 역할을 정의하는 Enum
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@RequiredArgsConstructor
 | 
				
			||||||
 | 
					public enum MemberRole {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    MEMBER("MEMBER", "일반 회원"),
 | 
				
			||||||
 | 
					    ADMIN("ADMIN", "관리자"),
 | 
				
			||||||
 | 
					    USER("USER", "사용자"),
 | 
				
			||||||
 | 
					    SYSTEM_ADMIN("SYSTEM_ADMIN", "시스템 관리자");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private final String value;
 | 
				
			||||||
 | 
					    private final String description;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 문자열 값으로부터 MemberRole을 찾는 메서드
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static MemberRole fromValue(String value) {
 | 
				
			||||||
 | 
					        for (MemberRole role : values()) {
 | 
				
			||||||
 | 
					            if (role.value.equals(value)) {
 | 
				
			||||||
 | 
					                return role;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        throw new IllegalArgumentException("Unknown MemberRole value: " + value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 기본 역할 반환
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static MemberRole getDefault() {
 | 
				
			||||||
 | 
					        return MEMBER;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package com.bio.bio_backend.domain.user.member.exception;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class UserDuplicateException extends RuntimeException {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public UserDuplicateException(String message) {
 | 
				
			||||||
 | 
					        super(message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public UserDuplicateException(String message, Throwable cause) {
 | 
				
			||||||
 | 
					        super(message, cause);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,27 +1,50 @@
 | 
				
			|||||||
package com.bio.bio_backend.domain.user.member.mapper;
 | 
					package com.bio.bio_backend.domain.user.member.mapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.List;
 | 
					import com.bio.bio_backend.domain.user.member.dto.CreateMemberRequestDto;
 | 
				
			||||||
import java.util.Map;
 | 
					import com.bio.bio_backend.domain.user.member.dto.CreateMemberResponseDto;
 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.apache.ibatis.annotations.Mapper;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
 | 
					import com.bio.bio_backend.domain.user.member.dto.MemberDto;
 | 
				
			||||||
 | 
					import com.bio.bio_backend.domain.user.member.entity.Member;
 | 
				
			||||||
 | 
					import com.bio.bio_backend.domain.user.member.enums.MemberRole;
 | 
				
			||||||
 | 
					import org.mapstruct.Mapper;
 | 
				
			||||||
 | 
					import org.mapstruct.Mapping;
 | 
				
			||||||
 | 
					import org.mapstruct.factory.Mappers;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Mapper
 | 
					@Mapper(componentModel = "spring")
 | 
				
			||||||
public interface MemberMapper {
 | 
					public interface MemberMapper {
 | 
				
			||||||
    int createMember(MemberDto memberDTO);
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    MemberDto loadUserByUsername(String id);
 | 
					    MemberMapper INSTANCE = Mappers.getMapper(MemberMapper.class);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void updateRefreshToken(MemberDto memberDTO);
 | 
					    /**
 | 
				
			||||||
 | 
					     * CreateMemberRequestDto를 MemberDto로 변환
 | 
				
			||||||
 | 
					     * 기본값 설정: role = MemberRole.MEMBER, useFlag = true
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Mapping(target = "oid", ignore = true)
 | 
				
			||||||
 | 
					    @Mapping(target = "role", expression = "java(com.bio.bio_backend.domain.user.member.enums.MemberRole.getDefault())")
 | 
				
			||||||
 | 
					    @Mapping(target = "useFlag", constant = "true")
 | 
				
			||||||
 | 
					    @Mapping(target = "refreshToken", ignore = true)
 | 
				
			||||||
 | 
					    @Mapping(target = "lastLoginAt", ignore = true)
 | 
				
			||||||
 | 
					    @Mapping(target = "createdAt", ignore = true)
 | 
				
			||||||
 | 
					    @Mapping(target = "updatedAt", ignore = true)
 | 
				
			||||||
 | 
					    MemberDto toMemberDto(CreateMemberRequestDto requestDto);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    String getRefreshToken(String id);
 | 
					    /**
 | 
				
			||||||
 | 
					     * Member 엔티티를 MemberDto로 변환
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    MemberDto toMemberDto(Member member);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    int deleteRefreshToken(String id);
 | 
					    /**
 | 
				
			||||||
 | 
					     * MemberDto를 Member 엔티티로 변환
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Member toMember(MemberDto memberDto);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    List<MemberDto> selectMemberList(Map<String, String> params);
 | 
					    /**
 | 
				
			||||||
 | 
					     * Member 엔티티 리스트를 MemberDto 리스트로 변환
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    List<MemberDto> toMemberDtoList(List<Member> members);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    MemberDto selectMemberBySeq(long seq);
 | 
					    /**
 | 
				
			||||||
 | 
					     * MemberDto를 CreateMemberResponseDto로 변환
 | 
				
			||||||
    int updateMember(MemberDto member);
 | 
					     */
 | 
				
			||||||
 | 
					    CreateMemberResponseDto toCreateMemberResponseDto(MemberDto memberDto);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,12 +4,13 @@ import org.springframework.data.jpa.repository.JpaRepository;
 | 
				
			|||||||
import org.springframework.stereotype.Repository;
 | 
					import org.springframework.stereotype.Repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.entity.Member;
 | 
					import com.bio.bio_backend.domain.user.member.entity.Member;
 | 
				
			||||||
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Repository
 | 
					@Repository
 | 
				
			||||||
public interface MemberRepository extends JpaRepository<Member, Long> {
 | 
					public interface MemberRepository extends JpaRepository<Member, Long> {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // 사용자 ID로 회원 조회
 | 
					    // 사용자 ID로 회원 조회 (Optional 반환)
 | 
				
			||||||
    Member findByUserId(String userId);
 | 
					    Optional<Member> findByUserId(String userId);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // 사용자 ID 존재 여부 확인
 | 
					    // 사용자 ID 존재 여부 확인
 | 
				
			||||||
    boolean existsByUserId(String userId);
 | 
					    boolean existsByUserId(String userId);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,32 +31,32 @@ public interface MemberRepositoryCustom {
 | 
				
			|||||||
    List<Member> findByRole(String role);
 | 
					    List<Member> findByRole(String role);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 상태(Status)별로 회원 목록을 조회합니다.
 | 
					     * 사용 여부별로 회원 목록을 조회합니다.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param status 회원 상태
 | 
					     * @param useFlag 사용 여부
 | 
				
			||||||
     * @return List<Member> 해당 상태를 가진 회원 목록
 | 
					     * @return List<Member> 해당 사용 여부를 가진 회원 목록
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    List<Member> findByStatus(String status);
 | 
					    List<Member> findByUseFlag(Boolean useFlag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 사용자 ID와 상태로 회원을 조회합니다.
 | 
					     * 사용자 ID와 사용 여부로 회원을 조회합니다.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param userId 사용자 ID
 | 
					     * @param userId 사용자 ID
 | 
				
			||||||
     * @param status 회원 상태
 | 
					     * @param useFlag 사용 여부
 | 
				
			||||||
     * @return Optional<Member> 회원 정보
 | 
					     * @return Optional<Member> 회원 정보
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    Optional<Member> findByUserIdAndStatus(String userId, String status);
 | 
					    Optional<Member> findByUserIdAndUseFlag(String userId, Boolean useFlag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 검색 조건에 따른 회원 목록을 페이징하여 조회합니다.
 | 
					     * 검색 조건에 따른 회원 목록을 페이징하여 조회합니다.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param userId 사용자 ID (부분 검색)
 | 
					     * @param userId 사용자 ID (부분 검색)
 | 
				
			||||||
     * @param role 회원 역할
 | 
					     * @param role 회원 역할
 | 
				
			||||||
     * @param status 회원 상태
 | 
					     * @param useFlag 사용 여부
 | 
				
			||||||
     * @param pageable 페이징 정보
 | 
					     * @param pageable 페이징 정보
 | 
				
			||||||
     * @return Page<Member> 페이징된 회원 목록
 | 
					     * @return Page<Member> 페이징된 회원 목록
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    Page<Member> findMembersByCondition(String userId, String role, String status, Pageable pageable);
 | 
					    Page<Member> findMembersByCondition(String userId, String role, Boolean useFlag, Pageable pageable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 마지막 로그인 시간이 특정 시간 이후인 회원들을 조회합니다.
 | 
					     * 마지막 로그인 시간이 특정 시간 이후인 회원들을 조회합니다.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package com.bio.bio_backend.domain.user.member.repository;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.entity.Member;
 | 
					import com.bio.bio_backend.domain.user.member.entity.Member;
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.entity.QMember;
 | 
					import com.bio.bio_backend.domain.user.member.entity.QMember;
 | 
				
			||||||
 | 
					import com.bio.bio_backend.domain.user.member.enums.MemberRole;
 | 
				
			||||||
import com.querydsl.core.BooleanBuilder;
 | 
					import com.querydsl.core.BooleanBuilder;
 | 
				
			||||||
import com.querydsl.core.types.dsl.BooleanExpression;
 | 
					import com.querydsl.core.types.dsl.BooleanExpression;
 | 
				
			||||||
import com.querydsl.jpa.impl.JPAQueryFactory;
 | 
					import com.querydsl.jpa.impl.JPAQueryFactory;
 | 
				
			||||||
@@ -46,37 +47,37 @@ public class MemberRepositoryImpl implements MemberRepositoryCustom {
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public List<Member> findByRole(String role) {
 | 
					    public List<Member> findByRole(String role) {
 | 
				
			||||||
        // 역할별로 회원을 조회합니다.
 | 
					        // 역할별로 회원을 조회합니다.
 | 
				
			||||||
        // eq() 메서드를 사용하여 정확한 일치 조건을 설정합니다.
 | 
					        // String을 MemberRole enum으로 변환하여 비교합니다.
 | 
				
			||||||
        return queryFactory
 | 
					        return queryFactory
 | 
				
			||||||
                .selectFrom(member)
 | 
					                .selectFrom(member)
 | 
				
			||||||
                .where(member.role.eq(role))
 | 
					                .where(member.role.eq(MemberRole.fromValue(role)))
 | 
				
			||||||
                .fetch();
 | 
					                .fetch();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public List<Member> findByStatus(String status) {
 | 
					    public List<Member> findByUseFlag(Boolean useFlag) {
 | 
				
			||||||
        // 상태별로 회원을 조회합니다.
 | 
					        // 사용 여부별로 회원을 조회합니다.
 | 
				
			||||||
        return queryFactory
 | 
					        return queryFactory
 | 
				
			||||||
                .selectFrom(member)
 | 
					                .selectFrom(member)
 | 
				
			||||||
                .where(member.status.eq(status))
 | 
					                .where(member.useFlag.eq(useFlag))
 | 
				
			||||||
                .fetch();
 | 
					                .fetch();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Optional<Member> findByUserIdAndStatus(String userId, String status) {
 | 
					    public Optional<Member> findByUserIdAndUseFlag(String userId, Boolean useFlag) {
 | 
				
			||||||
        // 사용자 ID와 상태를 모두 만족하는 회원을 조회합니다.
 | 
					        // 사용자 ID와 사용 여부를 모두 만족하는 회원을 조회합니다.
 | 
				
			||||||
        // and() 메서드를 사용하여 여러 조건을 결합합니다.
 | 
					        // and() 메서드를 사용하여 여러 조건을 결합합니다.
 | 
				
			||||||
        Member foundMember = queryFactory
 | 
					        Member foundMember = queryFactory
 | 
				
			||||||
                .selectFrom(member)
 | 
					                .selectFrom(member)
 | 
				
			||||||
                .where(member.userId.eq(userId)
 | 
					                .where(member.userId.eq(userId)
 | 
				
			||||||
                        .and(member.status.eq(status)))
 | 
					                        .and(member.useFlag.eq(useFlag)))
 | 
				
			||||||
                .fetchOne();
 | 
					                .fetchOne();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return Optional.ofNullable(foundMember);
 | 
					        return Optional.ofNullable(foundMember);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Page<Member> findMembersByCondition(String userId, String role, String status, Pageable pageable) {
 | 
					    public Page<Member> findMembersByCondition(String userId, String role, Boolean useFlag, Pageable pageable) {
 | 
				
			||||||
        // BooleanBuilder를 사용하여 동적 쿼리를 구성합니다.
 | 
					        // BooleanBuilder를 사용하여 동적 쿼리를 구성합니다.
 | 
				
			||||||
        // null이 아닌 조건만 쿼리에 포함시킵니다.
 | 
					        // null이 아닌 조건만 쿼리에 포함시킵니다.
 | 
				
			||||||
        BooleanBuilder builder = new BooleanBuilder();
 | 
					        BooleanBuilder builder = new BooleanBuilder();
 | 
				
			||||||
@@ -88,12 +89,12 @@ public class MemberRepositoryImpl implements MemberRepositoryCustom {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // 역할이 제공된 경우 정확한 일치 조건을 추가합니다.
 | 
					        // 역할이 제공된 경우 정확한 일치 조건을 추가합니다.
 | 
				
			||||||
        if (role != null && !role.trim().isEmpty()) {
 | 
					        if (role != null && !role.trim().isEmpty()) {
 | 
				
			||||||
            builder.and(member.role.eq(role));
 | 
					            builder.and(member.role.eq(MemberRole.fromValue(role)));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 상태가 제공된 경우 정확한 일치 조건을 추가합니다.
 | 
					        // 사용 여부가 제공된 경우 정확한 일치 조건을 추가합니다.
 | 
				
			||||||
        if (status != null && !status.trim().isEmpty()) {
 | 
					        if (useFlag != null) {
 | 
				
			||||||
            builder.and(member.status.eq(status));
 | 
					            builder.and(member.useFlag.eq(useFlag));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 전체 개수를 조회합니다.
 | 
					        // 전체 개수를 조회합니다.
 | 
				
			||||||
@@ -121,7 +122,7 @@ public class MemberRepositoryImpl implements MemberRepositoryCustom {
 | 
				
			|||||||
        // 여러 조건을 조합하여 복잡한 쿼리를 작성합니다.
 | 
					        // 여러 조건을 조합하여 복잡한 쿼리를 작성합니다.
 | 
				
			||||||
        return queryFactory
 | 
					        return queryFactory
 | 
				
			||||||
                .selectFrom(member)
 | 
					                .selectFrom(member)
 | 
				
			||||||
                .where(member.status.eq("A") // 활성 상태
 | 
					                .where(member.useFlag.eq(true) // 사용 중인 상태
 | 
				
			||||||
                        .and(member.lastLoginAt.isNotNull()) // 마지막 로그인 시간이 존재
 | 
					                        .and(member.lastLoginAt.isNotNull()) // 마지막 로그인 시간이 존재
 | 
				
			||||||
                        .and(member.lastLoginAt.after(lastLoginAfter))) // 특정 시간 이후
 | 
					                        .and(member.lastLoginAt.after(lastLoginAfter))) // 특정 시간 이후
 | 
				
			||||||
                .orderBy(member.lastLoginAt.desc()) // 마지막 로그인 시간 기준 내림차순 정렬
 | 
					                .orderBy(member.lastLoginAt.desc()) // 마지막 로그인 시간 기준 내림차순 정렬
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ public interface MemberService extends UserDetailsService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    UserDetails loadUserByUsername(String id);
 | 
					    UserDetails loadUserByUsername(String id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    long createMember(MemberDto memberDTO);
 | 
					    MemberDto createMember(MemberDto memberDTO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void updateRefreshToken(MemberDto memberDTO);
 | 
					    void updateRefreshToken(MemberDto memberDTO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,15 +2,17 @@ package com.bio.bio_backend.domain.user.member.service;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
 | 
					import com.bio.bio_backend.domain.user.member.dto.MemberDto;
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.entity.Member;
 | 
					import com.bio.bio_backend.domain.user.member.entity.Member;
 | 
				
			||||||
 | 
					import com.bio.bio_backend.domain.user.member.enums.MemberRole;
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.mapper.MemberMapper;
 | 
					import com.bio.bio_backend.domain.user.member.mapper.MemberMapper;
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.repository.MemberRepository;
 | 
					import com.bio.bio_backend.domain.user.member.repository.MemberRepository;
 | 
				
			||||||
import com.bio.bio_backend.global.constants.MemberConstants;
 | 
					import com.bio.bio_backend.domain.user.member.exception.UserDuplicateException;
 | 
				
			||||||
import lombok.RequiredArgsConstructor;
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
import org.springframework.security.core.userdetails.UserDetails;
 | 
					import org.springframework.security.core.userdetails.UserDetails;
 | 
				
			||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
 | 
					import org.springframework.security.core.userdetails.UsernameNotFoundException;
 | 
				
			||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 | 
					import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
 | 
					import org.springframework.transaction.annotation.Transactional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
@@ -18,59 +20,81 @@ import java.util.Map;
 | 
				
			|||||||
@Service
 | 
					@Service
 | 
				
			||||||
@RequiredArgsConstructor
 | 
					@RequiredArgsConstructor
 | 
				
			||||||
@Slf4j
 | 
					@Slf4j
 | 
				
			||||||
 | 
					@Transactional(readOnly = true)
 | 
				
			||||||
public class MemberServiceImpl implements MemberService {
 | 
					public class MemberServiceImpl implements MemberService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final MemberMapper memberMapper;
 | 
					    private final MemberMapper memberMapper;  // MapStruct Mapper 사용
 | 
				
			||||||
    private final MemberRepository memberRepository;
 | 
					    private final MemberRepository memberRepository;
 | 
				
			||||||
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
 | 
					    private final BCryptPasswordEncoder bCryptPasswordEncoder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
 | 
					    public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
 | 
				
			||||||
 | 
					        // JPA 레파지토리를 사용하여 회원 조회
 | 
				
			||||||
 | 
					        Member member = memberRepository.findByUserId(id)
 | 
				
			||||||
 | 
					                .orElseThrow(() -> new UsernameNotFoundException("User not found with id : " + id));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        MemberDto member = memberMapper.loadUserByUsername(id);
 | 
					        // MapStruct를 사용하여 Member 엔티티를 MemberDto로 변환
 | 
				
			||||||
 | 
					        MemberDto memberDto = memberMapper.toMemberDto(member);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (member == null) {
 | 
					        return memberDto;
 | 
				
			||||||
            throw new UsernameNotFoundException("User not found with id : " + id);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return member;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public long createMember(MemberDto memberDTO) {
 | 
					    @Transactional
 | 
				
			||||||
        // JPA Entity를 사용하여 회원 생성
 | 
					    public MemberDto createMember(MemberDto memberDTO) {
 | 
				
			||||||
 | 
					        // userId 중복 체크
 | 
				
			||||||
 | 
					        if (memberRepository.existsByUserId(memberDTO.getUserId())) {
 | 
				
			||||||
 | 
					            throw new UserDuplicateException("User ID already exists");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        Member member = Member.builder()
 | 
					        Member member = Member.builder()
 | 
				
			||||||
                .userId(memberDTO.getId())
 | 
					                .userId(memberDTO.getUserId())
 | 
				
			||||||
                .password(bCryptPasswordEncoder.encode(memberDTO.getPw()))
 | 
					                .password(bCryptPasswordEncoder.encode(memberDTO.getPassword()))
 | 
				
			||||||
                .role(MemberConstants.ROLE_MEMBER)
 | 
					                .role(MemberRole.getDefault())
 | 
				
			||||||
                .status(MemberConstants.MEMBER_ACTIVE)
 | 
					 | 
				
			||||||
                .build();
 | 
					                .build();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // JPA 레파지토리를 통해 저장
 | 
					 | 
				
			||||||
        Member savedMember = memberRepository.save(member);
 | 
					        Member savedMember = memberRepository.save(member);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // 저장된 회원의 oid를 반환
 | 
					        return memberMapper.toMemberDto(savedMember);
 | 
				
			||||||
        return savedMember.getOid();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
    public void updateRefreshToken(MemberDto memberDTO) {
 | 
					    public void updateRefreshToken(MemberDto memberDTO) {
 | 
				
			||||||
        memberMapper.updateRefreshToken(memberDTO);
 | 
					        // JPA를 사용하여 refresh token 업데이트
 | 
				
			||||||
 | 
					        Member member = memberRepository.findByUserId(memberDTO.getUserId())
 | 
				
			||||||
 | 
					                .orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + memberDTO.getUserId()));
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        member.setRefreshToken(memberDTO.getRefreshToken());
 | 
				
			||||||
 | 
					        memberRepository.save(member);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public String getRefreshToken(String id) {
 | 
					    public String getRefreshToken(String id) {
 | 
				
			||||||
        return memberMapper.getRefreshToken(id);
 | 
					        Member member = memberRepository.findByUserId(id)
 | 
				
			||||||
 | 
					                .orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + id));
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return member.getRefreshToken();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
    public int deleteRefreshToken(String id) {
 | 
					    public int deleteRefreshToken(String id) {
 | 
				
			||||||
        return memberMapper.deleteRefreshToken(id);
 | 
					        Member member = memberRepository.findByUserId(id)
 | 
				
			||||||
 | 
					                .orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + id));
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        member.setRefreshToken(null);
 | 
				
			||||||
 | 
					        memberRepository.save(member);
 | 
				
			||||||
 | 
					        return 1; // 성공 시 1 반환
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public List<MemberDto> selectMemberList(Map<String, String> params) {
 | 
					    public List<MemberDto> selectMemberList(Map<String, String> params) {
 | 
				
			||||||
        return memberMapper.selectMemberList(params);
 | 
					        // JPA를 사용하여 회원 목록 조회 (간단한 구현)
 | 
				
			||||||
 | 
					        List<Member> members = memberRepository.findAll();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // MapStruct를 사용하여 Member 엔티티 리스트를 MemberDto 리스트로 변환
 | 
				
			||||||
 | 
					        return memberMapper.toMemberDtoList(members);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
@@ -79,35 +103,39 @@ public class MemberServiceImpl implements MemberService {
 | 
				
			|||||||
        Member member = memberRepository.findById(seq)
 | 
					        Member member = memberRepository.findById(seq)
 | 
				
			||||||
                .orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. seq: " + seq));
 | 
					                .orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. seq: " + seq));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Member 엔티티를 MemberDto로 변환하여 반환
 | 
					        // MapStruct를 사용하여 Member 엔티티를 MemberDto로 자동 변환
 | 
				
			||||||
        MemberDto memberDto = new MemberDto();
 | 
					        return memberMapper.toMemberDto(member);
 | 
				
			||||||
        memberDto.setSeq(member.getOid().intValue());  // Long을 int로 안전하게 변환
 | 
					 | 
				
			||||||
        memberDto.setId(member.getUserId());
 | 
					 | 
				
			||||||
        memberDto.setPw(member.getPassword());
 | 
					 | 
				
			||||||
        memberDto.setRole(member.getRole());
 | 
					 | 
				
			||||||
        memberDto.setStatus(member.getStatus());
 | 
					 | 
				
			||||||
        memberDto.setRegAt(java.sql.Timestamp.valueOf(member.getCreatedAt()));  // LocalDateTime을 Timestamp로 변환
 | 
					 | 
				
			||||||
        memberDto.setUdtAt(java.sql.Timestamp.valueOf(member.getUpdatedAt()));
 | 
					 | 
				
			||||||
        if (member.getLastLoginAt() != null) {
 | 
					 | 
				
			||||||
            memberDto.setLastLoginAt(java.sql.Timestamp.valueOf(member.getLastLoginAt()));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        memberDto.setRefreshToken(member.getRefreshToken());
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return memberDto;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int updateMember(MemberDto member) {
 | 
					    @Transactional
 | 
				
			||||||
        return memberMapper.updateMember(member);
 | 
					    public int updateMember(MemberDto memberDto) {
 | 
				
			||||||
 | 
					        Member member = memberRepository.findByUserId(memberDto.getUserId())
 | 
				
			||||||
 | 
					                .orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + memberDto.getUserId()));
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // 비밀번호가 변경된 경우 암호화
 | 
				
			||||||
 | 
					        if (memberDto.getPassword() != null && !memberDto.getPassword().isEmpty()) {
 | 
				
			||||||
 | 
					            member.setPassword(bCryptPasswordEncoder.encode(memberDto.getPassword()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        member.setRole(memberDto.getRole());
 | 
				
			||||||
 | 
					        member.setUseFlag(memberDto.getUseFlag());
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        memberRepository.save(member);
 | 
				
			||||||
 | 
					        return 1; // 성공 시 1 반환
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int deleteMember(MemberDto member) {
 | 
					    @Transactional
 | 
				
			||||||
 | 
					    public int deleteMember(MemberDto memberDto) {
 | 
				
			||||||
 | 
					        Member member = memberRepository.findByUserId(memberDto.getUserId())
 | 
				
			||||||
 | 
					                .orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + memberDto.getUserId()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        member.setStatus(MemberConstants.MEMBER_INACTIVE);
 | 
					        member.setUseFlag(false);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        log.info(member.toString());
 | 
					        log.info("회원 삭제 처리: {}", member.toString());
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return memberMapper.updateMember(member);
 | 
					        memberRepository.save(member);
 | 
				
			||||||
 | 
					        return 1; // 성공 시 1 반환
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,21 +6,13 @@ import org.aspectj.lang.annotation.Around;
 | 
				
			|||||||
import org.aspectj.lang.annotation.Aspect;
 | 
					import org.aspectj.lang.annotation.Aspect;
 | 
				
			||||||
import org.springframework.stereotype.Component;
 | 
					import org.springframework.stereotype.Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					@Aspect
 | 
				
			||||||
 * Repository 계층의 메서드 호출을 로깅하는 AOP(Aspect-Oriented Programming) 클래스
 | 
					@Component
 | 
				
			||||||
 * 모든 Repository 인터페이스의 메서드 호출 시점과 실행 시간을 로그로 기록합니다.
 | 
					@Slf4j
 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Aspect  // AOP 기능을 활성화하는 어노테이션
 | 
					 | 
				
			||||||
@Component  // Spring Bean으로 등록하는 어노테이션
 | 
					 | 
				
			||||||
@Slf4j  // Lombok의 로깅 기능을 제공하는 어노테이션
 | 
					 | 
				
			||||||
public class RepositoryLoggingAspect {
 | 
					public class RepositoryLoggingAspect {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Repository 계층의 모든 메서드 호출을 가로채서 로깅하는 Around 어드바이스
 | 
					     * Repository 계층의 모든 메서드 호출을 가로채서 로깅하는 Around 어드바이스
 | 
				
			||||||
     * 
 | 
					 | 
				
			||||||
     * @param pjp ProceedingJoinPoint - 실행될 메서드의 정보를 담고 있는 객체
 | 
					 | 
				
			||||||
     * @return Object - 원본 메서드의 실행 결과
 | 
					 | 
				
			||||||
     * @throws Throwable - 원본 메서드에서 발생할 수 있는 예외
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Around("execution(* org.springframework.data.repository.Repository+.*(..))")
 | 
					    @Around("execution(* org.springframework.data.repository.Repository+.*(..))")
 | 
				
			||||||
    public Object logQueryCall(ProceedingJoinPoint pjp) throws Throwable {
 | 
					    public Object logQueryCall(ProceedingJoinPoint pjp) throws Throwable {
 | 
				
			||||||
@@ -47,10 +39,7 @@ public class RepositoryLoggingAspect {
 | 
				
			|||||||
            // 원본 메서드의 결과를 반환
 | 
					            // 원본 메서드의 결과를 반환
 | 
				
			||||||
            return result;
 | 
					            return result;
 | 
				
			||||||
        } catch (Throwable ex) {
 | 
					        } catch (Throwable ex) {
 | 
				
			||||||
            // 메서드 실행 중 예외 발생 시 로그로 기록
 | 
					 | 
				
			||||||
            log.warn("[QUERY FAIL] {}.{}() -> {}", type, method, ex.toString());
 | 
					            log.warn("[QUERY FAIL] {}.{}() -> {}", type, method, ex.toString());
 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            // 예외를 다시 던져서 원래의 예외 처리 흐름을 유지
 | 
					 | 
				
			||||||
            throw ex;
 | 
					            throw ex;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,8 @@
 | 
				
			|||||||
package com.bio.bio_backend.global.config;
 | 
					package com.bio.bio_backend.global.config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.modelmapper.ModelMapper;
 | 
					 | 
				
			||||||
import org.springframework.context.annotation.Bean;
 | 
					import org.springframework.context.annotation.Bean;
 | 
				
			||||||
import org.springframework.context.annotation.Configuration;
 | 
					import org.springframework.context.annotation.Configuration;
 | 
				
			||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 | 
					import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 | 
				
			||||||
import org.springframework.web.cors.CorsConfiguration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.springframework.context.annotation.Bean;
 | 
					 | 
				
			||||||
import org.springframework.web.cors.CorsConfiguration;
 | 
					 | 
				
			||||||
import org.springframework.web.cors.CorsConfigurationSource;
 | 
					 | 
				
			||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Configuration
 | 
					@Configuration
 | 
				
			||||||
public class AppConfig {
 | 
					public class AppConfig {
 | 
				
			||||||
@@ -18,9 +11,4 @@ public class AppConfig {
 | 
				
			|||||||
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
 | 
					    public BCryptPasswordEncoder bCryptPasswordEncoder() {
 | 
				
			||||||
        return new BCryptPasswordEncoder();
 | 
					        return new BCryptPasswordEncoder();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Bean
 | 
					 | 
				
			||||||
    public ModelMapper modelMapper() {
 | 
					 | 
				
			||||||
        return new ModelMapper();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,38 +0,0 @@
 | 
				
			|||||||
package com.bio.bio_backend.global.constants;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Member 엔티티에서 사용하는 상수들을 정의하는 클래스
 | 
					 | 
				
			||||||
 * 역할(Role)과 상태(Status) 등의 상수값을 관리합니다.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class MemberConstants {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 회원 역할 상수
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static final String ROLE_MEMBER = "MEMBER";        // 일반 회원
 | 
					 | 
				
			||||||
    public static final String ROLE_ADMIN = "ADMIN";          // 관리자
 | 
					 | 
				
			||||||
    public static final String ROLE_USER = "USER";            // 사용자
 | 
					 | 
				
			||||||
    public static final String ROLE_SYSTEM_ADMIN = "SYSTEM_ADMIN"; // 시스템 관리자
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 회원 상태 상수
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static final String MEMBER_ACTIVE = "A";           // 활성 상태 (Active)
 | 
					 | 
				
			||||||
    public static final String MEMBER_INACTIVE = "I";         // 비활성 상태 (Inactive)
 | 
					 | 
				
			||||||
    public static final String MEMBER_SUSPENDED = "S";        // 정지 상태 (Suspended)
 | 
					 | 
				
			||||||
    public static final String MEMBER_DELETED = "D";          // 삭제 상태 (Deleted)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 기본값 상수
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static final String DEFAULT_ROLE = ROLE_MEMBER;    // 기본 역할
 | 
					 | 
				
			||||||
    public static final String DEFAULT_STATUS = MEMBER_ACTIVE; // 기본 상태
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 유효성 검사 상수
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static final int MIN_USER_ID_LENGTH = 4;           // 사용자 ID 최소 길이
 | 
					 | 
				
			||||||
    public static final int MAX_USER_ID_LENGTH = 20;          // 사용자 ID 최대 길이
 | 
					 | 
				
			||||||
    public static final int MIN_PASSWORD_LENGTH = 8;          // 비밀번호 최소 길이
 | 
					 | 
				
			||||||
    public static final int MAX_PASSWORD_LENGTH = 100;        // 비밀번호 최대 길이
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -3,10 +3,10 @@ package com.bio.bio_backend.global.entity;
 | 
				
			|||||||
import jakarta.persistence.*;
 | 
					import jakarta.persistence.*;
 | 
				
			||||||
import lombok.Getter;
 | 
					import lombok.Getter;
 | 
				
			||||||
import lombok.Setter;
 | 
					import lombok.Setter;
 | 
				
			||||||
import org.hibernate.annotations.GenericGenerator;
 | 
					 | 
				
			||||||
import org.springframework.data.annotation.CreatedDate;
 | 
					import org.springframework.data.annotation.CreatedDate;
 | 
				
			||||||
import org.springframework.data.annotation.LastModifiedDate;
 | 
					import org.springframework.data.annotation.LastModifiedDate;
 | 
				
			||||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
 | 
					import org.springframework.data.jpa.domain.support.AuditingEntityListener;
 | 
				
			||||||
 | 
					import com.bio.bio_backend.global.utils.OidUtil;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.time.LocalDateTime;
 | 
					import java.time.LocalDateTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,50 +20,32 @@ import java.time.LocalDateTime;
 | 
				
			|||||||
@EntityListeners(AuditingEntityListener.class)
 | 
					@EntityListeners(AuditingEntityListener.class)
 | 
				
			||||||
public abstract class BaseEntity {
 | 
					public abstract class BaseEntity {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 엔티티의 고유 식별자 (Primary Key)
 | 
					 | 
				
			||||||
     * 자동 증가하는 Long 타입으로 설정
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Id
 | 
					    @Id
 | 
				
			||||||
    @GeneratedValue(generator = "customOidGenerator")
 | 
					 | 
				
			||||||
    @GenericGenerator(
 | 
					 | 
				
			||||||
        name = "customOidGenerator",
 | 
					 | 
				
			||||||
        type = com.bio.bio_backend.global.utils.CustomIdGenerator.class
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    @Column(name = "oid", nullable = false)
 | 
					    @Column(name = "oid", nullable = false)
 | 
				
			||||||
    private Long oid;
 | 
					    private Long oid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 엔티티 생성 시간
 | 
					 | 
				
			||||||
     * JPA Auditing을 통해 자동으로 설정됨
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @CreatedDate
 | 
					    @CreatedDate
 | 
				
			||||||
    @Column(name = "created_at", nullable = false, updatable = false)
 | 
					    @Column(name = "created_at", nullable = false, updatable = false)
 | 
				
			||||||
    private LocalDateTime createdAt;
 | 
					    private LocalDateTime createdAt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 엔티티 수정 시간
 | 
					 | 
				
			||||||
     * JPA Auditing을 통해 자동으로 설정됨
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @LastModifiedDate
 | 
					    @LastModifiedDate
 | 
				
			||||||
    @Column(name = "updated_at", nullable = false)
 | 
					    @Column(name = "updated_at", nullable = false)
 | 
				
			||||||
    private LocalDateTime updatedAt;
 | 
					    private LocalDateTime updatedAt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    @Column(name = "created_oid", updatable = false)
 | 
				
			||||||
     * 엔티티 저장 전에 실행되는 메서드
 | 
					    private Long createdOid;
 | 
				
			||||||
     * 생성 시간과 수정 시간을 자동으로 설정
 | 
					
 | 
				
			||||||
     */
 | 
					    @Column(name = "updated_oid")
 | 
				
			||||||
 | 
					    private Long updatedOid;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    @PrePersist
 | 
					    @PrePersist
 | 
				
			||||||
    protected void onCreate() {
 | 
					    protected void onCreate() {
 | 
				
			||||||
        LocalDateTime now = LocalDateTime.now();
 | 
					        LocalDateTime now = LocalDateTime.now();
 | 
				
			||||||
 | 
					        this.oid = OidUtil.generateOid();
 | 
				
			||||||
        this.createdAt = now;
 | 
					        this.createdAt = now;
 | 
				
			||||||
        this.updatedAt = now;
 | 
					        this.updatedAt = now;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 엔티티 수정 전에 실행되는 메서드
 | 
					 | 
				
			||||||
     * 수정 시간을 자동으로 설정
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @PreUpdate
 | 
					    @PreUpdate
 | 
				
			||||||
    protected void onUpdate() {
 | 
					    protected void onUpdate() {
 | 
				
			||||||
        this.updatedAt = LocalDateTime.now();
 | 
					        this.updatedAt = LocalDateTime.now();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ 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 {
 | 
				
			||||||
@@ -71,4 +72,9 @@ public class GlobalExceptionHandler {
 | 
				
			|||||||
    public CustomApiResponse<Void> handleExpiredJwtException(JsonProcessingException e) {
 | 
					    public CustomApiResponse<Void> handleExpiredJwtException(JsonProcessingException e) {
 | 
				
			||||||
        return CustomApiResponse.fail(ApiResponseCode.JSON_PROCESSING_EXCEPTION, null);
 | 
					        return CustomApiResponse.fail(ApiResponseCode.JSON_PROCESSING_EXCEPTION, null);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    @ExceptionHandler(UserDuplicateException.class)
 | 
				
			||||||
 | 
					    public CustomApiResponse<Void> handleUserDuplicateException(UserDuplicateException e) {
 | 
				
			||||||
 | 
					        return CustomApiResponse.fail(ApiResponseCode.USER_ID_DUPLICATE, null);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,6 @@ import com.bio.bio_backend.global.utils.JwtUtils;
 | 
				
			|||||||
import lombok.RequiredArgsConstructor;
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
import lombok.SneakyThrows;
 | 
					import lombok.SneakyThrows;
 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
import org.modelmapper.ModelMapper;
 | 
					 | 
				
			||||||
import org.springframework.core.env.Environment;
 | 
					import org.springframework.core.env.Environment;
 | 
				
			||||||
import org.springframework.http.HttpStatus;
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
import org.springframework.http.MediaType;
 | 
					import org.springframework.http.MediaType;
 | 
				
			||||||
@@ -42,7 +41,6 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private final AuthenticationManager authenticationManager;
 | 
					    private final AuthenticationManager authenticationManager;
 | 
				
			||||||
    private final MemberService memberService;
 | 
					    private final MemberService memberService;
 | 
				
			||||||
    private final ModelMapper modelMapper;
 | 
					 | 
				
			||||||
    private final JwtUtils jwtUtils;
 | 
					    private final JwtUtils jwtUtils;
 | 
				
			||||||
    private final Environment env;
 | 
					    private final Environment env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,10 +50,10 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte
 | 
				
			|||||||
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
 | 
					    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
 | 
				
			||||||
            throws AuthenticationException {
 | 
					            throws AuthenticationException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        LoginRequestDto req = new ObjectMapper().readValue(request.getInputStream(), LoginRequestDto.class);
 | 
					        LoginRequestDto requestDto = new ObjectMapper().readValue(request.getInputStream(), LoginRequestDto.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//        UsernamePasswordAuthenticationToken authToken;
 | 
					//        UsernamePasswordAuthenticationToken authToken;
 | 
				
			||||||
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(req.getId(), req.getPw());
 | 
					        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(requestDto.getUserId(), requestDto.getPassword());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*
 | 
					        /*
 | 
				
			||||||
        if (req.getLoginLogFlag() == 1) {
 | 
					        if (req.getLoginLogFlag() == 1) {
 | 
				
			||||||
@@ -76,15 +74,15 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        MemberDto member = (MemberDto) userDetails;
 | 
					        MemberDto member = (MemberDto) userDetails;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        String accessToken = jwtUtils.generateToken(userDetails.getUsername(), member.getRole(),
 | 
					        String accessToken = jwtUtils.generateToken(member.getUserId(), member.getRole().getValue(),
 | 
				
			||||||
                Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_access"))));
 | 
					                Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_access"))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String refreshToken = jwtUtils.generateToken(userDetails.getUsername(), member.getRole(),
 | 
					        String refreshToken = jwtUtils.generateToken(member.getUserId(), member.getRole().getValue(),
 | 
				
			||||||
                Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_refresh"))));
 | 
					                Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_refresh"))));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        member.setRefreshToken(refreshToken);
 | 
					        member.setRefreshToken(refreshToken);
 | 
				
			||||||
        member.setLastLoginAt(Timestamp.valueOf(LocalDateTime.now()));
 | 
					        member.setLastLoginAt(LocalDateTime.now());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        memberService.updateRefreshToken(member);
 | 
					        memberService.updateRefreshToken(member);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -109,7 +107,10 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte
 | 
				
			|||||||
        context.setAuthentication(authResult);
 | 
					        context.setAuthentication(authResult);
 | 
				
			||||||
        contextHolder.setContext(context);
 | 
					        contextHolder.setContext(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        LoginResponseDto memberData = modelMapper.map(member, LoginResponseDto.class);
 | 
					        LoginResponseDto memberData = new LoginResponseDto();
 | 
				
			||||||
 | 
					        memberData.setUserId(member.getUserId());
 | 
				
			||||||
 | 
					        memberData.setRole(member.getRole().getValue());
 | 
				
			||||||
 | 
					        memberData.setLastLoginAt(member.getLastLoginAt());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // login 성공 메시지 전송
 | 
					        // login 성공 메시지 전송
 | 
				
			||||||
        response.setStatus(HttpStatus.OK.value());
 | 
					        response.setStatus(HttpStatus.OK.value());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
package com.bio.bio_backend.global.security;
 | 
					package com.bio.bio_backend.global.security;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.modelmapper.ModelMapper;
 | 
					 | 
				
			||||||
import org.springframework.context.annotation.Bean;
 | 
					import org.springframework.context.annotation.Bean;
 | 
				
			||||||
import org.springframework.context.annotation.Configuration;
 | 
					import org.springframework.context.annotation.Configuration;
 | 
				
			||||||
import org.springframework.core.env.Environment;
 | 
					import org.springframework.core.env.Environment;
 | 
				
			||||||
@@ -19,7 +18,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 | 
				
			|||||||
import jakarta.servlet.Filter;
 | 
					import jakarta.servlet.Filter;
 | 
				
			||||||
//import com.bio.bio_backend.domain.common.service.AccessLogService;
 | 
					//import com.bio.bio_backend.domain.common.service.AccessLogService;
 | 
				
			||||||
import com.bio.bio_backend.domain.user.member.service.MemberService;
 | 
					import com.bio.bio_backend.domain.user.member.service.MemberService;
 | 
				
			||||||
import com.bio.bio_backend.global.constants.MemberConstants;
 | 
					 | 
				
			||||||
import com.bio.bio_backend.global.exception.CustomAuthenticationFailureHandler;
 | 
					import com.bio.bio_backend.global.exception.CustomAuthenticationFailureHandler;
 | 
				
			||||||
import com.bio.bio_backend.global.exception.JwtAccessDeniedHandler;
 | 
					import com.bio.bio_backend.global.exception.JwtAccessDeniedHandler;
 | 
				
			||||||
import com.bio.bio_backend.global.exception.JwtAuthenticationEntryPoint;
 | 
					import com.bio.bio_backend.global.exception.JwtAuthenticationEntryPoint;
 | 
				
			||||||
@@ -38,7 +36,6 @@ public class WebSecurity {
 | 
				
			|||||||
    private final JwtUtils jwtUtils;
 | 
					    private final JwtUtils jwtUtils;
 | 
				
			||||||
//    private final AccessLogService accessLogService;
 | 
					//    private final AccessLogService accessLogService;
 | 
				
			||||||
    private final CorsFilter corsFilter;
 | 
					    private final CorsFilter corsFilter;
 | 
				
			||||||
    private final ModelMapper mapper;
 | 
					 | 
				
			||||||
    private final ObjectMapper objectMapper;
 | 
					    private final ObjectMapper objectMapper;
 | 
				
			||||||
    private final HttpUtils httpUtils;
 | 
					    private final HttpUtils httpUtils;
 | 
				
			||||||
    private final Environment env;
 | 
					    private final Environment env;
 | 
				
			||||||
@@ -49,7 +46,7 @@ public class WebSecurity {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private JwtAuthenticationFilter getJwtAuthenticationFilter(AuthenticationManager authenticationManager) throws Exception {
 | 
					    private JwtAuthenticationFilter getJwtAuthenticationFilter(AuthenticationManager authenticationManager) throws Exception {
 | 
				
			||||||
        JwtAuthenticationFilter filter = new JwtAuthenticationFilter(authenticationManager, memberService, mapper, jwtUtils, env);
 | 
					        JwtAuthenticationFilter filter = new JwtAuthenticationFilter(authenticationManager, memberService, jwtUtils, env);
 | 
				
			||||||
        filter.setFilterProcessesUrl("/login"); // 로그인 EndPoint
 | 
					        filter.setFilterProcessesUrl("/login"); // 로그인 EndPoint
 | 
				
			||||||
        filter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler(objectMapper));
 | 
					        filter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler(objectMapper));
 | 
				
			||||||
        return filter;
 | 
					        return filter;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,9 @@ public enum ApiResponseCode {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    AUTHENTICATION_FAILED(HttpStatus.UNAUTHORIZED.value(), "Password is invalid"),
 | 
					    AUTHENTICATION_FAILED(HttpStatus.UNAUTHORIZED.value(), "Password is invalid"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 409 Conflict
 | 
				
			||||||
 | 
					    USER_ID_DUPLICATE(HttpStatus.CONFLICT.value(), "User ID already exists"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*auth*/
 | 
					    /*auth*/
 | 
				
			||||||
    // 401 Unauthorized
 | 
					    // 401 Unauthorized
 | 
				
			||||||
    JWT_SIGNATURE_MISMATCH(HttpStatus.UNAUTHORIZED.value(), "JWT signature does not match. Authentication failed"),
 | 
					    JWT_SIGNATURE_MISMATCH(HttpStatus.UNAUTHORIZED.value(), "JWT signature does not match. Authentication failed"),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,9 @@ logging.level.org.hibernate.SQL=DEBUG
 | 
				
			|||||||
logging.level.org.hibernate.orm.jdbc.bind=TRACE
 | 
					logging.level.org.hibernate.orm.jdbc.bind=TRACE
 | 
				
			||||||
logging.level.org.springframework.data.jpa=DEBUG
 | 
					logging.level.org.springframework.data.jpa=DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Open Session in View 설정 (권장: false)
 | 
				
			||||||
 | 
					spring.jpa.open-in-view=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# P6Spy
 | 
					# P6Spy
 | 
				
			||||||
decorator.datasource.p6spy.enable-logging=true
 | 
					decorator.datasource.p6spy.enable-logging=true
 | 
				
			||||||
decorator.datasource.p6spy.log-format=%(sqlSingleLine)
 | 
					decorator.datasource.p6spy.log-format=%(sqlSingleLine)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user