Skip to content

Commit cba53c6

Browse files
soyi47kth990303prefer2Seungpangyxxnghwan
authored
feat: v0.4.3을 배포한다. (#486)
* feat: DB에 인덱스를 적용한다 (#449) * feat: 엔티티에 index 적용 * build: flyway 세팅 적용 * fix: flyway sql문 오타 수정 * chore: flyway 버전 및 파일명 변경 * feat: 불필요한 이메일 인덱싱 제거 * fix: 작성한 메시지 개수를 해당페이지 개수로만 가져오는 버그 수정 (#474) * fix: 작성한 메시지 개수를 해당페이지 개수로만 가져오는 버그 수정 - 리팩터링 필요 (#477) * fix: 작성한 메시지 개수를 해당페이지 개수로만 가져오는 버그 수정 - 리팩터링 필요 (#478) * fix: 작성한 메시지 개수를 해당페이지 개수로만 가져오는 버그 수정 - 리팩터링 필요 * fix: 잘못된 querydsl JPQL로 임시로 변환 (#479) * refactor: requestApi 함수 수정 * feat: error page 수정 (#481) * fix: 멤버에게 롤링페이퍼 생성 페이지의 받는 사람 자동 완성 버그 수정 * fix: 오타 수정 Co-authored-by: TaeHyeon Kim <[email protected]> Co-authored-by: SunHo Park <[email protected]> Co-authored-by: seungpang <[email protected]> Co-authored-by: yxxnghwan <[email protected]> Co-authored-by: asebn1 <[email protected]>
1 parent 0fbb6cd commit cba53c6

File tree

23 files changed

+291
-303
lines changed

23 files changed

+291
-303
lines changed

backend/src/main/java/com/woowacourse/naepyeon/domain/Member.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@
1111
import javax.persistence.GeneratedValue;
1212
import javax.persistence.GenerationType;
1313
import javax.persistence.Id;
14+
import javax.persistence.Index;
1415
import javax.persistence.Table;
1516
import lombok.AccessLevel;
1617
import lombok.Getter;
1718
import lombok.NoArgsConstructor;
1819

1920
@Entity
2021
@Getter
21-
@Table(name = "member")
22+
@Table(name = "member", indexes = {
23+
@Index(name = "member_oauth_index", columnList = "platform, platform_id")
24+
})
2225
@NoArgsConstructor(access = AccessLevel.PROTECTED)
2326
public class Member extends BaseEntity {
2427

backend/src/main/java/com/woowacourse/naepyeon/domain/Message.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import javax.persistence.GeneratedValue;
1111
import javax.persistence.GenerationType;
1212
import javax.persistence.Id;
13+
import javax.persistence.Index;
1314
import javax.persistence.JoinColumn;
1415
import javax.persistence.ManyToOne;
1516
import javax.persistence.Table;
@@ -19,7 +20,9 @@
1920

2021
@Entity
2122
@Getter
22-
@Table(name = "message")
23+
@Table(name = "message", indexes = {
24+
@Index(name = "message_rollingpaper_index", columnList = "rollingpaper_id")
25+
})
2326
@NoArgsConstructor(access = AccessLevel.PROTECTED)
2427
public class Message extends BaseEntity {
2528

backend/src/main/java/com/woowacourse/naepyeon/domain/Team.java

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import javax.persistence.GeneratedValue;
77
import javax.persistence.GenerationType;
88
import javax.persistence.Id;
9+
import javax.persistence.Index;
910
import javax.persistence.Table;
1011
import lombok.AccessLevel;
1112
import lombok.Getter;

backend/src/main/java/com/woowacourse/naepyeon/domain/TeamParticipation.java

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import javax.persistence.GeneratedValue;
88
import javax.persistence.GenerationType;
99
import javax.persistence.Id;
10+
import javax.persistence.Index;
1011
import javax.persistence.JoinColumn;
1112
import javax.persistence.ManyToOne;
1213
import javax.persistence.Table;
@@ -18,6 +19,10 @@
1819
@Entity
1920
@Table(
2021
name = "team_participation",
22+
indexes = {
23+
@Index(name = "team_participation_team_index", columnList = "team_id"),
24+
@Index(name = "team_participation_member_index", columnList = "member_id")
25+
},
2126
uniqueConstraints = {
2227
@UniqueConstraint(
2328
name = "participate_duplicate",

backend/src/main/java/com/woowacourse/naepyeon/domain/rollingpaper/Rollingpaper.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import javax.persistence.GeneratedValue;
1313
import javax.persistence.GenerationType;
1414
import javax.persistence.Id;
15+
import javax.persistence.Index;
1516
import javax.persistence.JoinColumn;
1617
import javax.persistence.ManyToOne;
1718
import javax.persistence.Table;
@@ -21,7 +22,9 @@
2122

2223
@Entity
2324
@Getter
24-
@Table(name = "rollingpaper")
25+
@Table(name = "rollingpaper", indexes = {
26+
@Index(name = "rollingpaper_team_index", columnList = "team_id")
27+
})
2528
@NoArgsConstructor(access = AccessLevel.PROTECTED)
2629
public class Rollingpaper extends BaseEntity {
2730

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,29 @@
11
package com.woowacourse.naepyeon.repository.message;
22

33
import com.woowacourse.naepyeon.domain.Message;
4+
import com.woowacourse.naepyeon.service.dto.WrittenMessageResponseDto;
5+
import org.springframework.data.domain.Page;
6+
import org.springframework.data.domain.Pageable;
47
import org.springframework.data.jpa.repository.JpaRepository;
8+
import org.springframework.data.jpa.repository.Query;
9+
import org.springframework.data.repository.query.Param;
510

611
public interface MessageRepository extends JpaRepository<Message, Long>, MessageRepositoryCustom {
712

13+
@Query(value = "select distinct new com.woowacourse.naepyeon.service.dto.WrittenMessageResponseDto"
14+
+ "(m.id, r.id, r.title, t.id, t.name, m.content, m.color, "
15+
+ "case when r.recipient = com.woowacourse.naepyeon.domain.rollingpaper.Recipient.MEMBER then p.nickname "
16+
+ "when r.recipient = com.woowacourse.naepyeon.domain.rollingpaper.Recipient.TEAM then t.name "
17+
+ "else '' end) "
18+
+ "from Message m"
19+
+ ", Rollingpaper r"
20+
+ ", Team t"
21+
+ ", TeamParticipation p "
22+
+ "where m.rollingpaper.id = r.id "
23+
+ "and r.team.id = t.id "
24+
+ "and p.team.id = t.id "
25+
+ "and m.author.id = :authorId "
26+
+ "and (p.member.id = r.member.id or r.member.id is null)")
27+
Page<WrittenMessageResponseDto> findAllByAuthorId(@Param("authorId") final Long authorId,
28+
final Pageable pageRequest);
829
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
package com.woowacourse.naepyeon.repository.message;
22

33
import com.woowacourse.naepyeon.domain.Message;
4-
import com.woowacourse.naepyeon.service.dto.WrittenMessageResponseDto;
54
import java.util.List;
6-
import org.springframework.data.domain.Page;
7-
import org.springframework.data.domain.Pageable;
85

96
public interface MessageRepositoryCustom {
107

118
List<Message> findAllByRollingpaperId(final Long rollingpaperId);
12-
13-
Page<WrittenMessageResponseDto> findAllByAuthorId(final Long authorId, final Pageable pageRequest);
149
}

backend/src/main/java/com/woowacourse/naepyeon/repository/message/MessageRepositoryImpl.java

-60
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,14 @@
11
package com.woowacourse.naepyeon.repository.message;
22

33
import static com.woowacourse.naepyeon.domain.QMessage.message;
4-
import static com.woowacourse.naepyeon.domain.QTeamParticipation.teamParticipation;
54

65
import com.querydsl.core.BooleanBuilder;
7-
import com.querydsl.core.types.ConstructorExpression;
8-
import com.querydsl.core.types.Projections;
96
import com.querydsl.core.types.dsl.BooleanExpression;
10-
import com.querydsl.core.types.dsl.CaseBuilder;
11-
import com.querydsl.jpa.impl.JPAQuery;
127
import com.querydsl.jpa.impl.JPAQueryFactory;
138
import com.woowacourse.naepyeon.domain.Message;
14-
import com.woowacourse.naepyeon.domain.rollingpaper.Recipient;
15-
import com.woowacourse.naepyeon.service.dto.WrittenMessageResponseDto;
169
import java.util.List;
1710
import java.util.function.Supplier;
1811
import lombok.RequiredArgsConstructor;
19-
import org.springframework.data.domain.Page;
20-
import org.springframework.data.domain.PageImpl;
21-
import org.springframework.data.domain.Pageable;
2212

2313
@RequiredArgsConstructor
2414
public class MessageRepositoryImpl implements MessageRepositoryCustom {
@@ -33,60 +23,10 @@ public List<Message> findAllByRollingpaperId(final Long rollingpaperId) {
3323
.fetch();
3424
}
3525

36-
@Override
37-
public Page<WrittenMessageResponseDto> findAllByAuthorId(final Long authorId, final Pageable pageRequest) {
38-
final JPAQuery<WrittenMessageResponseDto> query = getQueryWhenFindAllByAuthorId(authorId);
39-
40-
final List<WrittenMessageResponseDto> content = query
41-
.offset(pageRequest.getOffset())
42-
.limit(pageRequest.getPageSize())
43-
.fetch();
44-
final long total = query
45-
.stream()
46-
.count();
47-
48-
return new PageImpl<>(content, pageRequest, total);
49-
}
50-
51-
private JPAQuery<WrittenMessageResponseDto> getQueryWhenFindAllByAuthorId(final Long authorId) {
52-
return queryFactory
53-
.select(makeProjections())
54-
.from(message)
55-
.join(teamParticipation).on(message.rollingpaper.team.id.eq(teamParticipation.team.id))
56-
.where(isAuthorIdEq(authorId)
57-
.and(message.rollingpaper.member.id.isNull()
58-
.or(message.rollingpaper.member.id.eq(teamParticipation.member.id))
59-
)
60-
)
61-
.distinct();
62-
}
63-
64-
private ConstructorExpression<WrittenMessageResponseDto> makeProjections() {
65-
return Projections.constructor(WrittenMessageResponseDto.class,
66-
message.id,
67-
message.rollingpaper.id,
68-
message.rollingpaper.title,
69-
message.rollingpaper.team.id,
70-
message.rollingpaper.team.name,
71-
message.content,
72-
message.color,
73-
new CaseBuilder()
74-
.when(message.rollingpaper.recipient.eq(Recipient.MEMBER))
75-
.then(teamParticipation.nickname)
76-
.when(message.rollingpaper.recipient.eq(Recipient.TEAM))
77-
.then(message.rollingpaper.team.name)
78-
.otherwise("")
79-
);
80-
}
81-
8226
private BooleanBuilder isRollingpaperIdEq(final Long rollingpaperId) {
8327
return nullSafeBuilder(() -> message.rollingpaper.id.eq(rollingpaperId));
8428
}
8529

86-
private BooleanBuilder isAuthorIdEq(final Long authorId) {
87-
return nullSafeBuilder(() -> message.author.id.eq(authorId));
88-
}
89-
9030
private BooleanBuilder nullSafeBuilder(Supplier<BooleanExpression> f) {
9131
try {
9232
return new BooleanBuilder(f.get());

backend/src/main/resources/application.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ google:
4040
client-secret: ${GOOGLE_CLIENT_SECRET}
4141

4242
logging:
43-
config: classpath:log4j2.yml
43+
config: classpath:log4j2.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CREATE INDEX member_oauth_index ON member (platform, platform_id);
2+
3+
CREATE INDEX message_rollingpaper_index ON message (rollingpaper_id);
4+
5+
CREATE INDEX rollingpaper_team_index ON rollingpaper (team_id);
6+
7+
CREATE INDEX team_participation_team_index ON team_participation (team_id);
8+
9+
CREATE INDEX team_participation_member_index ON team_participation (member_id);

backend/src/main/resources/log4j2.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ Configutation:
2525
additivity: false
2626
level: info
2727
AppenderRef:
28-
- ref: Console_Appender
28+
- ref: Console_Appender

backend/src/test/java/com/woowacourse/naepyeon/repository/MessageRepositoryTest.java

+38-7
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,21 @@ class MessageRepositoryTest {
6161
"#123456",
6262
false
6363
);
64+
private final Team team2 = new Team(
65+
"nae-pyeon2",
66+
"테스트 모임입니다.",
67+
"testEmoji",
68+
"#123456",
69+
false
70+
);
6471
private final Member member = new Member("member", "[email protected]", Platform.KAKAO, "1");
6572
private final Member author = new Member("author", "[email protected]", Platform.KAKAO, "2");
6673
private final Rollingpaper rollingpaper = new Rollingpaper("AlexAndKei", Recipient.MEMBER, team, member);
6774

6875
@BeforeEach
6976
void setUp() {
7077
teamRepository.save(team);
78+
teamRepository.save(team2);
7179
memberRepository.save(member);
7280
memberRepository.save(author);
7381
rollingpaperRepository.save(rollingpaper);
@@ -114,6 +122,10 @@ void findAllByMemberIdAndPageRequest() {
114122
teamParticipationRepository.save(teamParticipation1);
115123
final TeamParticipation teamParticipation2 = new TeamParticipation(team, author, "작성자");
116124
teamParticipationRepository.save(teamParticipation2);
125+
final TeamParticipation teamParticipation3 = new TeamParticipation(team2, member, "멤버");
126+
teamParticipationRepository.save(teamParticipation3);
127+
final TeamParticipation teamParticipation4 = new TeamParticipation(team2, author, "작성자");
128+
teamParticipationRepository.save(teamParticipation4);
117129

118130
final Message message1 = createMessage();
119131
messageRepository.save(message1);
@@ -125,18 +137,37 @@ void findAllByMemberIdAndPageRequest() {
125137
messageRepository.save(message4);
126138
final Message message5 = createMessage();
127139
messageRepository.save(message5);
140+
final Message message6 = createMessage();
141+
messageRepository.save(message6);
142+
final Message message7 = createMessage();
143+
messageRepository.save(message7);
144+
final Message message8 = createMessage();
145+
messageRepository.save(message8);
146+
final Message message9 = createMessage();
147+
messageRepository.save(message9);
148+
final Message message10 = createMessage();
149+
messageRepository.save(message10);
150+
final Message message11 = createMessage();
151+
messageRepository.save(message11);
152+
final Message message12 = createMessage();
153+
messageRepository.save(message12);
128154
final List<WrittenMessageResponseDto> expected = List.of(
129-
WrittenMessageResponseDto.of(rollingpaper, team, "멤버", message3),
130-
WrittenMessageResponseDto.of(rollingpaper, team, "멤버", message4)
155+
WrittenMessageResponseDto.of(rollingpaper, team, "멤버", message6),
156+
WrittenMessageResponseDto.of(rollingpaper, team, "멤버", message7),
157+
WrittenMessageResponseDto.of(rollingpaper, team, "멤버", message8),
158+
WrittenMessageResponseDto.of(rollingpaper, team, "멤버", message9),
159+
WrittenMessageResponseDto.of(rollingpaper, team, "멤버", message10)
131160
);
132161

133162
final Page<WrittenMessageResponseDto> writtenMessageResponseDtos =
134-
messageRepository.findAllByAuthorId(author.getId(), PageRequest.of(1, 2));
163+
messageRepository.findAllByAuthorId(author.getId(), PageRequest.of(1, 5));
135164
final List<WrittenMessageResponseDto> actual = writtenMessageResponseDtos.getContent();
136-
137-
assertThat(actual)
138-
.usingRecursiveComparison()
139-
.isEqualTo(expected);
165+
assertAll(
166+
() -> assertThat(writtenMessageResponseDtos.getTotalElements()).isEqualTo(12),
167+
() -> assertThat(actual)
168+
.usingRecursiveComparison()
169+
.isEqualTo(expected)
170+
);
140171
}
141172

142173
@Test

frontend/src/App.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const App = () => {
3939

4040
return (
4141
<PageContainer>
42-
<ErrorBoundary fallback={<div>👻👻👻👻</div>}>
42+
<ErrorBoundary fallback={<ErrorPage />}>
4343
<UserProvider
4444
initialData={
4545
data && {

frontend/src/api/googleOauth.ts

+9-13
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
import { appClient, requestApi } from "@/api";
2-
3-
import { ApiOptions } from "@/types/api";
42
import { postGoogleOauthRequest } from "@/types/apiRequest";
53

6-
const postGoogleOauth = async (
7-
{ authorizationCode, redirectUri }: postGoogleOauthRequest,
8-
options?: ApiOptions
9-
) =>
10-
requestApi(
11-
() =>
12-
appClient.post("/oauth/google", {
13-
authorizationCode,
14-
redirectUri,
15-
}),
16-
options
4+
const postGoogleOauth = async ({
5+
authorizationCode,
6+
redirectUri,
7+
}: postGoogleOauthRequest) =>
8+
requestApi(() =>
9+
appClient.post("/oauth/google", {
10+
authorizationCode,
11+
redirectUri,
12+
})
1713
);
1814

1915
export { postGoogleOauth };

frontend/src/api/index.ts

+4-22
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,10 @@ const setAppClientHeaderAuthorization = (accessToken: string) => {
1616
appClient.defaults.headers.common["Authorization"] = `Bearer ${accessToken}`;
1717
};
1818

19-
const requestApi = async (
20-
request: () => Promise<any>,
21-
options?: ApiOptions
22-
) => {
23-
try {
24-
const { data } = await request();
25-
26-
return data;
27-
} catch (error) {
28-
const axiosError = error as AxiosError;
29-
30-
if (axiosError.response) {
31-
const { errorCode, message } = axiosError.response
32-
.data as ApiErrorResponse;
33-
34-
throw new ApiError({
35-
errorCode,
36-
message,
37-
errorHandler: options?.onError,
38-
});
39-
}
40-
}
19+
const requestApi = async (request: () => Promise<any>) => {
20+
const { data } = await request();
21+
22+
return data;
4123
};
4224

4325
export { appClient, queryClient, setAppClientHeaderAuthorization, requestApi };

0 commit comments

Comments
 (0)