๐ Guava: ๊ตฌ๊ธ์ ํต์ฌ ์๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๐

์๋ , ์๋ฐ ๊ฐ๋ฐ์ ์น๊ตฌ๋ค! ์ค๋์ ์ ๋ง ์ฌ๋ฏธ์๊ณ ์ ์ฉํ ์ฃผ์ ๋ฅผ ๊ฐ์ง๊ณ ์์ด. ๋ฐ๋ก ๊ตฌ๊ธ์์ ๋ง๋ Guava ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ์ด ๋ ์, ์ ๋ง ๋๋จํ๋ค๊ณ ! ์๋ฐ ๊ฐ๋ฐํ ๋ ์์ด์๋ ์ ๋ ์น๊ตฌ ๊ฐ์ ์กด์ฌ๋ผ๋๊น. ๐
์ฐ๋ฆฌ๊ฐ ์ด Guava์ ๋ํด ๊น์ด ํ๊ณ ๋ค๋ฉด์, ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ์ฌ๋ฅ์ ๋ฐ๊ฒฌํ๋ ๊ฒ์ฒ๋ผ ์ ์ ํ ๊ฒฝํ์ ํ ๊ฑฐ์ผ. ์, ๊ทธ๋ผ ์ด ๋ฉ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ธ๊ณ๋ก ํจ๊ป ๋ ๋๋ณผ๊น?
๐ Guava๋?
Guava๋ ๊ตฌ๊ธ์์ ๊ฐ๋ฐํ ์คํ์์ค ์๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ์ด ๋ ์์ ์๋ฐ ๊ฐ๋ฐ์๋ค์ ์์ฐ์ฑ์ ์์ฒญ๋๊ฒ ๋์ฌ์ฃผ๋ ์ ํธ๋ฆฌํฐ ํด๋์ค๋ค์ ๋ชจ์์ด์ง. ์ปฌ๋ ์ , ์บ์ฑ, ๋ณ๋ ฌ ์ฒ๋ฆฌ, I/O ๋ฑ ๋ค์ํ ์์ญ์์ ์ฐ๋ฆฌ์ ์ฝ๋ฉ ์ํ์ ๋์ฑ ํธ๋ฆฌํ๊ฒ ๋ง๋ค์ด์ค.
๐ Guava์ ์ฃผ์ ํน์ง
- โ ํ๋ถํ ์ ํธ๋ฆฌํฐ ํด๋์ค
- โ ์ฑ๋ฅ ์ต์ ํ
- โ ์์ ์ฑ๊ณผ ์ ๋ขฐ์ฑ
- โ ์ง์์ ์ธ ์ ๋ฐ์ดํธ์ ์ปค๋ฎค๋ํฐ ์ง์
- โ ์ฌ์ด ์ฌ์ฉ๋ฒ
์ด์ ๋ถํฐ Guava์ ์ฃผ์ ๊ธฐ๋ฅ๋ค์ ํ๋์ฉ ์ดํด๋ณผ ๊ฑฐ์ผ. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ๊ตฌ๊ฒฝํ๋ฏ์ด, Guava์ ๋ค์ฑ๋ก์ด ๊ธฐ๋ฅ๋ค์ ํํํด๋ณด์๊ณ !
๐งฉ Guava์ ์ปฌ๋ ์ ์ ํธ๋ฆฌํฐ
์, ์ด์ Guava์ ์ฒซ ๋ฒ์งธ ๋งค๋ ฅ ํฌ์ธํธ, ์ปฌ๋ ์ ์ ํธ๋ฆฌํฐ์ ๋ํด ์์๋ณผ ๊ฑฐ์ผ. ์ด ๋ ์๋ค์ ์ ๋ง ๋๋จํด. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ฌ๋ค๋ฅํ ํ๋ฆฌ๋์๋ฅผ ๋ง๋ ๊ฒ ๊ฐ์ ๋๋์ด๋๊น? ๐
1. Immutable ์ปฌ๋ ์
Guava๋ ๋ถ๋ณ(Immutable) ์ปฌ๋ ์ ์ ์ ๊ณตํด. ์ด๊ฒ ๋ญ๊ฐ ์ข๋๊ณ ? ์, ์์ํด๋ด. ๋ค๊ฐ ๋ง๋ ๋ฆฌ์คํธ๋ฅผ ๋๊ตฐ๊ฐ๊ฐ ๋ชฐ๋ ๋ฐ๊ฟ๋ฒ๋ฆฌ๋ฉด ์ด๋จ๊น? ์์ฐํ์ง? ๊ทธ๋์ ๋ถ๋ณ ์ปฌ๋ ์ ์ด ํ์ํ ๊ฑฐ์ผ.
๐ Immutable ์ปฌ๋ ์ ์ ์ฅ์ :
- ์ค๋ ๋ ์์ ์ฑ ๋ณด์ฅ
- ์์์น ๋ชปํ ์์ ๋ฐฉ์ง
- ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ๋ณผ๊น?
import com.google.common.collect.ImmutableList;
ImmutableList<String> fruits = ImmutableList.of("์ฌ๊ณผ", "๋ฐ๋๋", "์ฒด๋ฆฌ");
// fruits.add("๋ธ๊ธฐ"); // ์ด๋ ๊ฒ ํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํด. ๋ถ๋ณ์ด๋๊น!
์! ์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ๋ถ๋ณ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค ์ ์์ด. ์ด์ ๋๊ฐ ๋ชฐ๋ ๊ณผ์ผ์ ์ถ๊ฐํ๊ฑฐ๋ ๋นผ๋ ค๊ณ ํด๋ ์ ๋ผ. ์ฐ๋ฆฌ์ ๊ณผ์ผ ๋ฐ๊ตฌ๋๋ ์์ ํด! ๐๐๐
2. Multiset
๋ค์์ Multiset์ด์ผ. ์ด ๋ ์์ ์ ๋ง ์ฌ๋ฐ์ด. ์ผ๋ฐ Set์ด๋ ๋น์ทํ๋ฐ, ์ค๋ณต ์์๋ฅผ ํ์ฉํด. ๊ทธ๋ฆฌ๊ณ ๊ฐ ์์์ ๊ฐ์๋ ์ธ์ด์ค. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ์ ์ง๊ณํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ!
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ์จ๋ณผ๊น?
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
Multiset<String> bookBag = HashMultiset.create();
bookBag.add("ํด๋ฆฌ ํฌํฐ");
bookBag.add("ํด๋ฆฌ ํฌํฐ");
bookBag.add("๋ฐ์ง์ ์ ์");
System.out.println(bookBag.count("ํด๋ฆฌ ํฌํฐ")); // ์ถ๋ ฅ: 2
System.out.println(bookBag.count("๋ฐ์ง์ ์ ์")); // ์ถ๋ ฅ: 1
์์ฐ! ์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ๊ฐ ์ฑ ์ ๊ฐ์๋ฅผ ์ ์ ์์ด. ๋ง์น ๋์๊ด ์ฌ์๊ฐ ๋ ๊ฒ ๊ฐ์ง ์์? ๐
3. Multimap
Multimap์ ๋ ๋ค๋ฅธ ์ฌ๋ฏธ์๋ ๋ ์์ด์ผ. ์ผ๋ฐ Map์ด๋ ๋น์ทํ๋ฐ, ํ๋์ ํค์ ์ฌ๋ฌ ๊ฐ์ ๊ฐ์ ๋งคํํ ์ ์์ด. ์ด๊ฑด ์ ๋ง ์ ์ฉํด. ์๋ฅผ ๋ค์ด, ํ์๋ค์ ์ทจ๋ฏธ๋ฅผ ์ ๋ฆฌํ๋ค๊ณ ์๊ฐํด๋ด.
๐ญ Multimap ์ฌ์ฉ ์์:
- ํ์ - ์ทจ๋ฏธ
- ๋์ - ๋๋๋งํฌ
- ์๊ฐ - ์ํ
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ๋ณผ๊น?
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
Multimap<String, String> studentHobbies = ArrayListMultimap.create();
studentHobbies.put("์ฒ ์", "์ถ๊ตฌ");
studentHobbies.put("์ฒ ์", "๊ฒ์");
studentHobbies.put("์ํฌ", "๋
์");
studentHobbies.put("์ํฌ", "๊ทธ๋ฆผ");
System.out.println(studentHobbies.get("์ฒ ์")); // ์ถ๋ ฅ: [์ถ๊ตฌ, ๊ฒ์]
System.out.println(studentHobbies.get("์ํฌ")); // ์ถ๋ ฅ: [๋
์, ๊ทธ๋ฆผ]
์! ์ด๋ ๊ฒ ์ฝ๊ฒ ํ ํ์์ ์ฌ๋ฌ ์ทจ๋ฏธ๋ฅผ ๊ด๋ฆฌํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ํ ์ฌ๋์ ๋ค์ํ ์ฌ๋ฅ์ ์๊ฐํ๋ ๊ฒ ๊ฐ์ง ์์? ๐
4. BiMap
BiMap์ ์๋ฐฉํฅ ๋งต์ด์ผ. ์ผ๋ฐ Map์ ํค๋ก ๊ฐ์ ์ฐพ์ ์ ์์ง๋ง, ๊ฐ์ผ๋ก ํค๋ฅผ ์ฐพ๊ธฐ๋ ์ด๋ ต์์. ํ์ง๋ง BiMap์ ์์ชฝ ๋ค ๊ฐ๋ฅํด!
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ์จ๋ณผ๊น?
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
BiMap<String, Integer> nameToId = HashBiMap.create();
nameToId.put("Alice", 1);
nameToId.put("Bob", 2);
System.out.println(nameToId.get("Alice")); // ์ถ๋ ฅ: 1
System.out.println(nameToId.inverse().get(2)); // ์ถ๋ ฅ: Bob
์์ฐ! ์ด๋ ๊ฒ ์ฝ๊ฒ ์ด๋ฆ์ผ๋ก ID๋ฅผ ์ฐพ๊ณ , ID๋ก ์ด๋ฆ์ ์ฐพ์ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฅ ์ด๋ฆ์ผ๋ก ์นดํ ๊ณ ๋ฆฌ๋ฅผ ์ฐพ๊ณ , ์นดํ ๊ณ ๋ฆฌ๋ก ์ฌ๋ฅ์ ์ฐพ๋ ๊ฒ์ฒ๋ผ ํธ๋ฆฌํ์ง? ๐
5. Table
๋ง์ง๋ง์ผ๋ก ์๊ฐํ ์ปฌ๋ ์ ์ Table์ด์ผ. ์ด ๋ ์์ ์ ๋ง ํน๋ณํด. 2์ฐจ์ ํ ์ด๋ธ ๊ตฌ์กฐ๋ฅผ ํํํ ์ ์๊ฑฐ๋ . ํ๊ณผ ์ด, ๊ทธ๋ฆฌ๊ณ ๊ฐ์ผ๋ก ๊ตฌ์ฑ๋ผ ์์ด.
๐ Table ์ฌ์ฉ ์์:
- ์์ ์ํธ ๋ฐ์ดํฐ
- ์ขํ ์์คํ
- ๋ค์ฐจ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ๋ณผ๊น?
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
Table<String, String, Integer> gradeTable = HashBasedTable.create();
gradeTable.put("์ฒ ์", "์ํ", 90);
gradeTable.put("์ฒ ์", "์์ด", 85);
gradeTable.put("์ํฌ", "์ํ", 95);
gradeTable.put("์ํฌ", "์์ด", 92);
System.out.println(gradeTable.get("์ฒ ์", "์ํ")); // ์ถ๋ ฅ: 90
System.out.println(gradeTable.column("์์ด")); // ์ถ๋ ฅ: {์ฒ ์=85, ์ํฌ=92}
System.out.println(gradeTable.row("์ํฌ")); // ์ถ๋ ฅ: {์ํ=95, ์์ด=92}
์! ์ด๋ ๊ฒ ์ฝ๊ฒ ํ์๋ค์ ๊ณผ๋ชฉ๋ณ ์ฑ์ ์ ๊ด๋ฆฌํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ์ฌ์ฉ์์ ๋ค์ํ ์ฌ๋ฅ๊ณผ ๊ทธ์ ๋ํ ํ๊ฐ๋ฅผ ํ๋์ ๋ณผ ์ ์๋ ๊ฒ ๊ฐ์ง ์์? ๐
์, ์ด๋ ๊ฒ Guava์ ์ปฌ๋ ์ ์ ํธ๋ฆฌํฐ๋ค์ ์ดํด๋ดค์ด. ์ด ๋ ์๋ค, ์ ๋ง ๋๋จํ์ง? ์ฐ๋ฆฌ์ ์ฝ๋ฉ ์ํ์ ํจ์ฌ ๋ ํธ๋ฆฌํ๊ฒ ๋ง๋ค์ด์ฃผ๋ ๋ ๋ ํ ์น๊ตฌ๋ค์ด์ผ. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฐ์ง ํ๋ฆฌ๋์๋ค์ ๋ง๋๋ ๊ฒ์ฒ๋ผ, Guava์ ์ปฌ๋ ์ ๋ค๋ ๊ฐ์์ ํน๋ณํ ์ฌ๋ฅ์ ๊ฐ์ง๊ณ ์์ด. ์ด์ ์ด ๋ ์๋ค์ ์ ํ์ฉํด์ ๋ ๋ฉ์ง ์๋ฐ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋์ด๋ณด์๊ณ ! ๐ช
๐ง Guava์ ์บ์ฑ ๊ธฐ๋ฅ
์, ์ด์ Guava์ ๋ ๋ค๋ฅธ ๋ฉ์ง ๊ธฐ๋ฅ์ธ ์บ์ฑ์ ๋ํด ์์๋ณผ ๊ฑฐ์ผ. ์บ์ฑ์ด ๋ญ๋๊ณ ? ์... ์์ํด๋ด. ๋ค๊ฐ ๋งค์ผ ์์นจ ๋๊ฐ์ ๊ธธ๋ก ํ๊ต์ ๊ฐ. ๊ทธ๋ฐ๋ฐ ๋งค์ผ ์ง๋๋ฅผ ๋ณด๋ฉด์ ๊ฐ? ์๋์ง! ํ ๋ฒ ์ธ์ฐ๋ฉด ๊ทธ ๋ค์๋ถํฐ๋ ๊ทธ๋ฅ ๊ธฐ์ตํด์ ๊ฐ์์. ๊ทธ๊ฒ ๋ฐ๋ก ์บ์ฑ์ด์ผ! ๐
๐ ์บ์ฑ์ ์ฅ์ :
- ๋น ๋ฅธ ๋ฐ์ดํฐ ์ ๊ทผ
- ์๋ฒ ๋ถํ ๊ฐ์
- ๋ฐ๋ณต์ ์ธ ๊ณ์ฐ ๋ฐฉ์ง
Guava์ ์บ์ฑ ๊ธฐ๋ฅ์ ์ ๋ง ๋๋จํด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ์ ๋ฏธ๋ฆฌ ์ค๋นํด๋๋ ๊ฒ์ฒ๋ผ, ์์ฃผ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ ๊ทผํ ์ ์๊ฒ ํด์ค.
1. LoadingCache
LoadingCache๋ Guava์ ์บ์ฑ ๊ธฐ๋ฅ ์ค ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ๋ ์์ด์ผ. ์ด ๋ ์์ ์บ์์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ๋ก๋ํด์ฃผ๋ ๊ธฐ๋ฅ์ด ์์ด. ์ ๋ง ํธ๋ฆฌํ์ง?
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ๋ณผ๊น?
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.build(
new CacheLoader<String, Integer>() {
public Integer load(String key) {
return heavyComputation(key);
}
});
// ์ฌ์ฉ ์
try {
int result = cache.get("someKey");
System.out.println("Result: " + result);
} catch (ExecutionException e) {
// ์์ธ ์ฒ๋ฆฌ
}
// heavyComputation ๋ฉ์๋๋ ์ค์ ๋ก ๋ฌด๊ฑฐ์ด ๊ณ์ฐ์ ์ํํ๋ ๋ฉ์๋๋ผ๊ณ ๊ฐ์
private static int heavyComputation(String key) {
// ์ค์ ๋ก๋ ๋ณต์กํ ๊ณ์ฐ์ด ์ฌ๊ธฐ์ ๋ค์ด๊ฐ ๊ฑฐ์ผ
return key.length() * 10;
}
์! ์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ์บ์๋ฅผ ๋ง๋ค ์ ์์ด. ์ด์ "someKey"์ ๋ํ ๊ณ์ฐ ๊ฒฐ๊ณผ๋ฅผ ํ ๋ฒ๋ง ์ํํ๊ณ , ๊ทธ ๋ค์๋ถํฐ๋ ์บ์์์ ๋ฐ๋ก ๊ฐ์ ธ์ค์ง. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ์ ๋ฏธ๋ฆฌ ์ค๋นํด๋๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ! ๐
2. ์บ์ ์ค์
Guava์ ์บ์๋ ์ ๋ง ๋ค์ํ ์ค์ ์ด ๊ฐ๋ฅํด. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ต์ ์ผ๋ก ์ฌ๋ฅ์ ๊ฒ์ํ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ. ๋ช ๊ฐ์ง ์ค์ํ ์ค์ ์ ์ดํด๋ณผ๊น?
โ๏ธ ์ฃผ์ ์บ์ ์ค์ :
- maximumSize: ์บ์์ ์ต๋ ํฌ๊ธฐ
- expireAfterWrite: ํญ๋ชฉ์ด ์์ฑ๋ ํ ํน์ ์๊ฐ์ด ์ง๋๋ฉด ๋ง๋ฃ
- expireAfterAccess: ํญ๋ชฉ์ ๋ง์ง๋ง์ผ๋ก ์ ๊ทผํ ํ ํน์ ์๊ฐ์ด ์ง๋๋ฉด ๋ง๋ฃ
- refreshAfterWrite: ํญ๋ชฉ์ด ์์ฑ๋ ํ ํน์ ์๊ฐ์ด ์ง๋๋ฉด ์๋ก๊ณ ์นจ
์ด ์ค์ ๋ค์ ์ฌ์ฉํด์ ์บ์๋ฅผ ๋์ฑ ์ธ๋ฐํ๊ฒ ์ ์ดํ ์ ์์ด. ์๋ฅผ ๋ค์ด๋ณผ๊น?
LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
.maximumSize(1000) // ์ต๋ 1000๊ฐ์ ํญ๋ชฉ๋ง ์ ์ฅ
.expireAfterWrite(10, TimeUnit.MINUTES) // ์์ฑ ํ 10๋ถ ๋ค ๋ง๋ฃ
.refreshAfterWrite(1, TimeUnit.MINUTES) // ์์ฑ ํ 1๋ถ ๋ค ์๋ก๊ณ ์นจ
.build(
new CacheLoader<String, Integer>() {
public Integer load(String key) {
return heavyComputation(key);
}
});
์์ฐ! ์ด๋ ๊ฒ ์ค์ ํ๋ฉด ์บ์๊ฐ ํญ์ ์ต์ ์ํ๋ฅผ ์ ์งํ๋ฉด์๋ ๋๋ฌด ์ปค์ง์ง ์๊ฒ ๊ด๋ฆฌํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ๋ค์ ์ฃผ๊ธฐ์ ์ผ๋ก ์ ๋ฐ์ดํธํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ! ๐
3. ์บ์ ํต๊ณ
Guava ์บ์์ ๋ ๋ค๋ฅธ ๋ฉ์ง ๊ธฐ๋ฅ์ ๋ฐ๋ก ํต๊ณ ๊ธฐ๋ฅ์ด์ผ. ์บ์๊ฐ ์ผ๋ง๋ ํจ์จ์ ์ผ๋ก ๋์ํ๊ณ ์๋์ง ์ ์ ์์ง. ์ด๊ฑด ์ ๋ง ์ ์ฉํด!
LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.recordStats() // ํต๊ณ ๊ธฐ๋ก ํ์ฑํ
.build(
new CacheLoader<String, Integer>() {
public Integer load(String key) {
return heavyComputation(key);
}
});
// ์บ์ ์ฌ์ฉ ํ...
System.out.println(cache.stats().hitRate()); // ์บ์ ํํธ์จ
System.out.println(cache.stats().averageLoadPenalty()); // ํ๊ท ๋ก๋ฉ ์๊ฐ
์ด๋ ๊ฒ ์บ์์ ์ฑ๋ฅ์ ๋ชจ๋ํฐ๋งํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ์ฌ๋ฅ์ ์ธ๊ธฐ๋๋ฅผ ์ฒดํฌํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ! ๐
4. ๋ฉํฐ์ฐ๋ ๋ ํ๊ฒฝ์์์ ์บ์ฑ
Guava์ ์บ์๋ ๋ฉํฐ์ฐ๋ ๋ ํ๊ฒฝ์์๋ ์์ ํ๊ฒ ๋์ํด. ์ด๊ฑด ์ ๋ง ์ค์ํ ํน์ง์ด์ผ. ์ฌ๋ฌ ์ฌ๋์ด ๋์์ ์ฌ๋ฅ๋ท์ ์ฌ์ฉํด๋ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ฒ๋ผ, ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ๋์์ ์บ์๋ฅผ ์ฌ์ฉํด๋ ๋ฌธ์ ๊ฐ ์์ด!
LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.concurrencyLevel(10) // ๋์์ ์ต๋ 10๊ฐ์ ์ฐ๋ ๋๊ฐ ์บ์์ ์ ๊ทผ ๊ฐ๋ฅ
.build(
new CacheLoader<String, Integer>() {
public Integer load(String key) {
return heavyComputation(key);
}
});
์ด๋ ๊ฒ ์ค์ ํ๋ฉด ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ๋์์ ์บ์๋ฅผ ์ฌ์ฉํด๋ ์์ ํด. ์ ๋ง ๋๋จํ์ง? ๐
5. ์บ์ ์ ๊ฑฐ ๋ฆฌ์ค๋
๋ง์ง๋ง์ผ๋ก ์๊ฐํ ๊ธฐ๋ฅ์ ์บ์ ์ ๊ฑฐ ๋ฆฌ์ค๋์ผ. ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์บ์์์ ํญ๋ชฉ์ด ์ ๊ฑฐ๋ ๋ ํน์ ์์ ์ ์ํํ ์ ์์ด.
LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.removalListener(new RemovalListener<String, Integer>() {
public void onRemoval(RemovalNotification<String, Integer> removal) {
System.out.println("Removed: " + removal.getKey() + " -> " + removal.getValue());
}
})
.build(
new CacheLoader<String, Integer>() {
public Integer load(String key) {
return heavyComputation(key);
}
});
์ด๋ ๊ฒ ํ๋ฉด ์บ์์์ ํญ๋ชฉ์ด ์ ๊ฑฐ๋ ๋๋ง๋ค ๋ก๊ทธ๋ฅผ ๋จ๊ธธ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ์ด ๋ชฉ๋ก์์ ์ ๊ฑฐ๋ ๋ ์๋ฆผ์ ๋ฐ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ! ๐ข
์, ์ด๋ ๊ฒ Guava์ ์บ์ฑ ๊ธฐ๋ฅ์ ๋ํด ์์๋ดค์ด. ์ด ๊ธฐ๋ฅ๋ค์ ์ ํ์ฉํ๋ฉด ํ๋ก๊ทธ๋จ์ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ๋ค์ ๋ฏธ๋ฆฌ ์ค๋นํด๋๋ ๊ฒ์ฒ๋ผ, ์์ฃผ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ ๊ทผํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฑฐ์ง. ์ด์ ์ด ๋ ์๋ค์ ํ์ฉํด์ ๋ ๋น ๋ฅด๊ณ ํจ์จ์ ์ธ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์๊ณ ! ๐ช
๐ Guava์ ๋ณ๋ ฌ ์ฒ๋ฆฌ ๊ธฐ๋ฅ
์, ์ด์ Guava์ ๋ ๋ค๋ฅธ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ธ ๋ณ๋ ฌ ์ฒ๋ฆฌ์ ๋ํด ์์๋ณผ ๊ฑฐ์ผ. ๋ณ๋ ฌ ์ฒ๋ฆฌ๊ฐ ๋ญ๋๊ณ ? ์... ์์ํด๋ด. ๋ค๊ฐ ํผ์์ ๋ฐฉ ์ฒญ์๋ฅผ ํ๋ฉด ์ค๋ ๊ฑธ๋ฆฌ์ง๋ง, ์น๊ตฌ๋ค์ด๋ ๊ฐ์ด ํ๋ฉด ํจ์ฌ ๋นจ๋ฆฌ ๋๋์์? ๊ทธ๊ฒ ๋ฐ๋ก ๋ณ๋ ฌ ์ฒ๋ฆฌ์ผ! ๐
๐ ๋ณ๋ ฌ ์ฒ๋ฆฌ์ ์ฅ์ :
- ์์ ์ฒ๋ฆฌ ์๋ ํฅ์
- ์์คํ ์์์ ํจ์จ์ ์ฌ์ฉ
- ๋ณต์กํ ์์ ์ ๊ฐํธํ ์ฒ๋ฆฌ
Guava์ ๋ณ๋ ฌ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ ์ ๋ง ๋๋จํด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ํ๋ฆฌ๋์๊ฐ ๋์์ ์ผ์ ์ฒ๋ฆฌํ๋ ๊ฒ์ฒ๋ผ, ์ฌ๋ฌ ์์ ์ ๋์์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ค.
1. ListenableFuture
ListenableFuture๋ Guava์์ ์ ๊ณตํ๋ Future์ ํ์ฅ ๋ฒ์ ์ด์ผ. ์ด ๋ ์์ ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋์์ ๋ ์ฝ๋ฐฑ์ ์คํํ ์ ์๊ฒ ํด์ค. ์ ๋ง ํธ๋ฆฌํ์ง?
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ๋ณผ๊น?
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Integer> future = service.submit(new Callable<Integer>() {
public Integer call() {
return heavyComputation();
}
});
Futures.addCallback(future, new FutureCallback<Integer>() {
public void onSuccess(Integer result) {
System.out.println("Computation finished: " + result);
}
public void onFailure(Throwable thrown) {
System.err.println("Computation failed: " + thrown);
}
});
// heavyComputation ๋ฉ์๋๋ ์ค์ ๋ก ๋ฌด๊ฑฐ์ด ๊ณ์ฐ์ ์ํํ๋ ๋ฉ์๋๋ผ๊ณ ๊ฐ์
private static int heavyComputation() {
// ์ค์ ๋ก๋ ๋ณต์กํ ๊ณ์ฐ์ด ์ฌ๊ธฐ์ ๋ค์ด๊ฐ ๊ฑฐ์ผ
return 42;
}
์! ์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ๋น๋๊ธฐ ์์ ์ ์ฒ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์๋ณผ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ํ๋ฆฌ๋์์๊ฒ ์์ ์ ์๋ขฐํ๊ณ ์๋ฃ๋๋ฉด ์๋ฆผ์ ๋ฐ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ! ๐
2. Futures ์ ํธ๋ฆฌํฐ
Guava๋ Futures๋ผ๋ ์ ํธ๋ฆฌํฐ ํด๋์ค๋ฅผ ์ ๊ณตํด. ์ด ๋ ์์ Future ๊ฐ์ฒด๋ค์ ๋ค๋ฃจ๋ ๋ฐ ์ ๋ง ์ ์ฉํ ๋ฉ์๋๋ค์ ๊ฐ์ง๊ณ ์์ด.
๐ ๏ธ Futures ์ ํธ๋ฆฌํฐ์ ์ฃผ์ ๊ธฐ๋ฅ:
- ์ฌ๋ฌ Future์ ๊ฒฐ๊ณผ๋ฅผ ํ๋๋ก ํฉ์น๊ธฐ
- Future์ ๊ฒฐ๊ณผ๋ฅผ ๋ณํํ๊ธฐ
- Future์ ํ์์์ ์ค์ ํ๊ธฐ
์ด ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํ๋ฉด ๋ณต์กํ ๋น๋๊ธฐ ์์ ์ ๋ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์์ด. ์๋ฅผ ๋ค์ด๋ณผ๊น?
ListenableFuture<Integer> future1 = service.submit(new Callable<Integer>() {
public Integer call() { return 1; }
});
ListenableFuture<Integer> future2 = service.submit(new Callable<Integer>() {
public Integer call() { return 2; }
});
ListenableFuture<List<Integer>> combinedFutures = Futures.allAsList(future1, future2);
Futures.addCallback(combinedFutures, new FutureCallback<List<Integer>>() {
public void onSuccess(List<Integer> result) {
System.out.println("Combined result: " + result);
}
public void onFailure(Throwable thrown) {
System.err.println("Computation failed: " + thrown);
}
});
์์ฐ! ์ด๋ ๊ฒ ์ฌ๋ฌ Future์ ๊ฒฐ๊ณผ๋ฅผ ํ ๋ฒ์ ๋ฐ์๋ณผ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ํ๋ฆฌ๋์์ ์์ ๊ฒฐ๊ณผ๋ฅผ ํ ๋ฒ์ ํ์ธํ๋ ๊ฒ์ฒ๋ผ ํธ๋ฆฌํ์ง? ๐
3. RateLimiter
RateLimiter๋ Guava์์ ์ ๊ณตํ๋ ๋ ๋ค๋ฅธ ์ ์ฉํ ๊ธฐ๋ฅ์ด์ผ. ์ด ๋ ์์ ์์ ์ ์คํ ์๋๋ฅผ ์ ์ดํ ์ ์๊ฒ ํด์ค. ํน์ ์๊ฐ ๋์ ์คํํ ์ ์๋ ์์ ์ ์๋ฅผ ์ ํํ๋ ๊ฑฐ์ง.
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ๋ณผ๊น?
import com.google.common.util.concurrent.RateLimiter;
RateLimiter limiter = RateLimiter.create(2.0); // ์ด๋น 2๊ฐ์ ์์
๋ง ํ์ฉ
for (int i = 0; i < 10; i++) {
limiter.acquire(); // ์์
์คํ ์ ๊ถํ ํ๋
executeTask(i);
}
private static void executeTask(int taskId) {
System.out.println("Executing task " + taskId);
// ์ค์ ์์
์ํ
}
์ด๋ ๊ฒ ํ๋ฉด ์ด๋น 2๊ฐ์ ์์ ๋ง ์คํ๋๋๋ก ์ ํํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ํ๋ฆฌ๋์๊ฐ ํ ๋ฒ์ ๋๋ฌด ๋ง์ ์์ ์ ๋ฐ์ง ์๋๋ก ์ ํํ๋ ๊ฒ๊ณผ ๋น์ทํด! ๐จโ๐ป
4. ServiceManager
๋ง์ง๋ง์ผ๋ก ์๊ฐํ ๊ธฐ๋ฅ์ ServiceManager์ผ. ์ด ๋ ์์ ์ฌ๋ฌ ์๋น์ค์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐ ์ฌ์ฉ๋ผ. ์๋น์ค์ ์์, ์ค์ง, ์ํ ํ์ธ ๋ฑ์ ํ ๋ฒ์ ์ฒ๋ฆฌํ ์ ์์ง.
import com.google.common.util.concurrent.AbstractService;
import com.google.common.util.concurrent.ServiceManager;
class MyService extends AbstractService {
protected void doStart() { /* ์๋น์ค ์์ ๋ก์ง */ }
protected void doStop() { /* ์๋น์ค ์ค์ง ๋ก์ง */ }
}
List<Service> services = Arrays.asList(new MyService(), new MyService());
ServiceManager manager = new ServiceManager(services);
manager.addListener(new ServiceManager.Listener() {
public void healthy() {
System.out.println("All services are running.");
}
public void stopped() {
System.out.println("All services have stopped.");
}
});
manager.startAsync(); // ๋ชจ๋ ์๋น์ค ๋น๋๊ธฐ์ ์ผ๋ก ์์
์! ์ด๋ ๊ฒ ์ฌ๋ฌ ์๋น์ค๋ฅผ ํ ๋ฒ์ ๊ด๋ฆฌํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ํ๋ฆฌ๋์์ ์์ ์ํ๋ฅผ ํ ๋์ ๊ด๋ฆฌํ๋ ๊ฒ์ฒ๋ผ ํธ๋ฆฌํ์ง? ๐
์, ์ด๋ ๊ฒ Guava์ ๋ณ๋ ฌ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ ๋ํด ์์๋ดค์ด. ์ด ๊ธฐ๋ฅ๋ค์ ์ ํ์ฉํ๋ฉด ๋ณต์กํ ๋น๋๊ธฐ ์์ ์ ํจ์ฌ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ํ๋ฆฌ๋์์ ์์ ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ. ์ด์ ์ด ๋ ์๋ค์ ํ์ฉํด์ ๋ ๊ฐ๋ ฅํ๊ณ ํจ์จ์ ์ธ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์๊ณ ! ๐ช
๐ Guava์ I/O ์ ํธ๋ฆฌํฐ
์, ์ด์ Guava์ ๋ง์ง๋ง ์ฃผ์ ๊ธฐ๋ฅ์ธ I/O ์ ํธ๋ฆฌํฐ์ ๋ํด ์์๋ณผ ๊ฑฐ์ผ. I/O๊ฐ ๋ญ๋๊ณ ? ์... ์์ํด๋ด. ๋ค๊ฐ ์ฑ ์ ์ฝ๊ณ (Input) ๊ทธ ๋ด์ฉ์ ๋ ธํธ์ ์ ๋(Output) ๊ฑธ ์๊ฐํด๋ด. ๊ทธ๊ฒ ๋ฐ๋ก I/O์ผ! ์ปดํจํฐ์์๋ ํ์ผ์ ์ฝ๊ณ ์ฐ๋ ๊ฑธ ๋งํ์ง. ๐
๐ Guava I/O ์ ํธ๋ฆฌํฐ์ ์ฅ์ :
- ๊ฐ๊ฒฐํ๊ณ ์ฝ๊ธฐ ์ฌ์ด ์ฝ๋
- ๋ค์ํ ์ ํธ๋ฆฌํฐ ๋ฉ์๋ ์ ๊ณต
- ์๋ฌ ์ฒ๋ฆฌ์ ๊ฐ์ํ
Guava์ I/O ์ ํธ๋ฆฌํฐ๋ ์ ๋ง ํธ๋ฆฌํด. ๋ง์น ์ฌ๋ฅ๋ท์์ ํ๋ฆฌ๋์๊ฐ ์์ ๊ฒฐ๊ณผ๋ฌผ์ ์ฝ๊ฒ ์ ๋ก๋ํ๊ณ ๋ค์ด๋ก๋ํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ์ฒ๋ผ, ํ์ผ ์์ ์ ํจ์ฌ ์ฝ๊ฒ ๋ง๋ค์ด์ค.
1. Files ํด๋์ค
Files ํด๋์ค๋ ํ์ผ ๊ด๋ จ ์์ ์ ์ฝ๊ฒ ํ ์ ์๊ฒ ํด์ฃผ๋ ์ ํธ๋ฆฌํฐ ํด๋์ค์ผ. ํ์ผ ์ฝ๊ธฐ, ์ฐ๊ธฐ, ๋ณต์ฌ ๋ฑ์ ์์ ์ ๊ฐ๋จํ๊ฒ ์ฒ๋ฆฌํ ์ ์์ง.
์, ์ด์ ์ฝ๋๋ก ํ๋ฒ ๋ณผ๊น?
import com.google.common.io.Files;
import java.io.File;
import java.nio.charset.StandardCharsets;
// ํ์ผ ์ฝ๊ธฐ
List<String> lines = Files.readLines(new File("input.txt"), StandardCharsets.UTF_8);
// ํ์ผ ์ฐ๊ธฐ
Files.write("Hello, Guava!".getBytes(), new File("output.txt"));
// ํ์ผ ๋ณต์ฌ
Files.copy(new File("source.txt"), new File("destination.txt"));
์! ์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ํ์ผ ์์ ์ ํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ํ๋ฆฌ๋์๊ฐ ์์ ๊ฒฐ๊ณผ๋ฌผ์ ์ฝ๊ฒ ์ ๋ก๋ํ๊ณ ๋ค์ด๋ก๋ํ๋ ๊ฒ์ฒ๋ผ ํธ๋ฆฌํ์ง? ๐
2. ByteSource์ CharSource
ByteSource์ CharSource๋ ๋ฐ์ดํธ ๋ฐ์ดํฐ์ ๋ฌธ์ ๋ฐ์ดํฐ๋ฅผ ์ถ์ํํ ํด๋์ค์ผ. ์ด ๋ ์๋ค์ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ์ ์์ฒ์ ์๊ด์์ด ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์์ด.
import com.google.common.io.ByteSource;
import com.google.common.io.CharSource;
import com.google.common.io.Files;
// ํ์ผ์์ ByteSource ์์ฑ
ByteSource byteSource = Files.asByteSource(new File("data.bin"));
byte[] bytes = byteSource.read();
// ๋ฌธ์์ด์์ CharSource ์์ฑ
CharSource charSource = CharSource.wrap("Hello, Guava!");
String result = charSource.read();
์ด๋ ๊ฒ ํ๋ฉด ๋ฐ์ดํฐ์ ์ถ์ฒ์ ์๊ด์์ด ๋์ผํ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ํ์์ ํฌํธํด๋ฆฌ์ค๋ฅผ ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ๋ณผ ์ ์๋ ๊ฒ์ฒ๋ผ ํธ๋ฆฌํ์ง? ๐
3. ByteSink์ CharSink
ByteSink์ CharSink๋ ByteSource์ CharSource์ ์ฐ๊ธฐ ๋ฒ์ ์ด์ผ. ์ด ๋ ์๋ค์ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ์์ ์ ์ถ์ํํ ์ ์์ด.
import com.google.common.io.ByteSink;
import com.google.common.io.CharSink;
import com.google.common.io.Files;
// ํ์ผ์ ByteSink ์์ฑ
ByteSink byteSink = Files.asByteSink(new File("output.bin"));
byteSink.write(new byte[]{1, 2, 3, 4, 5});
// ํ์ผ์ CharSink ์์ฑ
CharSink charSink = Files.asCharSink(new File("output.txt"), StandardCharsets.UTF_8);
charSink.write("Hello, Guava!");
์์ฐ! ์ด๋ ๊ฒ ์ฝ๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ธ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ํ๋ฆฌ๋์๊ฐ ๋ค์ํ ํ์์ ๊ฒฐ๊ณผ๋ฌผ์ ์ฝ๊ฒ ์ ๋ก๋ํ ์ ์๋ ๊ฒ์ฒ๋ผ ํธ๋ฆฌํ์ง? ๐จโ๐ป
4. ์คํธ๋ฆผ ์ ํธ๋ฆฌํฐ
Guava๋ ์คํธ๋ฆผ ์์ ์ ์ํ ๋ค์ํ ์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ ์ ๊ณตํด. ์ด ๋ ์๋ค์ ์ฌ์ฉํ๋ฉด ์คํธ๋ฆผ ์ฒ๋ฆฌ๋ฅผ ๋์ฑ ์ฝ๊ฒ ํ ์ ์์ด.
import com.google.common.io.ByteStreams;
import com.google.common.io.CharStreams;
import java.io.InputStream;
import java.io.InputStreamReader;
// InputStream์ byte ๋ฐฐ์ด๋ก ๋ณํ
byte[] bytes = ByteStreams.toByteArray(inputStream);
// Reader์ ๋ด์ฉ์ ๋ฌธ์์ด๋ก ์ฝ๊ธฐ
String content = CharStreams.toString(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
์ด๋ ๊ฒ ์คํธ๋ฆผ ์์ ์ ๊ฐ๋จํ๊ฒ ์ฒ๋ฆฌํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋์ฉ๋ ํ์ผ์ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ ๊ฒ์ฒ๋ผ ํธ๋ฆฌํ์ง? ๐
์, ์ด๋ ๊ฒ Guava์ I/O ์ ํธ๋ฆฌํฐ์ ๋ํด ์์๋ดค์ด. ์ด ๊ธฐ๋ฅ๋ค์ ์ ํ์ฉํ๋ฉด ํ์ผ ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ ์ ์ถ๋ ฅ ์์ ์ ํจ์ฌ ์ฝ๊ณ ํจ์จ์ ์ผ๋ก ํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ํ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฒ ๋ค๋ฃจ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ. ์ด์ ์ด ๋ ์๋ค์ ํ์ฉํด์ ๋ ๊ฐ๋ ฅํ๊ณ ํจ์จ์ ์ธ I/O ์ฒ๋ฆฌ๋ฅผ ํด๋ณด์๊ณ ! ๐ช
๐ญ Guava: ๊ฒฐ๋ก ๋ฐ ๋ง๋ฌด๋ฆฌ
์, ์ฐ๋ฆฌ์ Guava ์ฌํ์ด ๊ฑฐ์ ๋๋๊ฐ๊ณ ์์ด. ์ ๋ง ๋ฉ์ง ์ฌ์ ์ด์์ง? ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฐ์ง ํ๋ฆฌ๋์๋ค์ ๋ง๋๋ณธ ๊ฒ ๊ฐ์. ๐
๐ Guava์ ์ฃผ์ ์ฅ์ :
- ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ ํฅ์
- ์์ฐ์ฑ ์ฆ๊ฐ
- ๋ฒ๊ทธ ๋ฐ์ ๊ฐ๋ฅ์ฑ ๊ฐ์
- ์ฑ๋ฅ ์ต์ ํ
Guava๋ ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ์ผ. ์ปฌ๋ ์ , ์บ์ฑ, ๋ณ๋ ฌ ์ฒ๋ฆฌ, I/O ๋ฑ ๋ค์ํ ์์ญ์์ ์ฐ๋ฆฌ์ ์ฝ๋ฉ ์ํ์ ๋์ฑ ํธ๋ฆฌํ๊ฒ ๋ง๋ค์ด์ค. ๋ง์น ์ฌ๋ฅ๋ท์ด ํ๋ฆฌ๋์์ ํด๋ผ์ด์ธํธ๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ ๊ฒ์ฒ๋ผ, Guava๋ ์ฐ๋ฆฌ์ ํจ์จ์ ์ธ ์ฝ๋ฉ์ ์ฐ๊ฒฐํด์ฃผ๋ ๋ค๋ฆฌ ์ญํ ์ ํ์ง.
ํ์ง๋ง ๊ธฐ์ตํด์ผ ํ ์ ์, Guava๋ ๊ฒฐ๊ตญ์ ๋๊ตฌ์ผ ๋ฟ์ด๋ผ๋ ๊ฑฐ์ผ. ์ค์ํ ๊ฑด ์ด ๋๊ตฌ๋ฅผ ์ด๋ป๊ฒ ํ์ฉํ๋๋์ผ. ๋ง์น ์ฌ๋ฅ๋ท์์ ์์ ์ ์ฌ๋ฅ์ ์ด๋ป๊ฒ ํํํ๊ณ ํ์ฉํ๋๋๊ฐ ์ค์ํ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ.
๊ทธ๋ฌ๋ Guava๋ฅผ ์ฌ์ฉํ ๋๋ ํญ์ ์ด๋ฐ ์ง๋ฌธ์ ํด๋ณด์:
- ์ด ๊ธฐ๋ฅ์ด ๋ด ์ฝ๋๋ฅผ ๋ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ค์ด์ฃผ๋?
- ์ด ๊ธฐ๋ฅ์ด ๋ด ์ฝ๋์ ์ฑ๋ฅ์ ํฅ์์์ผ์ฃผ๋?
- ์ด ๊ธฐ๋ฅ์ด ๋ด ์ฝ๋์ ์์ ์ฑ์ ๋์ฌ์ฃผ๋?
์ด๋ฐ ์ง๋ฌธ๋ค์ "์"๋ผ๊ณ ๋ตํ ์ ์๋ค๋ฉด, ์ฃผ์ ์์ด Guava๋ฅผ ์ฌ์ฉํด๋ณด์๊ณ !
์, ์ด์ ์ฐ๋ฆฌ์ Guava ์ฌํ์ด ๋๋ฌ์ด. ํ์ง๋ง ์ด๊ฒ ๋์ด ์๋์ผ. ์ด์ ๋ถํฐ๊ฐ ์ง์ง ์์์ด์ง. Guava๋ฅผ ํ์ฉํด์ ๋ ๋ฉ์ง ์ฝ๋๋ฅผ ์์ฑํ๊ณ , ๋ ํจ์จ์ ์ธ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ๊ธฐํ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ์ฑ์ฅํด๋๊ฐ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ.
์ฝ๋ฉ์ ์ธ๊ณ๋ ๋๊ณ ๊น์ด. Guava๋ ๊ทธ ์ธ๊ณ๋ฅผ ํํํ๋ ๋ฐ ๋์์ ์ฃผ๋ ํ๋ฅญํ ๋๊ตฌ์ผ. ์ด ๋๊ตฌ๋ฅผ ์ ํ์ฉํด์ ์๋ฐ ๊ฐ๋ฐ์ ๋ฌ์ธ์ด ๋์ด๋ณด์๊ณ ! ํ์ดํ ! ๐ช๐
๊ด๋ จ ํค์๋
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ