From 8bc15e81a2c0f5bce2172de3e49cea934a24fc53 Mon Sep 17 00:00:00 2001 From: Kyeoungwoon Park Date: Sun, 4 Jan 2026 17:18:04 +0900 Subject: [PATCH 1/2] =?UTF-8?q?chore:=20build.gradle.kts=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QueryDSL의 QClass 생성 경로를 변경하였습니다. --- build.gradle.kts | 57 ++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index bd4d9ae8..7b867f7e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,6 @@ plugins { java id("org.springframework.boot") version "3.5.9" id("io.spring.dependency-management") version "1.1.7" - id("org.asciidoctor.jvm.convert") version "4.0.5" } group = "com.umc" @@ -20,7 +19,6 @@ configurations { compileOnly { extendsFrom(configurations.annotationProcessor.get()) } - create("asciidoctorExt") } repositories { @@ -32,6 +30,27 @@ val queryDslVersion = "5.0.0" val jwtVersion = "0.12.5" val awsVersion = "2.40.12" +// QueryDSL Q클래스 생성 경로 설정 +val querydslDir = layout.buildDirectory.dir("generated/querydsl").get().asFile + +sourceSets { + main { + java { + srcDirs(querydslDir) + } + } +} + +tasks.withType().configureEach { + options.generatedSourceOutputDirectory.set(querydslDir) +} + +tasks.named("clean") { + doLast { + querydslDir.deleteRecursively() + } +} + dependencies { // --- Spring Boot Starters (버전 생략: Boot가 관리) --- implementation("org.springframework.boot:spring-boot-starter-web") @@ -56,6 +75,9 @@ dependencies { annotationProcessor("com.querydsl:querydsl-apt:${queryDslVersion}:jakarta") annotationProcessor("jakarta.annotation:jakarta.annotation-api") + // APT가 jakarta 클래스를 로딩할 수 있게 명시 + annotationProcessor("jakarta.persistence:jakarta.persistence-api") + // --- Database --- implementation("org.flywaydb:flyway-core") implementation("org.flywaydb:flyway-database-postgresql") @@ -94,39 +116,8 @@ dependencies { testImplementation("org.testcontainers:testcontainers") testImplementation("org.testcontainers:junit-jupiter") testImplementation("org.testcontainers:postgresql") - - // --- Spring REST Docs --- - "asciidoctorExt"("org.springframework.restdocs:spring-restdocs-asciidoctor") - testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc") } tasks.withType { useJUnitPlatform() } - - -val snippetsDir = file("build/generated-snippets") - -tasks.test { - outputs.dir(snippetsDir) - -} - -tasks.asciidoctor { - inputs.dir(snippetsDir) - configurations("asciidoctorExt") - - sources { - include("**/index.adoc") - } - - baseDirFollowsSourceDir() - dependsOn(tasks.test) -} - -tasks.bootJar { - dependsOn(tasks.asciidoctor) - from(tasks.asciidoctor.get().outputDir) { - into("static/docs") - } -} \ No newline at end of file From 562f7a5e80c4cde824636c03a8e04d29b6b0929c Mon Sep 17 00:00:00 2001 From: Kyeoungwoon Park Date: Sun, 4 Jan 2026 17:18:52 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit user->member 변경 SQL단 예약어 충돌 회피를 위함. --- .github/copilot-instructions.md | 16 +++++----- CLAUDE.md | 30 +++++++++---------- ...4\353\266\204_\353\260\251\354\213\235.md" | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index afdcc621..1c7591fa 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -78,7 +78,7 @@ public class Challenger extends BaseEntity { @NoArgsConstructor // access level 누락 public class Challenger { @ManyToOne - private User user; // 다른 도메인 직접 참조 금지 + private Member member; // 다른 도메인 직접 참조 금지 // 도메인 로직 없이 getter/setter만 } @@ -230,10 +230,10 @@ public class ChallengerController { @PostMapping public ApiResponse register( - @AuthenticationPrincipal SecurityUser user, + @AuthenticationPrincipal SecurityUser member, @Valid @RequestBody RegisterChallengerRequest request) { - Long id = registerUseCase.register(request.toCommand(user.getUserId())); + Long id = registerUseCase.register(request.toCommand(member.getUserId())); return ApiResponse.success(id); } } @@ -407,7 +407,7 @@ public class ChallengerCommandService { private final UserRepository userRepository; // 다른 도메인 public void register(...) { - User user = userRepository.findById(userId); // 직접 접근 + User member = userRepository.findById(userId); // 직접 접근 } } ``` @@ -418,7 +418,7 @@ public class ChallengerCommandService { private final GetUserInfoUseCase getUserInfoUseCase; public void register(...) { - UserInfo user = getUserInfoUseCase.getById(userId); + UserInfo member = getUserInfoUseCase.getById(userId); } ``` @@ -446,9 +446,9 @@ public class ChallengerCommandService { // ✅ 인증된 사용자 정보는 @AuthenticationPrincipal로 @PostMapping public ApiResponse register( - @AuthenticationPrincipal SecurityUser user, + @AuthenticationPrincipal SecurityUser member, @RequestBody RegisterRequest request) { - // user.getUserId() 사용 + // member.getUserId() 사용 } // ❌ Request Body에서 userId 받지 않음 @@ -482,7 +482,7 @@ public void updateNotice(Long noticeId, UpdateCommand command, Long requesterId) // ❌ N+1 발생 가능 List challengers = repository.findAll(); for (Challenger c : challengers) { - User user = userRepository.findById(c.getUserId()); // N번 쿼리 + User member = userRepository.findById(c.getUserId()); // N번 쿼리 } // ✅ Fetch Join 또는 별도 쿼리 diff --git a/CLAUDE.md b/CLAUDE.md index 9170f517..0b574a65 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -99,7 +99,7 @@ Level 0 Level 1 Level 2 Level 3 ──────────────────────────────────────────────────────────────────────── common ◄──────────── 모든 도메인이 의존 -user ◄───────────── organization +member ◄───────────── organization │ ▼ ┌───────────┴───────────┐ @@ -110,22 +110,22 @@ user ◄───────────── organization ▼ ▼ ▼ curriculum schedule notice -community ◄────────── user, challenger +community ◄────────── member, challenger -form ◄─────────────── user (독립적) +form ◄─────────────── member (독립적) ``` | Domain | Description | Dependencies | |--------------|---------------------------------|--------------------------| | common | 공통 (BaseEntity, Exception, DTO) | 없음 | -| user | 사용자, OAuth, 약관 | common | -| organization | 기수, 지부, 학교, 스터디 | common, user | -| challenger | 챌린저, 역할, 상벌점 | user, organization | +| member | 사용자, OAuth, 약관 | common | +| organization | 기수, 지부, 학교, 스터디 | common, member | +| challenger | 챌린저, 역할, 상벌점 | member, organization | | curriculum | 커리큘럼, 워크북, 미션 | challenger | | schedule | 일정, 출석 | challenger, organization | | notice | 공지사항, 읽음, 알림 | challenger, organization | -| community | 게시글, 댓글, 번개모임 | user, challenger | -| form | 지원서 폼, 질문, 응답 | user | +| community | 게시글, 댓글, 번개모임 | member, challenger | +| form | 지원서 폼, 질문, 응답 | member | --- @@ -348,8 +348,8 @@ public class ChallengerQueryService implements GetChallengerUseCase { Challenger challenger = loadChallengerPort.findById(challengerId) .orElseThrow(() -> new BusinessException(ErrorCode.CHALLENGER_NOT_FOUND)); - UserInfo user = getUserInfoUseCase.getById(challenger.getUserId()); - return ChallengerInfo.of(challenger, user); + UserInfo member = getUserInfoUseCase.getById(challenger.getUserId()); + return ChallengerInfo.of(challenger, member); } } ``` @@ -390,9 +390,9 @@ public class ChallengerController { @PostMapping @Operation(summary = "챌린저 등록") public ApiResponse register( - @AuthenticationPrincipal SecurityUser user, + @AuthenticationPrincipal SecurityUser member, @Valid @RequestBody RegisterChallengerRequest request) { - Long id = registerUseCase.register(request.toCommand(user.getUserId())); + Long id = registerUseCase.register(request.toCommand(member.getUserId())); return ApiResponse.success(id); } @@ -454,14 +454,14 @@ public record ChallengerResponse( ```java // ❌ Bad: 다른 도메인 Entity 직접 참조 @ManyToOne -private User user; +private User member; // ✅ Good: ID만 저장 @Column(nullable = false) private Long userId; // ✅ Good: 필요시 UseCase로 조회 -UserInfo userInfo = getUserInfoUseCase.getById(challenger.getUserId()); +UserInfo memberInfo = getUserInfoUseCase.getById(challenger.getUserId()); ``` ### Event-Based Communication @@ -720,7 +720,7 @@ fix: resolve null pointer in attendance check - Entity에 `@Setter` 사용 - Controller에서 비즈니스 로직 처리 -- 다른 도메인 Entity 직접 참조 (`@ManyToOne private User user`) +- 다른 도메인 Entity 직접 참조 (`@ManyToOne private User member`) - 순환 의존성 (도메인 간 양방향 의존) - Adapter에서 트랜잭션 관리 diff --git "a/docs/\355\214\250\355\202\244\354\247\200_\352\265\254\353\266\204_\353\260\251\354\213\235.md" "b/docs/\355\214\250\355\202\244\354\247\200_\352\265\254\353\266\204_\353\260\251\354\213\235.md" index 89ccf544..4b1f3086 100644 --- "a/docs/\355\214\250\355\202\244\354\247\200_\352\265\254\353\266\204_\353\260\251\354\213\235.md" +++ "b/docs/\355\214\250\355\202\244\354\247\200_\352\265\254\353\266\204_\353\260\251\354\213\235.md" @@ -24,7 +24,7 @@ ## Domain 구분 -- user +- member - organization - challenger - activity