|
24 | 24 | import java.io.IOException; |
25 | 25 | import java.util.ArrayList; |
26 | 26 | import java.util.List; |
27 | | -import java.util.Set; |
| 27 | +import java.util.Map; |
28 | 28 | import java.util.stream.Collectors; |
29 | 29 |
|
30 | 30 | @Service |
@@ -123,33 +123,51 @@ private List<Tag> getOrCreateTags(List<String> tagNames) { |
123 | 123 | return new ArrayList<>(); |
124 | 124 | } |
125 | 125 |
|
126 | | - // 기존 태그 조회 |
127 | | - List<Tag> existingTags = tagRepository.findByNameIn(tagNames); |
128 | | - |
129 | | - Set<String> existingNames = existingTags.stream() |
130 | | - .map(Tag::getName) |
131 | | - .collect(Collectors.toSet()); |
| 126 | + // 1. 동일한 사용자의 태그 중복 제거 |
| 127 | + List<String> distinctNames = tagNames.stream() |
| 128 | + .map(String::trim) |
| 129 | + .filter(name -> !name.isEmpty()) |
| 130 | + .distinct() |
| 131 | + .toList(); |
132 | 132 |
|
133 | | - // 신규 태그 생성 |
134 | | - List<Tag> newTags = createNewTags(tagNames, existingNames); |
| 133 | + // 2. 기존 태그 조회 - MySQL collation에 의해 대소문자 무시 |
| 134 | + Map<String, Tag> tagMap = tagRepository.findByNameIn(distinctNames).stream() |
| 135 | + .collect(Collectors.toMap( |
| 136 | + Tag::getName, |
| 137 | + tag -> tag, (t1, t2) -> t1) |
| 138 | + ); |
135 | 139 |
|
136 | | - // 기존 태그 + 신규 태그 |
137 | | - List<Tag> allTags = new ArrayList<>(existingTags); |
138 | | - allTags.addAll(newTags); |
| 140 | + return buildTagList(distinctNames, tagMap); |
| 141 | + } |
139 | 142 |
|
140 | | - return allTags; |
| 143 | + /** |
| 144 | + * 기존 태그 + 신규 태그 |
| 145 | + * - 정확히 일치하는 건 재사용 (대소문자 구분) |
| 146 | + * - 없을 경우 신규 태그 생성 |
| 147 | + */ |
| 148 | + private List<Tag> buildTagList(List<String> distinctNames, Map<String, Tag> tagMap) { |
| 149 | + List<Tag> result = new ArrayList<>(); |
| 150 | + for (String name : distinctNames) { |
| 151 | + Tag tag = tagMap.getOrDefault(name, createTagSafely(name)); |
| 152 | + if (tag != null) { |
| 153 | + result.add(tag); |
| 154 | + } |
| 155 | + } |
| 156 | + return result; |
141 | 157 | } |
142 | 158 |
|
143 | | - private List<Tag> createNewTags(List<String> tagNames, Set<String> existingNames) { |
144 | | - List<Tag> newTags = tagNames.stream() |
145 | | - .filter(name -> !existingNames.contains(name)) |
146 | | - .map(name -> Tag.builder().name(name).build()) |
147 | | - .toList(); |
| 159 | + private Tag createTagSafely(String name) { |
| 160 | + // 생성 전 재조회로 중복 방지 |
| 161 | + Tag existing = tagRepository.findByNameIn(List.of(name)).stream() |
| 162 | + .filter(tag -> tag.getName().equals(name)) |
| 163 | + .findFirst() |
| 164 | + .orElse(null); |
148 | 165 |
|
149 | | - if (!newTags.isEmpty()) { |
150 | | - tagRepository.saveAll(newTags); |
| 166 | + if (existing != null) { |
| 167 | + return existing; |
151 | 168 | } |
152 | | - return newTags; |
| 169 | + |
| 170 | + return tagRepository.save(Tag.builder().name(name).build()); |
153 | 171 | } |
154 | 172 |
|
155 | 173 |
|
|
0 commit comments