Skip to content

Commit

Permalink
Merge pull request #71 from team-pofo/refactor/projectGraphQL
Browse files Browse the repository at this point in the history
[REFACTOR] 프로젝트 관련 graphql 일부 리펙토링
  • Loading branch information
sukjuhong authored Dec 27, 2024
2 parents f7b535e + 187990e commit 77cb171
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@ class ProjectController(

@QueryMapping
fun getAllProjectsByPagination(
@Argument cursor: Long,
@Argument cursor: Long?,
@Argument size: Int,
): ProjectList = projectService.getAllProjectsByPagination(size, cursor)
): ProjectList = projectService.getAllProjectsByPagination(size, cursor ?: 0)

@PreAuthorize("isAuthenticated()")
@MutationMapping
fun createProject(
@Argument title: String,
@Argument bio: String?,
@Argument urls: List<String>?,
@Argument keyImageIndex: Int?,
@Argument imageUrls: List<String>?,
@Argument content: String,
@Argument category: ProjectCategory,
Expand All @@ -46,6 +47,7 @@ class ProjectController(
title,
bio,
urls,
keyImageIndex,
imageUrls,
content,
category,
Expand All @@ -61,6 +63,7 @@ class ProjectController(
@Argument title: String?,
@Argument bio: String?,
@Argument urls: List<String>?,
@Argument keyImageIndex: Int,
@Argument imageUrls: List<String>?,
@Argument content: String?,
@Argument category: ProjectCategory?,
Expand All @@ -73,6 +76,7 @@ class ProjectController(
title,
bio,
urls,
keyImageIndex,
imageUrls,
content,
category,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ data class CreateProjectRequest(
val title: String,
val bio: String?,
val urls: List<String>?,
val keyImageIndex: Int?,
val imageUrls: List<String>?,
val content: String,
val category: ProjectCategory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data class UpdateProjectRequest(
val title: String?,
val bio: String?,
val urls: List<String>?,
val keyImageIndex: Int?,
val imageUrls: List<String>?,
val content: String?,
val category: ProjectCategory?,
Expand Down
27 changes: 27 additions & 0 deletions pofo-api/src/main/kotlin/org/pofo/api/service/ProjectService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ class ProjectService(
@Transactional
fun createProject(createProjectRequest: CreateProjectRequest): Project {
val author = entityManager.getReference(User::class.java, createProjectRequest.authorId)

val imageUrls = createProjectRequest.imageUrls ?: emptyList()
val keyImageIndex =
when {
imageUrls.isEmpty() -> -1
createProjectRequest.keyImageIndex == null -> 0
else -> createProjectRequest.keyImageIndex
}

if (keyImageIndex >= imageUrls.size || (imageUrls.isNotEmpty() && keyImageIndex < 0)) {
throw CustomException(ErrorCode.PROJECT_IMAGE_INDEX_ERROR)
}

val project =
Project
.builder()
Expand All @@ -52,11 +65,25 @@ class ProjectService(
var project =
projectRepository.findById(updateProjectRequest.projectId)
?: throw CustomException(ErrorCode.PROJECT_NOT_FOUND)

val imageUrls = updateProjectRequest.imageUrls ?: emptyList()
val keyImageIndex =
when {
imageUrls.isEmpty() -> -1
updateProjectRequest.keyImageIndex == null -> 0
else -> updateProjectRequest.keyImageIndex
}

if (keyImageIndex >= imageUrls.size || (imageUrls.isNotEmpty() && keyImageIndex <= 0)) {
throw CustomException(ErrorCode.PROJECT_IMAGE_INDEX_ERROR)
}

project =
project.update(
updateProjectRequest.title,
updateProjectRequest.bio,
updateProjectRequest.urls,
updateProjectRequest.keyImageIndex,
updateProjectRequest.imageUrls,
updateProjectRequest.content,
updateProjectRequest.category,
Expand Down
12 changes: 8 additions & 4 deletions pofo-api/src/main/resources/graphql/project.graphqls
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
type Project {
id: ID!
id: Int!
title: String!
bio: String
urls: [String]
urls: [String],
keyImageIndex: Int,
imageUrls: [String]
content: String!
isApproved: Boolean
isApproved: Boolean,
likes: Int,
category: ProjectCategory
stacks: [ProjectStack]
author: User
Expand All @@ -27,13 +29,14 @@ type Query {
# 특정 ID로 프로젝트를 조회
projectById(projectId: ID!): Project
# 프로젝트 리스트 페이지네이션
getAllProjectsByPagination(cursor: Int, size: Int!): ProjectList
getAllProjectsByPagination(cursor: Int = 0, size: Int!): ProjectList
}

type Mutation {
createProject(
title: String!,
bio: String,
keyImageIndex: Int,
urls: [String],
imageUrls: [String],
content: String!,
Expand All @@ -46,6 +49,7 @@ type Mutation {
title: String,
bio: String,
urls: [String],
keyImageIndex: Int!,
imageUrls: [String],
content: String,
category: ProjectCategory
Expand Down
1 change: 0 additions & 1 deletion pofo-api/src/main/resources/graphql/user.graphqls
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
type User {
id: ID!
name: String!
email: String!
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.pofo.api.controller

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.pofo.api.dto.CreateProjectRequest
import org.pofo.api.dto.RegisterRequest
Expand Down Expand Up @@ -102,6 +103,7 @@ internal class ProjectControllerTest
}

@Test
@DisplayName("페이지 네이션 적은 것 테스트")
fun getAllProjectsByPagination() {
// given
val savedProjects = mutableListOf<Project>()
Expand Down Expand Up @@ -131,6 +133,40 @@ internal class ProjectControllerTest
.isEqualTo(false)
}

@Test
@DisplayName("2번째 페이지 데이터 검증")
fun getSecondPageProjectsByPaginationTest() {
// given
val savedProjects = mutableListOf<Project>()
repeat(20) {
savedProjects.add(saveProject(createProject(), savedUser.id))
}

val graphQlTester =
HttpGraphQlTester
.builder(client)
.build()

val firstPageCursor = savedProjects[savedProjects.size - 5].id
val expectedSecondPageProjects = savedProjects.subList(10, 15).reversed()

// when & then
graphQlTester
.documentName("getAllProjectsByPagination")
.variable("cursor", firstPageCursor)
.variable("size", 5)
.execute()
.path("getAllProjectsByPagination.projectCount")
.entity(Int::class.java)
.isEqualTo(5)
.path("getAllProjectsByPagination.projects[*].title")
.entityList(String::class.java)
.containsExactly(*expectedSecondPageProjects.map { it.title }.toTypedArray())
.path("getAllProjectsByPagination.hasNext")
.entity(Boolean::class.java)
.isEqualTo(true)
}

@Test
fun updateProject() {
// given
Expand All @@ -147,6 +183,7 @@ internal class ProjectControllerTest
.documentName("updateProject")
.variable("projectId", savedProject.id)
.variable("title", newTitle)
.variable("keyImageIndex", 0)
.execute()
.path("updateProject.title")
.entity(String::class.java)
Expand All @@ -163,6 +200,7 @@ internal class ProjectControllerTest
bio = project.bio,
content = project.content,
urls = project.urls,
keyImageIndex = 0,
imageUrls = project.imageUrls,
category = project.category,
stacks = project.stacks,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mutation updateProject(
$title: String,
$bio: String,
$urls: [String],
$keyImageIndex: Int!,
$imageUrls: [String],
$content: String,
$category: ProjectCategory
Expand All @@ -12,6 +13,7 @@ mutation updateProject(
title: $title,
bio: $bio,
urls: $urls,
keyImageIndex: $keyImageIndex,
imageUrls: $imageUrls,
content: $content,
category: $category
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ enum class ErrorCode(
// PROJECT
PROJECT_NOT_FOUND(404, "프로젝트를 찾을 수 없습니다.", "PROJ-001"),
PROJECT_STACK_NOT_FOUND(400, "프로젝트 스택을 찾을 수 없습니다.", "PROJ-002"),
PROJECT_IMAGE_INDEX_ERROR(400, "대표 이미지 인덱스가 잘못되었습니다.", "PROJ-003"),
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ public class Project {
@Column
private String Bio; // 한줄 소개

@Column
@Builder.Default
private Integer keyImageIndex = -1; // 대표 이미지 인덱스

@Column
@Builder.Default
private Long likes = 0L; //좋아요 수 (매번 집계 쿼리 사용을 피하기 위함)

@Convert(converter = StringListConverter.class)
@Column(columnDefinition = "TEXT")
private List<String> urls; // 유저가 설정한 url list ex) github, npm 등등
Expand Down Expand Up @@ -53,7 +61,7 @@ public class Project {
@JoinColumn(name = "user_id")
private User author;

public Project update(String title, String bio, List<String> urls, List<String> imageUrls, String content, ProjectCategory category, List<ProjectStack> stacks) {
public Project update(String title, String bio, List<String> urls, Integer keyImageIndex, List<String> imageUrls, String content, ProjectCategory category, List<ProjectStack> stacks) {
if (title != null) {
this.title = title;
}
Expand All @@ -63,6 +71,9 @@ public Project update(String title, String bio, List<String> urls, List<String>
if (urls != null) {
this.urls = urls;
}
if (keyImageIndex != null) {
this.keyImageIndex = keyImageIndex;
}
if (imageUrls != null) {
this.imageUrls = imageUrls;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,14 @@ public class ProjectCustomRepositoryImpl implements ProjectCustomRepository {
@Override
public ProjectList searchProjectWithCursor(int size, Long cursor) {
QProject project = QProject.project;
BooleanExpression predicate = null;

if (cursor != null) {
predicate = project.id.lt(cursor);
}
boolean isInitialRequest = (cursor == null);

// 초기 요청: ID가 가장 큰 데이터부터 시작
List<Project> projects = queryFactory.selectFrom(project)
.where(predicate)
.orderBy(project.id.desc())
.limit(size + 1)
.where(isInitialRequest ? null : project.id.lt(cursor))
.orderBy(project.id.desc()) // 항상 ID 내림차순 정렬
.limit(size + 1) // 요청 크기 + 1로 가져와서 다음 페이지 확인
.fetch();

boolean hasNext = projects.size() > size;
Expand Down

0 comments on commit 77cb171

Please sign in to comment.