Skip to content
Merged
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
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-hateoas'

implementation 'org.projectlombok:lombok:1.18.30'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
Expand All @@ -40,6 +41,7 @@ dependencies {
developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'com.h2database:h2'
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

테스트 DB 설정 불일치(H2 추가 vs 테스트 YML은 PostgreSQL 사용)

둘 중 하나로 정리하세요. 아래 두 가지 옵션 중 선택 권장.

옵션 A: PostgreSQL로 일원화(권장: Testcontainers 사용)

-    testImplementation 'com.h2database:h2'
+    testImplementation 'org.testcontainers:junit-jupiter'
+    testImplementation 'org.testcontainers:postgresql'

옵션 B: H2 인메모리로 일원화

  • build.gradle 유지
  • src/test/resources/application.yml을 H2로 변경(아래 코멘트 참고)

CI/로컬 모두에서 재현성 높은 Testcontainers 사용을 권장합니다.


검증을 위해 아래 스크립트를 실행합니다.


🏁 Script executed:

#!/bin/bash
set -e
# 테스트 리소스 파일 목록 확인
find . -type f -path '*/src/test/resources/*' -maxdepth 4

# application.yml 내용 상단 200줄 출력
if [ -f src/test/resources/application.yml ]; then
  sed -n '1,200p' src/test/resources/application.yml
fi

# 테스트 리소스에서 PostgreSQL 참조 검색
grep -R "postgres" -n src/test/resources || true

# 테스트 리소스에서 H2 참조 검색
grep -R "h2" -n src/test/resources || true

Length of output: 775


테스트 DB 설정 통일 필요
build.gradle 44행에서 H2를 추가하셨지만, src/test/resources/application.yml은 PostgreSQL을 사용하고 있습니다. 둘 중 하나로 정리하세요:

옵션 A (권장 – Testcontainers 사용)

-    testImplementation 'com.h2database:h2'
+    testImplementation 'org.testcontainers:junit-jupiter'
+    testImplementation 'org.testcontainers:postgresql'

옵션 B (H2 인메모리 사용 일원화)

  • build.gradle 유지
  • src/test/resources/application.yml의 datasource 설정을 H2(jdbc:h2:mem:testdb, org.h2.Driver, org.hibernate.dialect.H2Dialect)로 변경

CI/로컬 양쪽에서 재현성 높은 Testcontainers 기반 옵션 A를 권장합니다.

📝 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
testImplementation 'com.h2database:h2'
dependencies {
// … other dependencies …
// use Testcontainers for PostgreSQL in tests
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:postgresql'
// … other dependencies …
}
🤖 Prompt for AI Agents
In build.gradle around line 44, tests currently add H2 but
src/test/resources/application.yml is configured for PostgreSQL; choose and
implement one of two fixes: Option A (recommended) — remove H2-only test
dependency if present, add Testcontainers PostgreSQL dependency and
Testcontainers JUnit integration, and update test bootstrap/config to start/use
the PostgreSQL container so application.yml remains PostgreSQL-compatible;
Option B — keep the H2 test dependency and change
src/test/resources/application.yml datasource to H2 (jdbc:h2:mem:testdb, driver
org.h2.Driver, Hibernate dialect org.hibernate.dialect.H2Dialect) and ensure any
PostgreSQL-specific SQL or dialect usage in tests is adapted for H2.

testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.postgresql:postgresql:42.6.0'

Expand Down
10 changes: 10 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
pluginManagement {
repositories {
gradlePluginPortal()
}
}

plugins {
id("org.gradle.toolchains.foojay-resolver") version "1.0.0"
}

rootProject.name = 'CLUE-Backend'
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package hello.cluebackend.domain.user.presentation;

import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;

import hello.cluebackend.global.config.JWTUtil;
import hello.cluebackend.global.security.jwt.RefreshTokenService;
import jakarta.servlet.http.HttpServletResponse;
Expand All @@ -19,11 +24,16 @@ public class TestController {
private final JWTUtil jwtUtil;

@PostMapping("/test")
public ResponseEntity<?> issueToken(@RequestParam UUID userId, @RequestParam String username, @RequestParam String role, HttpServletResponse response) {
public ResponseEntity<EntityModel<String>> issueToken(@RequestParam UUID userId, @RequestParam String username, @RequestParam String role, HttpServletResponse response) {
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

dev 전용 엔드포인트 보호

실서버 노출을 방지하기 위해 프로파일/플래그로 가드하세요(클래스 레벨 권장).

 @RestController
 @RequiredArgsConstructor
+@org.springframework.context.annotation.Profile("dev")
 public class TestController {

🏁 Script executed:

#!/bin/bash
# Locate TestController.java and display its first 200 lines
fd "TestController.java" -e java -x sed -n '1,200p' {}

echo ""
echo "Existing @Profile annotations in the repo:"
rg -n '@Profile' -n src

Length of output: 1789


🏁 Script executed:

#!/bin/bash
# locate application config files
echo "Config files:"
fd -t f -g 'application*.yml' -g 'application*.properties'

Length of output: 208


🏁 Script executed:

#!/bin/bash
# 프로젝트 루트에서 Spring Boot 설정 파일 검색
find . -type f \( -name "application*.yml" -o -name "application*.properties" \)

Length of output: 245


dev 전용 엔드포인트 보호: @Profile("dev") 클래스 레벨 적용
실서비스(prod) 프로파일에서 빈 등록 방지 위해 TestController 클래스에 @Profile("dev") 애노테이션 추가 필요

 @RestController
 @RequiredArgsConstructor
+@org.springframework.context.annotation.Profile("dev")
 public class TestController {
📝 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
public ResponseEntity<EntityModel<String>> issueToken(@RequestParam UUID userId, @RequestParam String username, @RequestParam String role, HttpServletResponse response) {
@RestController
@RequiredArgsConstructor
@org.springframework.context.annotation.Profile("dev")
public class TestController {
public ResponseEntity<EntityModel<String>> issueToken(
@RequestParam UUID userId,
@RequestParam String username,
@RequestParam String role,
HttpServletResponse response) {
// …
}
// …
}
🤖 Prompt for AI Agents
In src/main/java/hello/cluebackend/domain/user/presentation/TestController.java
around line 27, the TestController must be restricted to the dev profile; add
the Spring profile annotation to the class by annotating the controller class
with @Profile("dev") (and import org.springframework.context.annotation.Profile)
so the bean is only registered when the "dev" profile is active; keep existing
controller annotations and ensure imports compile.

String access = jwtUtil.createJwt("access", userId, username, role, 100 * 60 * 60 * 1000L);

EntityModel<String> entityModel = EntityModel.of("JWT access token and refresh token issued for dev use.");

Comment on lines +30 to +31
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

응답 메시지가 실제 동작과 불일치(리프레시 토큰 미발급)

현재 access 토큰만 발급합니다. 메시지를 정확히 수정하거나 실제로 refresh 토큰을 발급·쿠키로 설정하세요.

(간단 수정안)

-        EntityModel<String> entityModel = EntityModel.of("JWT access token and refresh token issued for dev use.");
+        EntityModel<String> entityModel = EntityModel.of("JWT access token issued for dev use.");
📝 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
EntityModel<String> entityModel = EntityModel.of("JWT access token and refresh token issued for dev use.");
EntityModel<String> entityModel = EntityModel.of("JWT access token issued for dev use.");

Link selfLink = linkTo(TestController.class).slash("test").withSelfRel();
entityModel.add(selfLink);

return ResponseEntity.ok()
.header("Authorization", "Bearer " + access)
.body("JWT access token and refresh token issued for dev use.");
.body(entityModel);
Comment on lines 35 to +37
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Authorization 헤더는 캐시 금지 헤더와 함께 반환

토큰이 캐시/프록시에 남지 않도록 Cache-Control: no-store, Pragma: no-cache를 함께 설정하고, HttpHeaders#setBearerAuth를 사용하세요.

-        return ResponseEntity.ok()
-                .header("Authorization", "Bearer " + access)
-                .body(entityModel);
+        return ResponseEntity.ok()
+                .headers(h -> {
+                    h.setBearerAuth(access);
+                    h.add("Cache-Control", "no-store");
+                    h.add("Pragma", "no-cache");
+                })
+                .body(entityModel);
📝 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
return ResponseEntity.ok()
.header("Authorization", "Bearer " + access)
.body("JWT access token and refresh token issued for dev use.");
.body(entityModel);
return ResponseEntity.ok()
.headers(h -> {
h.setBearerAuth(access);
h.add("Cache-Control", "no-store");
h.add("Pragma", "no-cache");
})
.body(entityModel);
🤖 Prompt for AI Agents
In src/main/java/hello/cluebackend/domain/user/presentation/TestController.java
around lines 35 to 37, the response sets the Authorization header directly but
lacks cache-prevention headers; update the response to use
HttpHeaders#setBearerAuth to set the bearer token and add cache-control headers
(Cache-Control: no-store and Pragma: no-cache) before building the
ResponseEntity so the token is not stored by caches or proxies.

}
}
12 changes: 12 additions & 0 deletions src/test/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
spring:
datasource:
url: jdbc:postgresql://localhost:5432/testdb
username: testuser
password: testpass
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: create-drop # 테스트 끝나면 테이블 삭제
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
Comment on lines +1 to +12
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

테스트 DB를 PostgreSQL로 강제하고 있어 H2 의존성과 충돌

H2를 사용할 계획이면 다음처럼 변경하세요:

 spring:
   datasource:
-    url: jdbc:postgresql://localhost:5432/testdb
-    username: testuser
-    password: testpass
-    driver-class-name: org.postgresql.Driver
+    url: jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+    driver-class-name: org.h2.Driver
+    username: sa
+    password:
   jpa:
     hibernate:
       ddl-auto: create-drop   # 테스트 끝나면 테이블 삭제
     properties:
       hibernate:
-        dialect: org.hibernate.dialect.PostgreSQLDialect
+        dialect: org.hibernate.dialect.H2Dialect

PostgreSQL을 유지하려면 build.gradle에서 H2를 제거하고(또는 Testcontainers를 추가) 테스트 인프라에서 로컬 DB 가용성을 보장해야 합니다.

📝 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
spring:
datasource:
url: jdbc:postgresql://localhost:5432/testdb
username: testuser
password: testpass
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: create-drop # 테스트 끝나면 테이블 삭제
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
spring:
datasource:
url: jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: create-drop # 테스트 끝나면 테이블 삭제
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 12-12: no new line character at the end of file

(new-line-at-end-of-file)

🤖 Prompt for AI Agents
In src/test/resources/application.yml around lines 1 to 12, the test
configuration forces PostgreSQL which conflicts with using H2; either switch the
test datasource to an embedded H2 URL/driver/profile for tests (update url,
driver-class-name, and Hibernate dialect to H2 or activate a test profile that
does so), or keep PostgreSQL and remove H2 from build.gradle (or add
Testcontainers and configure tests to use a containerized Postgres) and ensure
the test environment provides a reachable local Postgres instance; apply one of
these fixes so the test runtime and dependencies match.

Loading