Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: CI/CD with Docker
name: CI/CD with Docker & ASG

on:
push:
branches: [ "deploy" ]
branches: [ "stage" ]

jobs:
deploy:
Expand All @@ -20,7 +20,7 @@ jobs:
run: |
mkdir -p ./src/main/resources/firebase
touch ./src/main/resources/application.yml
echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.yml
echo "${{ secrets.APPLICATION_STAGE }}" > ./src/main/resources/application.yml

- name: create-json
uses: jsdaniell/[email protected]
Expand Down Expand Up @@ -50,16 +50,16 @@ jobs:
push: true
tags: ${{ secrets.DOCKER_REPO }}:latest

- name: Deploy to Server
uses: appleboy/ssh-action@master
- name: AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
Comment on lines +53 to 55
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

aws-actions/configure-aws-credentials 버전 업데이트

  • actionlint 경고대로 v2는 더 이상 권장되지 않습니다. v4로 올리세요.
-      - name: AWS credentials
-        uses: aws-actions/configure-aws-credentials@v2
+      - name: AWS credentials
+        uses: aws-actions/configure-aws-credentials@v4
         with:
           aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
           aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
           aws-region: ap-northeast-2

가능하면 OIDC(Role to Assume)로 전환해 키 제거도 검토하세요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
- name: AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
aws-region: ap-northeast-2
🧰 Tools
🪛 actionlint (1.7.7)

54-54: the runner of "aws-actions/configure-aws-credentials@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
envs: GITHUB_SHA
script: |
echo "${{ secrets.DOCKER_COMPOSE }}" | sudo tee ./docker-compose.yml
sudo docker ps -q | xargs -r sudo docker stop && sudo docker ps -aq | xargs -r sudo docker rm
sudo docker compose -f ./docker-compose.yml down --rmi all
sudo docker pull ${{ secrets.DOCKER_REPO}}:latest
sudo docker compose -f ./docker-compose.yml up -d
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
aws-region: ap-northeast-2

- name: Auto Scaling Group Refresh
run: |
aws autoscaling start-instance-refresh \
--auto-scaling-group-name onlyone-buddkit-back-asg \
--strategy "Rolling" \
--preferences "MinHealthyPercentage=50"
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

@RestController
@RequiredArgsConstructor
@RequestMapping("/clubs/{clubId}/chat")
@RequestMapping("/api/clubs/{clubId}/chat")
public class ChatRoomRestController {

private final ChatRoomService chatRoomService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

@RestController
@RequiredArgsConstructor
@RequestMapping("/chat")
@RequestMapping("/api/chat")
public class MessageRestController {

private final MessageService messageService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ public class MessageService {
* 메시지 저장
*/
@Transactional
public ChatMessageResponse saveMessage(Long chatRoomId, Long kakaoId, String text) {
public ChatMessageResponse saveMessage(Long chatRoomId, Long userId, String text) {
if (text == null || text.isBlank()) throw new CustomException(ErrorCode.MESSAGE_BAD_REQUEST);

ChatRoom chatRoom = chatRoomRepository.findById(chatRoomId)
.orElseThrow(() -> new CustomException(ErrorCode.CHAT_ROOM_NOT_FOUND));
User user = userRepository.findByKakaoId(kakaoId)
User user = userRepository.findByUserId(userId)
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

// 채팅방 미참여자 차단
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
@RestController
@Tag(name = "Club")
@RequiredArgsConstructor
@RequestMapping("/clubs")
@RequestMapping("/api/clubs")
public class ClubController {

private final ClubService clubService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.springframework.data.elasticsearch.annotations.DateFormat;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import com.fasterxml.jackson.annotation.JsonFormat;

@Document(indexName = "clubs")
Expand Down Expand Up @@ -52,10 +54,8 @@ public class ClubDocument {
@Field(type = FieldType.Keyword)
private String interestKoreanName;

@Field(type = FieldType.Date,
pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS||yyyy-MM-dd'T'HH:mm:ss.SSS||yyyy-MM-dd'T'HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSS]")
private LocalDateTime createdAt;
@Field(type = FieldType.Date, pattern = "yyyy-MM-dd'T'HH:mm:ss")
private String createdAt;
Comment on lines +57 to +58
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

createdAt을 String으로 저장 + Date 필드 매핑: 타임존 주의

  • 문자열로 포맷팅해 전송할 때 타임존 정보를 잃습니다. ES는 타임존 미지정 값을 UTC로 해석하므로, 서버 로컬(예: Asia/Seoul) 시간으로 포맷팅 시 9시간 오프셋 문제가 생길 수 있습니다.

대안:

  • 가능하면 LocalDateTime 유지 + 멀티 패턴(혹은 strict_date_optional_time)으로 파싱.
  • 문자열 유지 시 서버 표준 시간대를 UTC로 고정하여 포맷팅하거나 오프셋 포함 패턴 사용(운영 제약이 없다면).
🤖 Prompt for AI Agents
In src/main/java/com/example/onlyone/domain/club/document/ClubDocument.java
around lines 57-58, the createdAt field is declared as String while annotated as
an Elasticsearch Date, which loses timezone info when formatted; change the
field type to java.time.LocalDateTime (or java.time.OffsetDateTime/Instant if
you need explicit offsets) and update mapping to accept multi-patterns (or use
strict_date_optional_time with offset) so ES parses correctly; alternatively, if
you must keep String, ensure all code formats timestamps to UTC or include the
offset in the string (e.g., use ISO_OFFSET_DATE_TIME) before indexing and update
the @Field pattern to match the offset-aware format.


@Field(type = FieldType.Text, searchAnalyzer = "club_analyzer")
private String searchText;
Expand All @@ -74,7 +74,7 @@ public static ClubDocument from(Club club) {
.interestId(club.getInterest().getInterestId())
.interestCategory(category.name())
.interestKoreanName(category.getKoreanName())
.createdAt(club.getCreatedAt())
.createdAt(club.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")))
.searchText(club.getName() + " " + club.getDescription())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ public void addSchedule(Schedule schedule) {
}

public void incrementMemberCount() {
this.memberCount++;
if (this.memberCount == null) {
this.memberCount = 1L;
} else {
this.memberCount++;
}
}

public void decrementMemberCount() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ public ClubCreateResponseDto createClub(ClubRequestDto requestDto) {
Interest interest = interestRepository.findByCategory(Category.from(requestDto.getCategory()))
.orElseThrow(() -> new CustomException(ErrorCode.INTEREST_NOT_FOUND));
Club club = requestDto.toEntity(interest);
club.incrementMemberCount();
clubRepository.save(club);

// 모임장의 UserClub 생성
User user = userService.getCurrentUser();
UserClub userClub = UserClub.builder()
Expand All @@ -59,7 +61,7 @@ public ClubCreateResponseDto createClub(ClubRequestDto requestDto) {
.clubRole(ClubRole.LEADER)
.build();
userClubRepository.save(userClub);
club.incrementMemberCount();

// 모임 전체 채팅방 생성
ChatRoom chatRoom = ChatRoom.builder()
.club(club)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@RestController
@Tag(name = "feed")
@RequiredArgsConstructor
@RequestMapping("/clubs/{clubId}/feeds")
@RequestMapping("/api/clubs/{clubId}/feeds")
public class FeedController {
private final FeedService feedService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
@Tag(name = "feed-main", description = "전체 피드 조회 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/feeds")
@RequestMapping("/api/feeds")
public class FeedMainController {
private final FeedMainService feedMainService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class ImageController {
private final ImageService imageService;

@Operation(summary = "Presigned URL 생성", description = "S3에 이미지 업로드를 위한 Presigned URL을 생성합니다.")
@PostMapping("/{imageFolderType}/presigned-url")
@PostMapping("/api/{imageFolderType}/presigned-url")
public ResponseEntity<CommonResponse<PresignedUrlResponseDto>> generatePresignedUrl(
@PathVariable String imageFolderType,
@Valid @RequestBody PresignedUrlRequestDto request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

@Tag(name = "알림", description = "알림 관리 API")
@RestController
@RequestMapping("/notifications")
@RequestMapping("/api/notifications")
@RequiredArgsConstructor
@Slf4j
public class NotificationController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
@RestController
@Tag(name = "Payment")
@RequiredArgsConstructor
@RequestMapping("/payments")
@RequestMapping("/api/payments")
public class PaymentController {
private final PaymentService paymentService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
@RestController
@Tag(name = "Schedule")
@RequiredArgsConstructor
@RequestMapping("/clubs/{clubId}/schedules")
@RequestMapping("/api/clubs/{clubId}/schedules")
public class ScheduleController {
private final ScheduleService scheduleService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
@RestController
@Tag(name = "Search")
@RequiredArgsConstructor
@RequestMapping("/search")
@RequestMapping("/api/search")
public class SearchController {
private final SearchService searchService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
@RestController
@Tag(name = "Settlement")
@RequiredArgsConstructor
@RequestMapping("/clubs/{clubId}/schedules/{scheduleId}/settlements")
@RequestMapping("/api/clubs/{clubId}/schedules/{scheduleId}/settlements")
public class SettlementController {
private final SettlementService settlementService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

@Log4j2
@RestController
@RequestMapping("/auth")
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final KakaoService kakaoService;
Expand All @@ -31,22 +31,29 @@ public class AuthController {

@PostMapping("/kakao/callback")
public ResponseEntity<?> kakaoLogin(@RequestParam String code) {
log.error("🔍 [DEBUG] kakaoLogin 시작 - code={}", code);

try {
// 1. 인증 코드로 카카오 액세스 토큰 받기
String kakaoAccessToken = kakaoService.getAccessToken(code);
log.error("✅ [DEBUG] kakaoAccessToken={}", kakaoAccessToken);

// 2. 카카오 액세스 토큰으로 사용자 정보 받기
Map<String, Object> kakaoUserInfo = kakaoService.getUserInfo(kakaoAccessToken);
log.error("✅ [DEBUG] kakaoUserInfo={}", kakaoUserInfo);

// 3. 사용자 정보 저장 또는 업데이트
Map<String, Object> loginResult = userService.processKakaoLogin(kakaoUserInfo, kakaoAccessToken);
User user = (User) loginResult.get("user");
boolean isNewUser = (boolean) loginResult.get("isNewUser");
log.error("✅ [DEBUG] userId={}, isNewUser={}", user.getUserId(), isNewUser);

// 4. JWT 토큰 생성 (Access + Refresh)
Map<String, String> tokens = userService.generateTokenPair(user);
log.error("✅ [DEBUG] tokens 생성됨 - accessToken={}, refreshToken={}",
tokens.get("accessToken"), tokens.get("refreshToken"));

Comment on lines +34 to 55
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

심각: 인증 코드/토큰 등 민감정보 로그 유출

code, kakaoAccessToken, access/refreshToken, kakaoUserInfo를 그대로 로그로 남기고 있으며 log.error 레벨입니다. 즉시 제거/마스킹하세요.

적용 예시(민감정보 미출력, 로그 레벨 조정):

-        log.error("🔍 [DEBUG] kakaoLogin 시작 - code={}", code);
+        log.debug("kakaoLogin 시작");

-            log.error("✅ [DEBUG] kakaoAccessToken={}", kakaoAccessToken);
+            log.debug("kakaoAccessToken 수신");

-            log.error("✅ [DEBUG] kakaoUserInfo={}", kakaoUserInfo);
+            log.debug("kakaoUserInfo 수신");

-            log.error("✅ [DEBUG] userId={}, isNewUser={}", user.getUserId(), isNewUser);
+            log.debug("user resolved - userId={}, isNewUser={}", user.getUserId(), isNewUser);

-            log.error("✅ [DEBUG] tokens 생성됨 - accessToken={}, refreshToken={}",
-                    tokens.get("accessToken"), tokens.get("refreshToken"));
+            log.debug("tokens 생성 완료");

또한 성공 로그는 info, 실패는 warn/error로 일관되게 사용하세요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
log.error("🔍 [DEBUG] kakaoLogin 시작 - code={}", code);
try {
// 1. 인증 코드로 카카오 액세스 토큰 받기
String kakaoAccessToken = kakaoService.getAccessToken(code);
log.error("✅ [DEBUG] kakaoAccessToken={}", kakaoAccessToken);
// 2. 카카오 액세스 토큰으로 사용자 정보 받기
Map<String, Object> kakaoUserInfo = kakaoService.getUserInfo(kakaoAccessToken);
log.error("✅ [DEBUG] kakaoUserInfo={}", kakaoUserInfo);
// 3. 사용자 정보 저장 또는 업데이트
Map<String, Object> loginResult = userService.processKakaoLogin(kakaoUserInfo, kakaoAccessToken);
User user = (User) loginResult.get("user");
boolean isNewUser = (boolean) loginResult.get("isNewUser");
log.error("✅ [DEBUG] userId={}, isNewUser={}", user.getUserId(), isNewUser);
// 4. JWT 토큰 생성 (Access + Refresh)
Map<String, String> tokens = userService.generateTokenPair(user);
log.error("✅ [DEBUG] tokens 생성됨 - accessToken={}, refreshToken={}",
tokens.get("accessToken"), tokens.get("refreshToken"));
log.debug("kakaoLogin 시작");
try {
// 1. 인증 코드로 카카오 액세스 토큰 받기
String kakaoAccessToken = kakaoService.getAccessToken(code);
log.debug("kakaoAccessToken 수신");
// 2. 카카오 액세스 토큰으로 사용자 정보 받기
Map<String, Object> kakaoUserInfo = kakaoService.getUserInfo(kakaoAccessToken);
log.debug("kakaoUserInfo 수신");
// 3. 사용자 정보 저장 또는 업데이트
Map<String, Object> loginResult = userService.processKakaoLogin(kakaoUserInfo, kakaoAccessToken);
User user = (User) loginResult.get("user");
boolean isNewUser = (boolean) loginResult.get("isNewUser");
log.debug("user resolved - userId={}, isNewUser={}", user.getUserId(), isNewUser);
// 4. JWT 토큰 생성 (Access + Refresh)
Map<String, String> tokens = userService.generateTokenPair(user);
log.debug("tokens 생성 완료");
🤖 Prompt for AI Agents
In src/main/java/com/example/onlyone/domain/user/controller/AuthController.java
around lines 34 to 55, remove or mask all sensitive values from logs (code,
kakaoAccessToken, tokens, full kakaoUserInfo) and stop logging them at error
level; instead log only non-sensitive context (e.g., "kakaoLogin started") and
safe identifiers (if needed, a non-sensitive userId or masked id) at info level
for success and use warn/error only for failures without sensitive details.
Update each debug log to omit the token/code/userinfo payloads (or replace with
a constant like "<masked>" if you must indicate presence) and change log.error
-> log.info for success traces; ensure any catch blocks log exception
messages/errors (not tokens) at warn/error level.

// 5. refreshToken Redis에 저장 (VITE_API_BASE_URL local 시, 주석)
// 5. refreshToken Redis에 저장 (local dev 시 주석 처리 가능)
// redisTemplate.opsForValue()
// .set(user.getUserId().toString(), tokens.get("refreshToken"), Duration.ofMillis(REFRESH_TOKEN_EXPIRE_TIME));

Comment on lines +56 to 59
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

리프레시 토큰 미보관(주석 처리) — 무효화/로테이션 불가

운영에서 refreshToken 저장이 비활성화되면 강제 로그아웃/블랙리스트가 불가합니다. 프로파일/환경변수로 저장 기능을 토글하도록 처리하거나 최소한 운영 프로파일에서는 활성화하세요.

🤖 Prompt for AI Agents
In src/main/java/com/example/onlyone/domain/user/controller/AuthController.java
around lines 56 to 59, the refresh token persistence to Redis is commented out
which prevents token invalidation/rotation in production; restore and gate this
behavior behind a configuration flag (e.g., application.profile or an env var
like ENABLE_REFRESH_TOKEN_STORE) so that: when the flag is true (and in
production profile) the code writes the refresh token to Redis with the proper
expiration, otherwise skip storing for local/dev; wire this flag from
application.properties or Environment, default to true for production profiles,
and add logging for success/failure of the Redis write so ops can detect storage
issues.

Expand All @@ -57,12 +64,15 @@ public ResponseEntity<?> kakaoLogin(@RequestParam String code) {
isNewUser
);

log.error("✅ [DEBUG] 로그인 성공 - userId={}", user.getUserId());
return ResponseEntity.ok(CommonResponse.success(response));

} catch (CustomException e) {
// CustomException은 그대로 재던지기 (탈퇴한 사용자 403 에러 포함)
throw e;
log.error("❌ [DEBUG] CustomException 발생 - code={}, message={}",
e.getErrorCode(), e.getMessage(), e);
throw e; // CustomException은 그대로 재던지기
} catch (Exception e) {
// 기타 예외는 502 에러로 처리
log.error("❌ [DEBUG] Exception 발생 - message={}", e.getMessage(), e);
throw new CustomException(ErrorCode.KAKAO_LOGIN_FAILED);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*/
@Tag(name = "사용자", description = "사용자 정보 및 설정 관리 API")
@RestController
@RequestMapping("/users")
@RequestMapping("/api/users")
@RequiredArgsConstructor
@Slf4j
public class UserController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@

public interface UserRepository extends JpaRepository<User,Long> {
Optional<User> findByKakaoId(Long kakaoId);
Optional<User> findByUserId(Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
@RestController
@Tag(name = "Wallet")
@RequiredArgsConstructor
@RequestMapping("/users/wallet")
@RequestMapping("/api/users/wallet")
public class WalletController {

private final WalletService walletService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,18 @@ public WebSecurityCustomizer webSecurityCustomizer() {
}

private static final String[] AUTH_WHITELIST = {
"/signup/**",
"/login/**",
"/token",
"/center",
"/email/**",
"/api/auth/kakao/callback/**",
"/api/signup/**",
"/api/login/**",
"/api/token",
"/api/center",
"/api/email/**",
"/ws/**", // WebSocket STOMP 엔드포인트 허용
"/ws/chat/**", // SockJS는 /info, /websocket, /xhr 등 내부 경로 씀
// "/sse/subscribe/**", // SSE는 별도 필터에서 인증 처리
"/ws-native",
"/kakao/**",
"/auth/**",
"/api/kakao/**",
"/api/auth/**",
"/grafana/**", // Grafana 대시보드
"/influxdb/**", // InfluxDB API
"/write", // InfluxDB write
Expand All @@ -73,6 +74,7 @@ public WebSecurityCustomizer webSecurityCustomizer() {
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(List.of(
"https://buddkit.com",
"http://localhost:8080",
"http://localhost:5173",
"https://only-one-front-delta.vercel.app",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse

// 사용자 상태 확인 - 탈퇴한 사용자인 경우 인증 거부, GUEST와 ACTIVE는 허용
Optional<User> userOpt = userRepository.findByKakaoId(kakaoId);
log.error("userOpt = {}", userOpt.orElse(null));
if (userOpt.isPresent()) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

PII/노이즈 로그: user 엔티티 직렬화 로깅 지양

에러 레벨로 엔티티 전체를 출력하면 PII 노출·로그 스팸 우려가 큽니다. presence 중심의 디버그 로그로 축소하세요.

다음 변경을 권장합니다.

-            log.error("userOpt = {}", userOpt.orElse(null));
+            if (log.isDebugEnabled()) {
+                log.debug("User lookup by kakaoId={} present={}", kakaoId, userOpt.isPresent());
+            }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (userOpt.isPresent()) {
if (log.isDebugEnabled()) {
log.debug("User lookup by kakaoId={} present={}", kakaoId, userOpt.isPresent());
}
if (userOpt.isPresent()) {
🤖 Prompt for AI Agents
In src/main/java/com/example/onlyone/global/filter/JwtAuthenticationFilter.java
around line 65, the code logs the entire user entity at error level which risks
PII exposure and noisy logs; replace that with a presence-focused, non-PII
debug/info log (e.g., "user present for token" or "user found" and optionally
log only a non-sensitive identifier or masked id), remove serialization of the
full entity from logs, and lower the log level from error to debug/info so only
presence is recorded without exposing sensitive fields.

User user = userOpt.get();

Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/elasticsearch/club-create-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
},
"createdAt": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss.SSSSSS||yyyy-MM-dd'T'HH:mm:ss.SSS||yyyy-MM-dd'T'HH:mm:ss"
"format": "yyyy-MM-dd'T'HH:mm:ss"
},
"searchText": {
"type": "text",
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/elasticsearch/club-mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
},
"createdAt": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss.SSSSSS||yyyy-MM-dd'T'HH:mm:ss.SSS||yyyy-MM-dd'T'HH:mm:ss"
"format": "yyyy-MM-dd'T'HH:mm:ss"
},
"searchText": {
"type": "text",
Expand Down