25-03-21
๐ Daily Reportโ
๐ ํ๋ก์ ํธ ์ํฉโ
์ ๊ธฐํ ๊ฒฝํ์ ํ๊ณ ์๋ค. ์๋ฌด๋ฆฌ ์๋ ์ ๊ฒ ๊ฐ์ง๊ฐ ์์;
์ต๋ํ ๋ฎ์ ์ด์ฌํ ํด๋ณด๊ณ ํ ์์ผ ๋๋น๋ฅผ ํด์ผ๊ฒ ๋ค ํ... ์ฐ์ฑ ๋ 1์๊ฐ๋ฐ์ ๋ชปํ๊ธ๋ค
๋ค์ด๋ฒ ์๋ฐ๊ธฐ ์ผ์ ์ด๋ ์ต์ข ๋ฐํ๋ ๊ฒน์ณ์ ์ ๋ง ๋ถ๋จ์๋ก ๋ญ์ ๋ ๋ฆฌ์์ค๋ฅผ ํ ๋นํ ์ง ์๊ฐ์ด ๋ฐ๋๊ณ ์๋ค.
๐ DateTimeFormatter locale ์ค์ โ
๋ฐฐํฌํ๋๊น ์ญ์ ์๋ฒ ๋จธ์ ์ธํ ๋ฐ๋ผ์ locale์ด ๊นจ์ง๊ธธ๋ ๊ณ ์ ์์ผ์คฌ๋ค.
DateTimeFormatter ์์ฐ๊ณ thymeleaf ํ
ํ๋ฆฟ ํ์ผ ๋ด์์ ๋ฐ๋ก ์ธํ
ํ๋ ๋ฐฉ๋ฒ๋ ์๊ธด ํ๋๋ฐ, (#temporal
์ด์ฉ๊ตฌ) ํ
ํ๋ฆฟ ์ฝ๋ ๊ธธ์ด์ง๋๊ฑฐ ์์ข์ํ๊ธฐ๋ ํ๊ณ locale๋ DateTimeFormatter๋ณด๋ค ๋์จํ๊ธธ๋ (๋ก์ปฌ ๋จธ์ locale ์๋ฐ๋ผ๊ฐ) ๊ทธ๋ฅ ๊ธฐ์กด์ ์ฐ๋ ๋ฐฉ์ ์ฐ๊ธฐ๋ก ํ๋ค.
์ฐธ๊ณ ๋ก ํ
ํ๋ฆฟ ์ฝ๋ ๊ธธ์ด์ง๋๊ฑฐ ์์ข์ํ๋ ์ด์ ๋, ๋ง๊ทธ๋๋ก ๊ทธ๊ฑด view๋ฅผ ์ํ ํ
ํ๋ฆฟ์ด๊ธฐ ๋๋ฌธ์ด๋ค. ํ
ํ๋ฆฟ ํ์ผ์ ๋ณผ ๋ view์ ๊ตฌ์กฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ดํดํ๋ ๊ฒ์ด ๋ชฉ์ ์ด๋ค. ๊ทธ๋ฐ๋ฐ #temporal
์ด๋ฐ๊ฑธ๋ก ํ์๋ฆฌํ ๋ฌธ๋ฒ ๊ธธ์ญ๊ธธ์ญํ๊ฒ ๋ค์ด๊ฐ์ ๊ฐ๋
์ฑ ๋ง๊ฐ์ง๋ฉด ๋ฆฌ๋ฉ ์๊ฐ์ด ๋์ด๋๋ค. ๋ ๊ทธ๊ฒ ์ซ๋ค.
๋ฐ์ดํฐ ๊ฐ๊ณต ๋ก์ง์ java์์ ์ฒ๋ฆฌํด์ผ ํ๋ค๊ณ ์๊ฐํ๋ค. ์ฌ์ฐจํ๋ฉด ์ ์ฒ๋ฆฌ ๋ก์ง ๋ฐ๋ก ๋ถ๋ฆฌํด์ ๋ฐ์๋ค ๋นผ๋๋ฉด ๋๊ณ .
{
// 1. ๋นํ์์ด๊ฑฐ๋ ๋ก๊ทธ์ธํ ์ด์ฉ์ (null ์ฒดํฌ๊ฐ ์กฐ๊ฑด์ ์์ ์์ด์ผ ํจ)
if (role == null || role.equals("MEMBER")) {
if (pageIdx == null) pageIdx = 0; // ๋ฃจํธ ๊ฒฝ๋ก์์ ํธ์ถ ์ ์ฒซ ํ์ด์ง ์กฐํ
PageResponseDto page = storeIndexService.getStoreListInternal("", pageIdx); // v2 ํ์
์คํ ์ด ์กฐํ
model.addAttribute("page", page);
List<StoreMetaDocument> storeList = (List<StoreMetaDocument>) page.getData(); // downcast
model.addAttribute("storeList", storeList);
model.addAttribute("formatter", DateTimeFormatter.ofPattern("MM.dd(E)").withLocale(Locale.forLanguageTag("ko")));
return "index"; // ํ์
์คํ ์ด ๋ชฉ๋ก ํ์ด์ง๋ก ์ด๋
}
}
๐ 3๊ฐ์ง ์กฐํ ๋ก์ง ์์ฑโ
MySQL, Elasticsearch, Redis cache ์ด 3๊ฐ์ง ๋ฐฉ์์ผ๋ก ํ์ ์คํ ์ด ๋ชฉ๋ก ์กฐํ ๋ก์ง์ ์์ฑํ๋ค.
...Redis์ผ LocalDate ์ง์์ ์ข ๊ธฐ๋ณธ์ผ๋ก ํด์ฃผ๋ฉด ์๋ ๊น.
๋ฟ๋ง ์๋๋ผ config ์ค์ ๊น์ง ๋ง์ ธ์ค์ผ ํ๋ค.
config์ ๋น์ผ๋ก ๋ฑ๋กํ๋๊น ObjectMapper ์ปค์คํ ํ๊ฒ ํฐ์ ธ์ dto serializing์ด ์๋๋๋ฐ, ์ด์ฐจํผ ํ ์คํธ๋ง ํ๋ ค๋ ๋ชฉ์ ์ด๋๊น ๊ธํ๊ฒ Object๋ก ํ์ด๋ง์๋ค.
์ญ์ ๋ง ์๋ค์ผ๋ฉด ๋ถ๋ชจ๋ฅผ ๋ฐ๋ ค์์ผ ใ
Object๋ ์์กฐ ์๋๊ฐ
๐ JMeter ๊ทธ๋ํ ํ๋ฌ๊ทธ์ธโ
๊ธฐ์กด๊บผ๋ ๋ง์๊ฒ ์๊ฒจ์ ๊ทธ๋ํ ํ๋ฌ๊ทธ์ธ์ ํ๋ ๊น์๋ค. ๋ํดํธ listener๋ณด๋จ ๋ซ๋๋ผ.
๋ ํผ๋ฐ์ค๋ ์ด๊ฑธ ์ฐธ๊ณ ํ๋ค.
๐ Redis ์บ์ฑ ์ฌํโ
๋น์ฅ์ ๊ฐ๋จํ ์บ์ฑ ์ค์ ์ผ๋ก ๋ณด๊ณ ์๋ฅผ ์์ฑํ๋๋ฐ, ์๋ ์ด์ ๋๋ ๋์ด์ผ ํ์ง ์์๊น ์ถ๋ค.
๊ทธ๋ฆฌ๊ณ Grafana ์ง์ง ๋ง์๊ฒ ์๊ธด๋ฏ... ๋ค์ ๋ฒ์ ์ ๊ผญ ๋ถ์ด์!!
๐ JMeter Out of Memory ๋ฌธ์ โ
์กฐํ ํ ์คํธํ๋๋ฐ ์ค๊ฐ์ ์ ๊ฐ ๋ฉ์ถฐ๋ฒ๋ ค์ bat ํ์ผ ๋ณด๋๊น...
heap ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ๋จ๋ค... ๊ทธ๋์ ์ต๋ 8GB๊น์ง ๋๋ ค์คฌ๋ค ใ ใ
์๊พธ ์ธํ ์ ์ ๊ฐ๋๊ฑฐ ๊ท์ฐฎ์.
๐ JMeter port ๊ฐ์ ๋ถ์กฑโ
3000๊ฐ๊น์ง ๊ทธ๋ญ์ ๋ญ ๊ตด๋ฌ๊ฐ๋๋ฐ 5000๊ฐ๋ ํ๋ failed transaction์ด ๋ง์ด ๋ ์, ๋ญ๊ฐ ํ๊ณ Tree๋ฅผ ๋ดค๋๋ฐ ์ด๋ฐ ๋ก๊ทธ๊ฐ ์์๋ค.
java.net.BindException: Address already in use: connect
์ด๊ฑฐ ์ฐธ๊ณ ํด์ ๋ ์ง์คํธ๋ฆฌ ์ถ๊ฐํ๊ธฐ ์ ๋ณด๋จ ์กฐ๊ธ ๋์์ง๊ธด ํ๋๋ฐ ๊ทธ๋๋ ํธ๋์ญ์ ์ด ๋งํ์ ์ข ๋ถ์์ ํจ. ์...
์์ง?? ๐๐๐
๐ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ๋ก์ง ์์ โ
์๊ธฐ์ resizing option ์ ์ค๋ช ํด์ฃผ๋๋ผ!
๋ค์๊ณผ ๊ฐ์ด ์์ ํ๋ค.
๊ทธ๋ฆฌ๊ณ webp ์ด๊ฑฐ ์์ ์ ๋ ํผ๋ฐ์ค ๋ดค์๋ ๋ฌด์จ ๋ฒํผ ๋ค๋ฃจ๊ณ ๊ทธ๋ฌ์ด์ผ ํ๋๋ฐ... ๊ทธ๊ฑด sharp ์ด๊ฒ ์๋์๋?
์์ธ๋ก JMeter ํ ์คํธ๊ฐ ํ๋ฃจ์ข ์ผ ๊ฑธ๋ฆฌ๊ณ ์ ์ webp ๋ณํ์ ๊ธ๋ฐฉ ๋๋์ ๊ธฐ๋ถ์ด ์ข์๋ค ^ใ ^
if (key.includes('thumb')) {
try {
resizedImage_400 = await sharp(originalImage.Body)
.resize(400, 400, {fit: 'inside'})
.jpeg({ quality: 100 })
.toBuffer();
} catch (error) {
console.log(error);
return;
}
...
}
if (key.includes('thumb')) {
try {
resizedImage_400 = await sharp(originalImage.Body)
.resize(400, 400, {fit: 'outside'})
.webp({ quality: 100 })
.toBuffer();
} catch (error) {
console.log(error);
return;
}
...
}