-
Notifications
You must be signed in to change notification settings - Fork 4
[fix] elasticsearch 수정 및 배포 적용 #150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
ec56218
b56aad9
a743dfa
2fbbb94
3209eb3
6af25bb
8b0f087
18f8e3d
170dfad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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: | ||
|
|
@@ -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] | ||
|
|
@@ -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: | ||
| 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 |
|---|---|---|
|
|
@@ -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") | ||
|
|
@@ -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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. createdAt을 String으로 저장 + Date 필드 매핑: 타임존 주의
대안:
🤖 Prompt for AI Agents |
||
|
|
||
| @Field(type = FieldType.Text, searchAnalyzer = "club_analyzer") | ||
| private String searchText; | ||
|
|
@@ -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(); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,7 +22,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Log4j2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RestController | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequestMapping("/auth") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequestMapping("/api/auth") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class AuthController { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final KakaoService kakaoService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 심각: 인증 코드/토큰 등 민감정보 로그 유출 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리프레시 토큰 미보관(주석 처리) — 무효화/로테이션 불가 운영에서 refreshToken 저장이 비활성화되면 강제 로그아웃/블랙리스트가 불가합니다. 프로파일/환경변수로 저장 기능을 토글하도록 처리하거나 최소한 운영 프로파일에서는 활성화하세요. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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()) { | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| User user = userOpt.get(); | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aws-actions/configure-aws-credentials 버전 업데이트
가능하면 OIDC(Role to Assume)로 전환해 키 제거도 검토하세요.
📝 Committable suggestion
🧰 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)