From 49d034a7de53bad5472abfb97f8e00089d2a3379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 05:43:37 +0900 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20ArticleKeywordUserMapRepository?= =?UTF-8?q?=20findAll=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ArticleKeywordUserMapRepository.java | 7 +++++++ .../koin/domain/community/util/KeywordExtractor.java | 2 ++ 2 files changed, 9 insertions(+) diff --git a/src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordUserMapRepository.java b/src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordUserMapRepository.java index c1c00bc81..532812796 100644 --- a/src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordUserMapRepository.java +++ b/src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordUserMapRepository.java @@ -47,4 +47,11 @@ Optional findByArticleKeywordIdAndUserIdIncludingDeleted( ); List findAllByArticleKeywordIdIn(List articleKeywordIds); + + @Query(""" + SELECT akum FROM ArticleKeywordUserMap akum + JOIN FETCH akum.articleKeyword + JOIN FETCH akum.user + """) + List findAll(); } diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index 2fce59b97..5cc3e110d 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -30,6 +30,8 @@ public class KeywordExtractor { private final ArticleKeywordUserMapRepository articleKeywordUserMapRepository; public List matchKeyword(List
articles, Integer authorId) { + List articleKeywordUserMaps = articleKeywordUserMapRepository.findAll(); + Map> matchedKeywordByUserIdByArticleId = new LinkedHashMap<>(); int offset = 0; From f178c7253f0aa3eedece690e4b7c69638584be97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 06:04:02 +0900 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20ArticleKeywordUserMap=20=EC=97=B0?= =?UTF-8?q?=EA=B4=80=EA=B4=80=EA=B3=84=20=EA=B2=8C=ED=84=B0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/keyword/model/ArticleKeywordUserMap.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/in/koreatech/koin/domain/community/keyword/model/ArticleKeywordUserMap.java b/src/main/java/in/koreatech/koin/domain/community/keyword/model/ArticleKeywordUserMap.java index 835021e25..3c409e6cb 100644 --- a/src/main/java/in/koreatech/koin/domain/community/keyword/model/ArticleKeywordUserMap.java +++ b/src/main/java/in/koreatech/koin/domain/community/keyword/model/ArticleKeywordUserMap.java @@ -56,4 +56,12 @@ public void delete() { public void restore() { this.isDeleted = false; } + + public String getKeyword() { + return articleKeyword.getKeyword(); + } + + public Integer getUserId() { + return user.getId(); + } } From a0ce02697acfbc99864884fe5e810e241e326a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 14:48:08 +0900 Subject: [PATCH 03/15] =?UTF-8?q?chore:=20matchKeyword=20=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4=20=EB=A1=9C=EC=A7=81=20=EC=A3=BC=EC=84=9D=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/community/util/KeywordExtractor.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index 5cc3e110d..e9e5cd245 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -1,20 +1,13 @@ package in.koreatech.koin.domain.community.util; -import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import in.koreatech.koin.common.event.ArticleKeywordEvent; import in.koreatech.koin.domain.community.article.model.Article; -import in.koreatech.koin.domain.community.keyword.model.ArticleKeyword; import in.koreatech.koin.domain.community.keyword.model.ArticleKeywordUserMap; -import in.koreatech.koin.common.event.ArticleKeywordEvent; import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordRepository; import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordUserMapRepository; import lombok.RequiredArgsConstructor; @@ -32,6 +25,8 @@ public class KeywordExtractor { public List matchKeyword(List
articles, Integer authorId) { List articleKeywordUserMaps = articleKeywordUserMapRepository.findAll(); + + /* Map> matchedKeywordByUserIdByArticleId = new LinkedHashMap<>(); int offset = 0; @@ -85,8 +80,9 @@ public List matchKeyword(List
articles, Integer au keywordEvents.add(new ArticleKeywordEvent(article.getId(), authorId, matchedKeywordByUserId)); } } + */ - return keywordEvents; + return null; } private String pickHigherPriorityKeyword(String previousKeyword, String candidateKeyword) { From 6f02c313d971d1601b88b87f6420c036a71955a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:39:24 +0900 Subject: [PATCH 04/15] =?UTF-8?q?feat:=20KeywordMatchResult=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../keyword/model/KeywordMatchResult.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/domain/community/keyword/model/KeywordMatchResult.java diff --git a/src/main/java/in/koreatech/koin/domain/community/keyword/model/KeywordMatchResult.java b/src/main/java/in/koreatech/koin/domain/community/keyword/model/KeywordMatchResult.java new file mode 100644 index 000000000..90bbe1961 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/community/keyword/model/KeywordMatchResult.java @@ -0,0 +1,38 @@ +package in.koreatech.koin.domain.community.keyword.model; + +import java.util.Objects; + +public class KeywordMatchResult { + + private final Integer articleId; + private final Integer userId; + private String keyword; + + private KeywordMatchResult(Integer articleId, Integer userId, String keyword) { + this.articleId = articleId; + this.userId = userId; + this.keyword = keyword; + } + + public static KeywordMatchResult of(Integer articleId, Integer userId, String keyword) { + return new KeywordMatchResult(articleId, userId, keyword); + } + + public void updateKeywordIfLonger(String candidate) { + if (candidate.trim().length() > this.keyword.trim().length()) { + this.keyword = candidate; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof KeywordMatchResult that)) return false; + return Objects.equals(articleId, that.articleId) && Objects.equals(userId, that.userId); + } + + @Override + public int hashCode() { + return Objects.hash(articleId, userId); + } +} From ebd59f552c70af320c2604f51c5f1c1d0c11d088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:42:56 +0900 Subject: [PATCH 05/15] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=ED=82=A4=EC=9B=8C=EB=93=9C=20=EB=A7=A4=EC=B9=AD=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/util/KeywordExtractor.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index e9e5cd245..27199547b 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -1,6 +1,8 @@ package in.koreatech.koin.domain.community.util; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,6 +10,7 @@ import in.koreatech.koin.common.event.ArticleKeywordEvent; import in.koreatech.koin.domain.community.article.model.Article; import in.koreatech.koin.domain.community.keyword.model.ArticleKeywordUserMap; +import in.koreatech.koin.domain.community.keyword.model.KeywordMatchResult; import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordRepository; import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordUserMapRepository; import lombok.RequiredArgsConstructor; @@ -17,6 +20,12 @@ @Transactional(readOnly = true) public class KeywordExtractor { + /** + * - 하나의 게시글에서 여러 키워드가 매칭 될 경우 + * - 하나의 게시글에서 동일한 키워드가 매칭 될 경우 + * - 여러개의 게시글에서 동일한 키워드가 매칭 될 경우 + */ + private static final int KEYWORD_BATCH_SIZE = 100; private final ArticleKeywordRepository articleKeywordRepository; @@ -24,7 +33,30 @@ public class KeywordExtractor { public List matchKeyword(List
articles, Integer authorId) { List articleKeywordUserMaps = articleKeywordUserMapRepository.findAll(); + Set keywordMatchResults = new HashSet<>(); + + for (Article article : articles) { + String title = article.getTitle(); + for (ArticleKeywordUserMap articleKeywordUserMap : articleKeywordUserMaps) { + String keyword = articleKeywordUserMap.getKeyword(); + if (!title.contains(keyword)) { + continue; + } + + KeywordMatchResult keywordMatchResult = KeywordMatchResult.of( + article.getId(), articleKeywordUserMap.getUserId(), keyword + ); + + keywordMatchResults.stream() + .filter(result -> result.equals(keywordMatchResult)) + .findFirst() + .ifPresentOrElse( + existing -> existing.updateKeywordIfLonger(keyword), + () -> keywordMatchResults.add(keywordMatchResult) + ); + } + } /* Map> matchedKeywordByUserIdByArticleId = new LinkedHashMap<>(); From e84f9b11677bd4c70ebab11315af39bc295b5e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:48:06 +0900 Subject: [PATCH 06/15] =?UTF-8?q?fix:=20matchKeyword=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9D=91=EB=8B=B5=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/community/util/KeywordExtractor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index 27199547b..bcf863350 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -31,7 +31,7 @@ public class KeywordExtractor { private final ArticleKeywordRepository articleKeywordRepository; private final ArticleKeywordUserMapRepository articleKeywordUserMapRepository; - public List matchKeyword(List
articles, Integer authorId) { + public List matchKeyword(List
articles, Integer authorId) { List articleKeywordUserMaps = articleKeywordUserMapRepository.findAll(); Set keywordMatchResults = new HashSet<>(); @@ -58,6 +58,8 @@ public List matchKeyword(List
articles, Integer au } } + return keywordMatchResults.stream().toList(); + /* Map> matchedKeywordByUserIdByArticleId = new LinkedHashMap<>(); int offset = 0; From 2b6735acd8d3ccdc91ee2e0a99087d31b665c08a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:48:35 +0900 Subject: [PATCH 07/15] =?UTF-8?q?chore:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/util/KeywordExtractor.java | 76 ------------------- 1 file changed, 76 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index bcf863350..f67dae11f 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -7,11 +7,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import in.koreatech.koin.common.event.ArticleKeywordEvent; import in.koreatech.koin.domain.community.article.model.Article; import in.koreatech.koin.domain.community.keyword.model.ArticleKeywordUserMap; import in.koreatech.koin.domain.community.keyword.model.KeywordMatchResult; -import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordRepository; import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordUserMapRepository; import lombok.RequiredArgsConstructor; @@ -20,15 +18,6 @@ @Transactional(readOnly = true) public class KeywordExtractor { - /** - * - 하나의 게시글에서 여러 키워드가 매칭 될 경우 - * - 하나의 게시글에서 동일한 키워드가 매칭 될 경우 - * - 여러개의 게시글에서 동일한 키워드가 매칭 될 경우 - */ - - private static final int KEYWORD_BATCH_SIZE = 100; - - private final ArticleKeywordRepository articleKeywordRepository; private final ArticleKeywordUserMapRepository articleKeywordUserMapRepository; public List matchKeyword(List
articles, Integer authorId) { @@ -59,70 +48,5 @@ public List matchKeyword(List
articles, Integer aut } return keywordMatchResults.stream().toList(); - - /* - Map> matchedKeywordByUserIdByArticleId = new LinkedHashMap<>(); - int offset = 0; - - while (true) { - Pageable pageable = PageRequest.of(offset / KEYWORD_BATCH_SIZE, KEYWORD_BATCH_SIZE); - List keywords = articleKeywordRepository.findAll(pageable); - - if (keywords.isEmpty()) { - break; - } - List keywordIds = keywords.stream() - .map(ArticleKeyword::getId) - .toList(); - Map> userMapsByKeywordId = articleKeywordUserMapRepository - .findAllByArticleKeywordIdIn(keywordIds) - .stream() - .filter(keywordUserMap -> !keywordUserMap.getIsDeleted()) - .collect(Collectors.groupingBy( - keywordUserMap -> keywordUserMap.getArticleKeyword().getId(), - LinkedHashMap::new, - Collectors.toList() - )); - - for (Article article : articles) { - String title = article.getTitle(); - for (ArticleKeyword keyword : keywords) { - if (!title.contains(keyword.getKeyword())) { - continue; - } - Map matchedKeywordByUserId = matchedKeywordByUserIdByArticleId - .computeIfAbsent(article.getId(), ignored -> new LinkedHashMap<>()); - - for (ArticleKeywordUserMap keywordUserMap : - userMapsByKeywordId.getOrDefault(keyword.getId(), List.of())) { - Integer userId = keywordUserMap.getUser().getId(); - matchedKeywordByUserId.merge( - userId, - keyword.getKeyword(), - this::pickHigherPriorityKeyword - ); - } - } - } - offset += KEYWORD_BATCH_SIZE; - } - - List keywordEvents = new ArrayList<>(); - for (Article article : articles) { - Map matchedKeywordByUserId = matchedKeywordByUserIdByArticleId.get(article.getId()); - if (matchedKeywordByUserId != null && !matchedKeywordByUserId.isEmpty()) { - keywordEvents.add(new ArticleKeywordEvent(article.getId(), authorId, matchedKeywordByUserId)); - } - } - */ - - return null; - } - - private String pickHigherPriorityKeyword(String previousKeyword, String candidateKeyword) { - if (candidateKeyword.length() > previousKeyword.length()) { - return candidateKeyword; - } - return previousKeyword; } } From d15c14cc78f93ec2cde515fbcdf5af4ccf151104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:51:15 +0900 Subject: [PATCH 08/15] =?UTF-8?q?fix:=20KeywordExtractor=20Service=20->=20?= =?UTF-8?q?Component=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/community/util/KeywordExtractor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index f67dae11f..04433510d 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.Set; -import org.springframework.stereotype.Service; +import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import in.koreatech.koin.domain.community.article.model.Article; @@ -13,7 +13,7 @@ import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordUserMapRepository; import lombok.RequiredArgsConstructor; -@Service +@Component @RequiredArgsConstructor @Transactional(readOnly = true) public class KeywordExtractor { From 5256239056129580065347c747d460ae32cfde57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:54:06 +0900 Subject: [PATCH 09/15] =?UTF-8?q?feat:=20=EC=9E=90=EC=8B=A0=EC=9D=98=20?= =?UTF-8?q?=EA=B0=9C=EC=8B=9C=EA=B8=80=20=EC=97=AC=EB=B6=80=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/community/util/KeywordExtractor.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index 04433510d..f69932ac1 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -2,6 +2,7 @@ import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import org.springframework.stereotype.Component; @@ -28,6 +29,10 @@ public List matchKeyword(List
articles, Integer aut String title = article.getTitle(); for (ArticleKeywordUserMap articleKeywordUserMap : articleKeywordUserMaps) { + if (Objects.equals(articleKeywordUserMap.getUserId(), authorId)) { + continue; + } + String keyword = articleKeywordUserMap.getKeyword(); if (!title.contains(keyword)) { continue; From 3d2bbba7c02048292cafcfc7e73d1faec40e0518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:55:29 +0900 Subject: [PATCH 10/15] =?UTF-8?q?fix:=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koreatech/koin/domain/community/util/KeywordExtractor.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index f69932ac1..19a4c6003 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -6,7 +6,6 @@ import java.util.Set; import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; import in.koreatech.koin.domain.community.article.model.Article; import in.koreatech.koin.domain.community.keyword.model.ArticleKeywordUserMap; @@ -16,7 +15,6 @@ @Component @RequiredArgsConstructor -@Transactional(readOnly = true) public class KeywordExtractor { private final ArticleKeywordUserMapRepository articleKeywordUserMapRepository; From 36ad5aacb52165da59998a18a320ad7aefbbcb5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:56:09 +0900 Subject: [PATCH 11/15] =?UTF-8?q?fix:=20articleKeywordUserMapRepository=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/community/util/KeywordExtractor.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index 19a4c6003..9a94121c6 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -10,17 +10,14 @@ import in.koreatech.koin.domain.community.article.model.Article; import in.koreatech.koin.domain.community.keyword.model.ArticleKeywordUserMap; import in.koreatech.koin.domain.community.keyword.model.KeywordMatchResult; -import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordUserMapRepository; import lombok.RequiredArgsConstructor; @Component -@RequiredArgsConstructor public class KeywordExtractor { - private final ArticleKeywordUserMapRepository articleKeywordUserMapRepository; - - public List matchKeyword(List
articles, Integer authorId) { - List articleKeywordUserMaps = articleKeywordUserMapRepository.findAll(); + public List matchKeyword( + List
articles, List articleKeywordUserMaps, Integer authorId + ) { Set keywordMatchResults = new HashSet<>(); for (Article article : articles) { From 88146f2256aff413a92a1ff0649368e851e51729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 15:57:32 +0900 Subject: [PATCH 12/15] =?UTF-8?q?fix:=20RequiredArgsConstructor=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koreatech/koin/domain/community/util/KeywordExtractor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index 9a94121c6..72eb5b5c3 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -10,7 +10,6 @@ import in.koreatech.koin.domain.community.article.model.Article; import in.koreatech.koin.domain.community.keyword.model.ArticleKeywordUserMap; import in.koreatech.koin.domain.community.keyword.model.KeywordMatchResult; -import lombok.RequiredArgsConstructor; @Component public class KeywordExtractor { From 44a706899e30088d935b34e64d226f98d256f559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 16:03:24 +0900 Subject: [PATCH 13/15] =?UTF-8?q?refactor:=20matchKeyword=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/util/KeywordExtractor.java | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index 72eb5b5c3..99922f036 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -20,32 +20,34 @@ public List matchKeyword( Set keywordMatchResults = new HashSet<>(); for (Article article : articles) { - String title = article.getTitle(); - for (ArticleKeywordUserMap articleKeywordUserMap : articleKeywordUserMaps) { - if (Objects.equals(articleKeywordUserMap.getUserId(), authorId)) { - continue; - } - - String keyword = articleKeywordUserMap.getKeyword(); - if (!title.contains(keyword)) { - continue; + if (isMatchable(article, articleKeywordUserMap, authorId)) { + addOrUpdateResult(keywordMatchResults, article, articleKeywordUserMap); } - - KeywordMatchResult keywordMatchResult = KeywordMatchResult.of( - article.getId(), articleKeywordUserMap.getUserId(), keyword - ); - - keywordMatchResults.stream() - .filter(result -> result.equals(keywordMatchResult)) - .findFirst() - .ifPresentOrElse( - existing -> existing.updateKeywordIfLonger(keyword), - () -> keywordMatchResults.add(keywordMatchResult) - ); } } return keywordMatchResults.stream().toList(); } + + private boolean isMatchable(Article article, ArticleKeywordUserMap articleKeywordUserMap, Integer authorId) { + return !Objects.equals(articleKeywordUserMap.getUserId(), authorId) + && article.getTitle().contains(articleKeywordUserMap.getKeyword()); + } + + private void addOrUpdateResult( + Set results, Article article, ArticleKeywordUserMap userMap + ) { + KeywordMatchResult keywordMatchResult = KeywordMatchResult.of( + article.getId(), userMap.getUserId(), userMap.getKeyword() + ); + + results.stream() + .filter(result -> result.equals(keywordMatchResult)) + .findFirst() + .ifPresentOrElse( + existing -> existing.updateKeywordIfLonger(userMap.getKeyword()), + () -> results.add(keywordMatchResult) + ); + } } From 4ac7c5b0f4adfb112f5ddb299b57bec7792b39fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 16:04:09 +0900 Subject: [PATCH 14/15] =?UTF-8?q?chore:=20=EB=B3=80=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/community/util/KeywordExtractor.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java index 99922f036..87a7516b2 100644 --- a/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java +++ b/src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java @@ -36,18 +36,18 @@ private boolean isMatchable(Article article, ArticleKeywordUserMap articleKeywor } private void addOrUpdateResult( - Set results, Article article, ArticleKeywordUserMap userMap + Set keywordMatchResults, Article article, ArticleKeywordUserMap articleKeywordUserMap ) { KeywordMatchResult keywordMatchResult = KeywordMatchResult.of( - article.getId(), userMap.getUserId(), userMap.getKeyword() + article.getId(), articleKeywordUserMap.getUserId(), articleKeywordUserMap.getKeyword() ); - results.stream() + keywordMatchResults.stream() .filter(result -> result.equals(keywordMatchResult)) .findFirst() .ifPresentOrElse( - existing -> existing.updateKeywordIfLonger(userMap.getKeyword()), - () -> results.add(keywordMatchResult) + existing -> existing.updateKeywordIfLonger(articleKeywordUserMap.getKeyword()), + () -> keywordMatchResults.add(keywordMatchResult) ); } } From 07ee2cc5815d2843cd4553e15581ed44ab0f86f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Mon, 30 Mar 2026 16:09:57 +0900 Subject: [PATCH 15/15] =?UTF-8?q?chore:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=8C=EC=A7=80=ED=86=A0=EB=A6=AC=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArticleKeywordUserMapRepository.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordUserMapRepository.java b/src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordUserMapRepository.java index 532812796..b55c9f118 100644 --- a/src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordUserMapRepository.java +++ b/src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordUserMapRepository.java @@ -29,13 +29,6 @@ default ArticleKeywordUserMap getById(Integer keywordUserMapId) { List findAllByUserId(Integer userId); - @Query(""" - SELECT akw.keyword FROM ArticleKeywordUserMap akum - JOIN akum.articleKeyword akw - WHERE akum.user.id = :userId - """) - List findAllKeywordByUserId(@Param("userId") Integer userId); - @Query(value = """ SELECT * FROM article_keyword_user_map akum WHERE akum.keyword_id = :articleKeywordId @@ -47,11 +40,4 @@ Optional findByArticleKeywordIdAndUserIdIncludingDeleted( ); List findAllByArticleKeywordIdIn(List articleKeywordIds); - - @Query(""" - SELECT akum FROM ArticleKeywordUserMap akum - JOIN FETCH akum.articleKeyword - JOIN FETCH akum.user - """) - List findAll(); }