Skip to content

Commit 4a2cbaf

Browse files
authored
[Release] 리뷰미 v2.0.5 배포
- 하이라이트 관련 버그 수정 - 하이라이트 리팩토링
2 parents b82137a + 90646b6 commit 4a2cbaf

File tree

107 files changed

+616
-581
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+616
-581
lines changed

.github/CODEOWNERS

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
* @chysis @BadaHertz52 @soosoo22 @ImxYJL @donghoony @Kimprodp @nayonsoso @skylar1220
2+
/frontend/ @chysis @BadaHertz52 @soosoo22 @ImxYJL
3+
/backend/ @donghoony @Kimprodp @nayonsoso @skylar1220

.github/workflows/discord-pull-request-comment.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
elif [ "$PR_PREFIX" = '[FE]' ]; then
3232
echo Frontend PR Found!
3333
echo "PR_PREFIX=FE" >> $GITHUB_ENV
34-
elif [ "$PR_PREFIX" = '[All]' ]; then
34+
elif [ "$PR_PREFIX" = '[All]' ] || [ "$PR_PREFIX" = '[Release]' ]; then
3535
echo All PR Found!
3636
echo "PR_PREFIX=All" >> $GITHUB_ENV
3737
fi

.github/workflows/discord-pull-request.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
elif [ "$PR_PREFIX" = '[FE]' ]; then
3232
echo Frontend PR Found!
3333
echo "PR_PREFIX=FE" >> $GITHUB_ENV
34-
elif [ "$PR_PREFIX" = '[All]' ]; then
34+
elif [ "$PR_PREFIX" = '[All]' ] || [ "$PR_PREFIX" = '[Release]' ]; then
3535
echo All PR Found!
3636
echo "PR_PREFIX=All" >> $GITHUB_ENV
3737
fi

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
### 백엔드
4949
<p align="center"><img src="https://github.com/user-attachments/assets/0a7aa302-b737-496d-9fec-54a8088da3b5" width="600px"/></p>
5050

51+
### Infrastructure
52+
<p align=center><img src=https://github.com/user-attachments/assets/ea1c3226-f452-4910-9a90-11a9d3e1e1df width=800px/></p>
53+
5154
## 🧑‍💻 팀원 소개
5255

5356
### 프론트엔드
@@ -59,3 +62,4 @@
5962
| <img src="https://review-me-blog.github.io/assets/images/sancho-a505ff332869b4eda5a1fa6cf296ddc8.jpeg" width="120px" max-height="120px"> | <img src="https://review-me-blog.github.io/assets/images/aru-f1f92d2d3284aab8aa385afd817d2ae7.jpeg" width="120px" max-height="120px"> | <img src="https://review-me-blog.github.io/assets/images/kirby-c5c179939bc7a2fd587bcc2cbb6af129.png" width="120px" max-height="120px"> | <img src="https://review-me-blog.github.io/assets/images/ted-a4f788b021e7619d4cc9ae7fc0ab336d.png" width="120px" max-height="120px"> |
6063
| :---: | :---: | :---: | :---: |
6164
| [🦧 산초](https://github.com/nayonsoso) | [🤸🏻‍♂️ 아루](https://github.com/donghoony) | [💃 커비](https://github.com/skylar1220) | [🐻 테드](https://github.com/Kimprodp) |
65+

backend/src/main/java/reviewme/DatabaseInitializer.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import lombok.RequiredArgsConstructor;
66
import org.springframework.stereotype.Component;
77
import org.springframework.transaction.annotation.Transactional;
8-
import reviewme.question.domain.OptionGroup;
9-
import reviewme.question.domain.OptionItem;
10-
import reviewme.question.domain.OptionType;
11-
import reviewme.question.domain.Question;
12-
import reviewme.question.domain.QuestionType;
13-
import reviewme.question.repository.OptionGroupRepository;
14-
import reviewme.question.repository.OptionItemRepository;
15-
import reviewme.question.repository.QuestionRepository;
8+
import reviewme.template.domain.OptionGroup;
9+
import reviewme.template.domain.OptionItem;
10+
import reviewme.template.domain.OptionType;
11+
import reviewme.template.domain.Question;
12+
import reviewme.template.domain.QuestionType;
13+
import reviewme.template.repository.OptionGroupRepository;
14+
import reviewme.template.repository.OptionItemRepository;
15+
import reviewme.template.repository.QuestionRepository;
1616
import reviewme.template.domain.Section;
1717
import reviewme.template.domain.Template;
1818
import reviewme.template.domain.VisibleType;

backend/src/main/java/reviewme/config/WebConfig.java

-10
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
import java.util.List;
44
import lombok.RequiredArgsConstructor;
55
import org.springframework.context.annotation.Configuration;
6-
import org.springframework.data.redis.core.RedisTemplate;
76
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
8-
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
97
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
10-
import reviewme.global.RequestLimitInterceptor;
118
import reviewme.reviewgroup.controller.ReviewGroupSessionResolver;
129
import reviewme.reviewgroup.service.ReviewGroupService;
1310

@@ -16,16 +13,9 @@
1613
public class WebConfig implements WebMvcConfigurer {
1714

1815
private final ReviewGroupService reviewGroupService;
19-
private final RedisTemplate<String, Long> redisTemplate;
20-
private final RequestLimitProperties requestLimitProperties;
2116

2217
@Override
2318
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
2419
resolvers.add(new ReviewGroupSessionResolver(reviewGroupService));
2520
}
26-
27-
@Override
28-
public void addInterceptors(InterceptorRegistry registry) {
29-
registry.addInterceptor(new RequestLimitInterceptor(redisTemplate, requestLimitProperties));
30-
}
3121
}

backend/src/main/java/reviewme/config/CorsConfig.java backend/src/main/java/reviewme/config/cors/CorsConfig.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
package reviewme.config;
1+
package reviewme.config.cors;
22

33
import lombok.RequiredArgsConstructor;
4-
import org.slf4j.Logger;
5-
import org.slf4j.LoggerFactory;
4+
import lombok.extern.slf4j.Slf4j;
65
import org.springframework.boot.context.properties.EnableConfigurationProperties;
76
import org.springframework.context.annotation.Configuration;
87
import org.springframework.context.annotation.Profile;
98
import org.springframework.web.servlet.config.annotation.CorsRegistry;
109
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
1110

11+
@Slf4j
1212
public class CorsConfig {
1313

14-
private static final Logger log = LoggerFactory.getLogger(CorsConfig.class);
15-
1614
private CorsConfig() {
1715
}
1816

backend/src/main/java/reviewme/config/CorsProperties.java backend/src/main/java/reviewme/config/cors/CorsProperties.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reviewme.config;
1+
package reviewme.config.cors;
22

33
import java.util.List;
44
import org.springframework.boot.context.properties.ConfigurationProperties;

backend/src/main/java/reviewme/config/DataSourceType.java backend/src/main/java/reviewme/config/datasource/DataSourceType.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reviewme.config;
1+
package reviewme.config.datasource;
22

33
public enum DataSourceType {
44
READ,

backend/src/main/java/reviewme/config/ReplicationDatasourceConfig.java backend/src/main/java/reviewme/config/datasource/ReplicationDatasourceConfig.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reviewme.config;
1+
package reviewme.config.datasource;
22

33
import java.util.HashMap;
44
import java.util.Map;
@@ -54,4 +54,3 @@ public DataSource dataSource(@Qualifier(ROUTING_DATA_SOURCE_NAME) DataSource rou
5454
return new LazyConnectionDataSourceProxy(routingDataSource);
5555
}
5656
}
57-

backend/src/main/java/reviewme/config/ReplicationRoutingDataSource.java backend/src/main/java/reviewme/config/datasource/ReplicationRoutingDataSource.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reviewme.config;
1+
package reviewme.config.datasource;
22

33
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
44
import org.springframework.transaction.support.TransactionSynchronizationManager;

backend/src/main/java/reviewme/global/RequestLimitInterceptor.java backend/src/main/java/reviewme/config/requestlimit/RequestLimitInterceptor.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reviewme.global;
1+
package reviewme.config.requestlimit;
22

33
import static org.springframework.http.HttpHeaders.USER_AGENT;
44

@@ -11,8 +11,6 @@
1111
import org.springframework.http.HttpMethod;
1212
import org.springframework.stereotype.Component;
1313
import org.springframework.web.servlet.HandlerInterceptor;
14-
import reviewme.config.RequestLimitProperties;
15-
import reviewme.global.exception.TooManyRequestException;
1614

1715
@Component
1816
@EnableConfigurationProperties(RequestLimitProperties.class)
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
package reviewme.config;
1+
package reviewme.config.requestlimit;
22

33
import java.time.Duration;
44
import org.springframework.boot.context.properties.ConfigurationProperties;
55

66
@ConfigurationProperties(prefix = "request-limit")
7-
public record RequestLimitProperties(
8-
long threshold,
9-
Duration duration,
10-
String host,
11-
int port
12-
) {
7+
public record RequestLimitProperties(long threshold, Duration duration, String host, int port) {
138
}

backend/src/main/java/reviewme/config/RequestLimitRedisConfig.java backend/src/main/java/reviewme/config/requestlimit/RequestLimitRedisConfig.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reviewme.config;
1+
package reviewme.config.requestlimit;
22

33
import lombok.RequiredArgsConstructor;
44
import org.springframework.boot.context.properties.EnableConfigurationProperties;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package reviewme.config.requestlimit;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.data.redis.core.RedisTemplate;
6+
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
7+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8+
9+
@Configuration
10+
@RequiredArgsConstructor
11+
public class RequestLimitWebConfig implements WebMvcConfigurer {
12+
13+
private final RedisTemplate<String, Long> redisTemplate;
14+
private final RequestLimitProperties requestLimitProperties;
15+
16+
@Override
17+
public void addInterceptors(InterceptorRegistry registry) {
18+
registry.addInterceptor(new RequestLimitInterceptor(redisTemplate, requestLimitProperties));
19+
}
20+
}

backend/src/main/java/reviewme/global/exception/TooManyRequestException.java backend/src/main/java/reviewme/config/requestlimit/TooManyRequestException.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package reviewme.global.exception;
1+
package reviewme.config.requestlimit;
22

33
import lombok.extern.slf4j.Slf4j;
4+
import reviewme.global.exception.ReviewMeException;
45

56
@Slf4j
67
public class TooManyRequestException extends ReviewMeException {

backend/src/main/java/reviewme/global/GlobalExceptionHandler.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.springframework.web.servlet.resource.NoResourceFoundException;
2323
import reviewme.global.exception.BadRequestException;
2424
import reviewme.global.exception.DataInconsistencyException;
25-
import reviewme.global.exception.TooManyRequestException;
25+
import reviewme.config.requestlimit.TooManyRequestException;
2626
import reviewme.global.exception.FieldErrorResponse;
2727
import reviewme.global.exception.NotFoundException;
2828
import reviewme.global.exception.UnauthorizedException;
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
package reviewme.global.exception;
22

3-
public record FieldErrorResponse(
4-
String field,
5-
Object value,
6-
String message
7-
) {
3+
public record FieldErrorResponse(String field, Object value, String message) {
84
}

backend/src/main/java/reviewme/highlight/domain/HighlightedLines.java

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.util.Arrays;
44
import java.util.List;
5+
import java.util.function.Function;
6+
import java.util.stream.IntStream;
57
import lombok.Getter;
68
import reviewme.highlight.domain.exception.InvalidHighlightLineIndexException;
79
import reviewme.highlight.domain.exception.NegativeHighlightLineIndexException;
@@ -37,4 +39,12 @@ private void validateLineIndexRange(int lineIndex) {
3739
throw new InvalidHighlightLineIndexException(lineIndex, lines.size());
3840
}
3941
}
42+
43+
public List<Highlight> toHighlights(long answerId) {
44+
return IntStream.range(0, lines.size())
45+
.mapToObj(lineIndex -> lines.get(lineIndex).getRanges().stream()
46+
.map(range -> new Highlight(answerId, lineIndex, range)))
47+
.flatMap(Function.identity())
48+
.toList();
49+
}
4050
}

backend/src/main/java/reviewme/highlight/domain/exception/HighlightStartIndexExceedEndIndexException.java

-13
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package reviewme.highlight.repository;
2+
3+
import java.util.Collection;
4+
import reviewme.highlight.domain.Highlight;
5+
6+
public interface HighlightJdbcRepository {
7+
8+
void saveAll(Collection<Highlight> highlights);
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package reviewme.highlight.repository;
2+
3+
import java.util.Collection;
4+
import lombok.RequiredArgsConstructor;
5+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
6+
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
7+
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
8+
import reviewme.highlight.domain.Highlight;
9+
10+
@RequiredArgsConstructor
11+
public class HighlightJdbcRepositoryImpl implements HighlightJdbcRepository {
12+
13+
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
14+
15+
@Override
16+
public void saveAll(Collection<Highlight> highlights) {
17+
SqlParameterSource[] parameterSources = SqlParameterSourceUtils.createBatch(highlights.toArray());
18+
String insertSql = """
19+
INSERT INTO highlight (answer_id, line_index, start_index, end_index)
20+
VALUES (:answerId, :lineIndex, :highlightRange.startIndex, :highlightRange.endIndex)
21+
""";
22+
namedParameterJdbcTemplate.batchUpdate(insertSql, parameterSources);
23+
}
24+
}

backend/src/main/java/reviewme/highlight/repository/HighlightRepository.java

+17-10
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,32 @@
22

33
import java.util.Collection;
44
import java.util.List;
5-
import org.springframework.data.jpa.repository.JpaRepository;
65
import org.springframework.data.jpa.repository.Modifying;
76
import org.springframework.data.jpa.repository.Query;
7+
import org.springframework.data.repository.Repository;
88
import reviewme.highlight.domain.Highlight;
99

10-
public interface HighlightRepository extends JpaRepository<Highlight, Long> {
10+
public interface HighlightRepository extends Repository<Highlight, Long>, HighlightJdbcRepository {
1111

12-
@Modifying
13-
@Query("""
14-
DELETE FROM Highlight h
15-
WHERE h.answerId IN :answerIds
16-
""")
17-
void deleteAllByAnswerIds(Collection<Long> answerIds);
12+
Highlight save(Highlight highlight);
13+
14+
boolean existsById(long id);
1815

1916
@Query("""
20-
SELECT h
21-
FROM Highlight h
17+
SELECT h FROM Highlight h
2218
WHERE h.answerId IN :answerIds
2319
ORDER BY h.lineIndex, h.highlightRange.startIndex ASC
2420
""")
2521
List<Highlight> findAllByAnswerIdsOrderedAsc(Collection<Long> answerIds);
22+
23+
@Modifying
24+
@Query("""
25+
DELETE FROM Highlight h
26+
WHERE h.answerId IN (
27+
SELECT a.id FROM Answer a
28+
JOIN Review r ON a.reviewId = r.id
29+
WHERE r.reviewGroupId = :reviewGroupId AND a.questionId = :questionId
30+
)
31+
""")
32+
void deleteByReviewGroupIdAndQuestionId(long reviewGroupId, long questionId);
2633
}
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,33 @@
11
package reviewme.highlight.service;
22

33
import java.util.List;
4-
import java.util.Set;
54
import lombok.RequiredArgsConstructor;
65
import org.springframework.stereotype.Service;
76
import org.springframework.transaction.annotation.Transactional;
87
import reviewme.highlight.domain.Highlight;
98
import reviewme.highlight.repository.HighlightRepository;
109
import reviewme.highlight.service.dto.HighlightsRequest;
1110
import reviewme.highlight.service.mapper.HighlightMapper;
12-
import reviewme.highlight.service.validator.HighlightValidator;
13-
import reviewme.review.repository.AnswerRepository;
11+
import reviewme.review.service.validator.AnswerValidator;
1412
import reviewme.reviewgroup.domain.ReviewGroup;
1513

1614
@Service
1715
@RequiredArgsConstructor
1816
public class HighlightService {
1917

2018
private final HighlightRepository highlightRepository;
21-
private final AnswerRepository answerRepository;
2219

23-
private final HighlightValidator highlightValidator;
2420
private final HighlightMapper highlightMapper;
21+
private final AnswerValidator answerValidator;
2522

2623
@Transactional
2724
public void editHighlight(HighlightsRequest highlightsRequest, ReviewGroup reviewGroup) {
28-
highlightValidator.validate(highlightsRequest, reviewGroup);
29-
List<Highlight> highlights = highlightMapper.mapToHighlights(highlightsRequest);
30-
31-
Set<Long> answerIds = answerRepository.findIdsByQuestionId(highlightsRequest.questionId());
32-
highlightRepository.deleteAllByAnswerIds(answerIds);
25+
List<Long> requestedAnswerIds = highlightsRequest.getUniqueAnswerIds();
26+
answerValidator.validateQuestionContainsAnswers(highlightsRequest.questionId(), requestedAnswerIds);
27+
answerValidator.validateReviewGroupContainsAnswers(reviewGroup, requestedAnswerIds);
3328

29+
List<Highlight> highlights = highlightMapper.mapToHighlights(highlightsRequest);
30+
highlightRepository.deleteByReviewGroupIdAndQuestionId(reviewGroup.getId(), highlightsRequest.questionId());
3431
highlightRepository.saveAll(highlights);
3532
}
3633
}

0 commit comments

Comments
 (0)