Skip to content

Commit 0610b79

Browse files
authored
feat: youtube api key rotate 구현
# 변경점 👍 youtube api key rotating 구현 AtomicInteger를 통해서 여러개있는 api key를 순차적으로 사용하도록 합니다.
1 parent 1c280df commit 0610b79

File tree

2 files changed

+51
-9
lines changed

2 files changed

+51
-9
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package apptive.team5.youtube;
2+
3+
4+
import jakarta.annotation.PostConstruct;
5+
import org.springframework.beans.factory.annotation.Value;
6+
import org.springframework.stereotype.Component;
7+
8+
import java.util.Arrays;
9+
import java.util.List;
10+
import java.util.concurrent.atomic.AtomicInteger;
11+
12+
@Component
13+
public class YoutubeApiKeyProvider {
14+
15+
@Value("${youtube.api.key}")
16+
private String apiKey;
17+
18+
private List<String> keys;
19+
private final AtomicInteger index = new AtomicInteger(0);
20+
21+
@PostConstruct
22+
public void init() {
23+
24+
keys = Arrays.stream(apiKey.split(","))
25+
.map(String::trim)
26+
.toList();
27+
}
28+
29+
public String nextKey() {
30+
int i = Math.abs(index.getAndIncrement() % keys.size());
31+
return keys.get(i);
32+
}
33+
}

src/main/java/apptive/team5/youtube/service/YoutubeService.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import apptive.team5.global.exception.ExceptionCode;
44
import apptive.team5.global.exception.ExternalApiConnectException;
5+
import apptive.team5.youtube.YoutubeApiKeyProvider;
56
import apptive.team5.youtube.dto.YoutubeSearchRequest;
67
import apptive.team5.youtube.dto.YoutubeVideoResponse;
78
import com.google.api.client.http.javanet.NetHttpTransport;
89
import com.google.api.client.json.gson.GsonFactory;
910
import com.google.api.services.youtube.YouTube;
1011
import com.google.api.services.youtube.model.SearchListResponse;
1112
import com.google.api.services.youtube.model.VideoListResponse;
12-
import org.springframework.beans.factory.annotation.Value;
1313
import org.springframework.http.HttpStatus;
1414
import org.springframework.stereotype.Service;
1515

@@ -21,13 +21,18 @@
2121
@Service
2222
public class YoutubeService {
2323

24-
@Value("${youtube.api.key}")
25-
private String apiKey;
24+
private final YoutubeApiKeyProvider apiKeyProvider;
2625
private static final GsonFactory gsonFactory = new GsonFactory();
2726

27+
public YoutubeService(YoutubeApiKeyProvider provider) {
28+
this.apiKeyProvider = provider;
29+
}
30+
2831
public List<YoutubeVideoResponse> searchVideo(YoutubeSearchRequest searchRequest) {
29-
YouTube youtube = new YouTube.
30-
Builder(
32+
33+
String apiKey = apiKeyProvider.nextKey();
34+
35+
YouTube youtube = new YouTube.Builder(
3136
new NetHttpTransport(), gsonFactory, request -> {}
3237
).build();
3338

@@ -40,25 +45,29 @@ public List<YoutubeVideoResponse> searchVideo(YoutubeSearchRequest searchRequest
4045
.setKey(apiKey)
4146
.execute();
4247

43-
List<String> videoIds = searchResponse.getItems().stream()
48+
List<String> videoIds = searchResponse.getItems()
49+
.stream()
4450
.map(r -> r.getId().getVideoId())
4551
.filter(Objects::nonNull)
4652
.toList();
4753

48-
4954
VideoListResponse videoResponse = youtube.videos()
5055
.list(Collections.singletonList("snippet,contentDetails,statistics"))
5156
.setId(Collections.singletonList(String.join(",", videoIds)))
5257
.setKey(apiKey)
5358
.execute();
5459

5560
return videoResponse.getItems()
56-
.stream().map(YoutubeVideoResponse::new)
61+
.stream()
62+
.map(YoutubeVideoResponse::new)
5763
.sorted()
5864
.toList();
5965

6066
} catch (IOException e) {
61-
throw new ExternalApiConnectException(ExceptionCode.YOUTUBE_API_EXCEPTION.getDescription(), HttpStatus.INTERNAL_SERVER_ERROR);
67+
throw new ExternalApiConnectException(
68+
ExceptionCode.YOUTUBE_API_EXCEPTION.getDescription(),
69+
HttpStatus.INTERNAL_SERVER_ERROR
70+
);
6271
}
6372
}
6473
}

0 commit comments

Comments
 (0)