* ์๋น์ค๋ช : ์๋๋ฐฑ (Think + Sandbag = Thandbag!)
* ์๋น์ค ์ค๋ช : ์ผ์ ์ํ์์์ ๋ฐ์ ์คํธ๋ ์ค, ๊ณ ๋ฏผ์ ์๋๋ฐฑ์ ๋๋ฆฌ๋ฉด์ ์ฌ๋ฏธ์๊ฒ ํ ์ ์๋ ์คํธ๋ ์ค ํด์ ์๋น์ค
- [์ฌ์ดํธ ๋ฐ๋ก๊ฐ๊ธฐ] ๊ณผ๊ธ์ผ๋ก ์ธํด ํ์ฌ๋ ์๋ฒ๋ฅผ ์ด์ํ์ง ์๊ณ ์์ต๋๋ค.
- [์์ฐ์์ ๋ฐ๋ก๊ฐ๊ธฐ]
- Back-end: ๊ณ ์ฑ๋ฒ, ์ค๊ทํ(์กฐ์ฅ)
- Front-end: ์ด์ค๋ช , ์ ์ฉํ, ์ ์์ผ
- Design : ์ ์์ค, ํฉ์งํ
- [Front-End Github]
- 2021๋ 12์ 18์ผ ~ 2022๋ 01์ 28์ผ
๋ถ๋ฅ | ๊ธฐ์ |
---|---|
IDE | |
Language | |
Framework | |
Build Tool | |
DB | |
Memory DB | |
Server | |
CI/CD | |
Test | |
Load Test | |
VCS | |
Reverse Proxy | |
API Document Tool |
- ๋ณ์ ๋ค์ด๋ฐ ๊ท์น :
Camel Case
- ํ ์ค์ ๊ธ์ ์ :
์ต๋ 80์
- ํ ์ค ์ฃผ์ ํ๊ธฐ :
/* */
- ์ฌ๋ฌ ์ค ์ฃผ์ ํ๊ธฐ :
/*- * * */
- ์ผํญ์ฐ์ฐ์ ํ๊ธฐ :
alpha = (BooleanExpression) ? beta : gamma
- If๋ฌธ์์ &&, ||' ํ๊ธฐ
if((condition1 && condition2) || (condition3 && condition4) || (condition5 && condition6) { do something(); }
* ํผ๋๋ฐฑ ์์ง์ผ์ : 2022๋ 1์ 22์ผ ~ 2022๋ 1์ 25์ผ
* ํผ๋๋ฐฑ ์ : ์ด 30๊ฐ
- ์๋น์ค ๋ง์กฑ๋ ํ๊ท ์ ์ : 4.23์ (5์ )
- ์คํธ๋ ์ค ํด์ ๋ง์กฑ๋ ์ ์ : 4.2์ (5์ )
- ๊ธ์ ์ ์ธ ํผ๋๋ฐฑ Top3
- ์๋๋ฐฑ์ ๋๋ฆฌ๋ฉด์ ์คํธ๋ ์ค๋ฅผ ํด์ํ๋ค๋ ์์ด๋์ด๊ฐ ์ฐธ์ ํ๊ณ ์ข์๋ค.
- ์๋๋ฐฑ์ ๋๋ฆด ๋, ์๋๋ฐฑ์ด ๋ง๋ ๋ชจ์ ๊ณผ ํจ๊ป ํ๊ฒฉ๊ฐ์ด ์์ด์ ์ฌ๋ฏธ์์๋ค.
- ๊ฐ๋จํ๊ฒ ์ด์ฉํ ์ ์๊ณ ์ธํฐํ์ด์ค๊ฐ ์ต์ํ๋ฉด์ ํธํ๋ค.
- ๊ฐ์ ์ ๋ํ ํผ๋๋ฐฑ Top3
- ์ผ๋ถ ํ์ด์ง์์ ํ๋จ ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ๋ณด์ฌ์ง์ง ์์ ๋ถํธํ๋ค. (๋ค๋น๊ฒ์ด์ ๋ฐ๋ฅผ ๋ชจ๋ ํ์ด์ง์์ ๋ณผ ์ ์๋๋ก ๊ฐ์ ์๋ฃ)
- ์ฑํ ์ ์ด๋จ ๋ ์ด์ฉํ ์ ์๋์ง ๋ชจ๋ฅด๊ฒ ๋ค. (์ฑํ ๋ฉ๋ด์์ ์ด์ฉ์๋ด ๊ฐ์ด๋๋ฅผ ๋ณผ ์ ์๋๋ก ๊ฐ์ ์๋ฃ)
- ์ฒซ ํ๋ฉด์ด ๋ก๊ทธ์ธ์ด๋ผ์, ๋ก๊ทธ์ธ์ ํ์ง ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ํ ์ ์๋ค. (๊ฒ์๊ธ ์กฐํ๋ ๋ก๊ทธ์ธ์ ํ์ง ์์๋ ๋๋๋ก ๊ฐ์ ์๋ฃ)
* ๋ฐ์นญ์ผ์ : 2022๋ 01์ 22์ผ(ํ )
* ์ฑ๊ณผ ์ง๊ณ์ผ์ : 2022๋ 01์ 27์ผ(๋ชฉ) 15:00
- 3์ผ๊ฐ ์ธ์คํ๊ทธ๋จ ๊ด๊ณ ์งํ์ ํตํด ์ฝ 2๋ง๋ช ์๊ฒ ๋๋ฌํ์์ผ๋ฉฐ ์ด ์ค, 182๋ช ์ด ์ฌ์ดํธ์ ๋ฐฉ๋ฌธํ์์
- ๋ฐฉ๋ฌธ์ ์ค ์ฝ 67%๋ ์ฌ์ฑ์ด์์
- ๋ฐฉ๋ฌธ์ ์ค ์ฝ 91%๋ 13-17์ธ์ ์ฐ๋ น์ธต์ด์์
- Okky, ๋ฝ๋ฟ ๊ฐ๋ฐ์ํฌ๋ผ์ ํตํด ์๋น์ค ํ๋ณด๋ฅผ ์งํํ์์
- ์ฌ์ฉ์, ์ธ์ ์ ๋ฑ์์ ์ธ์คํ๊ทธ๋จ ๊ด๊ณ ๋ฅผ ํตํ ์ฑ๊ณผ ์งํ๋ณด๋ค ๋์ ์ฑ๊ณผ๋ฅผ ์ป์์
- ๊ฐ์ ํ์ ์ : 141๋ช
- ์์ฑ๋ ์๋๋ฐฑ(๊ฒ์๊ธ) ์ : ์ด 86๊ฐ
- ํฐํธ๋ฆฐ ์๋๋ฐฑ ์ : 36๊ฐ (์ ์ฒด ๋๋น 41.8%)
- ์์ฑ๋ ์ฝ(๋๊ธ) ์ : ์ด 93๊ฐ
- ๊ฐ์ฅ ๋ง์ ์๋๋ฐฑ์ด ์์ฑ๋ ๊ณ ๋ฏผ ์นดํ ๊ณ ๋ฆฌ Top3 : ๊ธฐํ(27๊ฐ), ๊ณต๋ถ(13๊ฐ), ์ง๋ก๊ณ ๋ฏผ(13๊ฐ)
- ๊ธฐ๊ฐ๋์ ์๋๋ฐฑ์ด ๋ง์ ํ์ : ์ด 6,995๋ (1์ธ ํ๊ท 49.6๋)
- ์ฌ์ฉ์ : 741๋ช (First Visit ๊ธฐ์ค)
- Page View : 1๋ง
- ์ด๋ฒคํธ ์ : 1.5๋ง
- ๋ชจ๋ฐ์ผ / PC ๋น์จ : 6.5 / 3.5
- ์ฌ์ฉ์ ์ฌ๋ฐฉ๋ฌธ : 12.6%
* ์ด 154๊ฐ์ ํ ์คํธ ์ฝ๋ ์์ฑ
* 87%์ ์ปค๋ฒ๋ฆฌ์ง ๋ฌ์ฑ
1. ์ ์ฒดDB ์กฐํ ์, ๋ฐํ ์๋๊ฐ ๋๋ฆฐ ๋ฌธ์
๐ ํด๊ฒฐ๋ฐฉ๋ฒ : DB ์ธ๋ฑ์ฑ์ ํตํ data ๋ฐํ ์๋ ํฅ์ (์ด๋น 122๊ฐ ๋ฐํ -> ์ด๋น 486๊ฐ ๋ฐํ)
โ๏ธ ํ์ธ๋ ๊ฐ์ ์ฌํญ
์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ๊ธฐ์ํด spirng data JPA์์ findByUsername๊ณผ findByNickname๊ณผ ๊ฐ์ query method๋ฑ์ ์กฐํ๊ฐ ์ฆ์. Update๋ insert๊ฐ ๋ฐ์ํ๋ ๊ฒ๋ณด๋ค ์กฐํ๊ฐ ๋ง์ด ๋ฐ์ํ๋ค๊ณ ํ๋จ.
ex) ๋ง์ดํ์ด์ง์์ ์ ๋ณด ์์ (๋๋ค์์ด ์๋๋ผ MBTI๋ ์ด๋ฏธ์ง๋ฅผ ๋ณ๊ฒฝ ํ๊ธฐ ์ํด์๋ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์งํ)
ex2) ์ฑํ ๋ชฉ๋ก์ ๋ถ๋ฌ์ค๊ฑฐ๋ ํ์๊ฐ์ ์์๋ ํด๋น query method๋ฅผ ํธ์ถํจ.
indexing์ ํ๊ธฐ์๋ ์์ง ๋ฐ์ดํฐ ํ ์ด๋ธ์ด ํฌ์ง๋ ์์ผ๋, ํ์ฌ DB ํ ์ด๋ธ์์๋ user ํ ์ด๋ธ์ด ๊ฐ์ฅ ํฌ๊ธฐ ๋๋ฌธ์, indexing์ ์ ์ฉํ์ฌ ์ฑ๋ฅ์ ํ์ธํด ๋ณด๊ธฐ๋กํจ.
โ๏ธ ํ ์คํธ ์๋๋ฆฌ์ค
Given: 10000๋ช ์ ํ์์ด DB์ ์ ์ฅ๋์ด ์์.
When: ์ด๋น 10๋ช ์ด ๋์์ ์์ ์ ๋ง์ดํ์ด์ง ์ ๋ณด๋ฅผ ์์ ํจ
Then: DB์ธ๋ฑ์ฑ์ ํด์ค๊ฒ์ด ์๋ ๊ฒฐ๊ณผ ์คํฌ๋ฆฐ ์ฟ๊ณผ ๊ฐ์ด throughput์ด ์ฝ 4๋ฐฐ ๊ฐ์ ๋จ.
2. JPA์์ ๋ฐ์ดํฐ ์กฐํ ์ ๋ฐ์ํ๋ n+1 ๋ฌธ์
โ๏ธ ๋ฌธ์ : Spring Data JPA๋ฅผ ํตํด ๊ฒ์๊ธ ๋ชฉ๋ก์ ์ ์ฒด ์กฐํํ ๊ฒฝ์ฐ, ์ฐ๊ด๊ด๊ณ๊ฐ ์๋ ๋ฐ์ดํฐ๋ค์ด ํ์น ์ ๋ต๊ณผ ์๊ด ์์ด ์ ๋ถ ์ถ๊ฐ๋ก ์กฐํ๋๋ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์
๐ ํด๊ฒฐ๋ฐฉ๋ฒ : @Query๋ฅผ ์ฌ์ฉํ ์ ์ ์ฟผ๋ฆฌ๋ฌธ์ ํ์ด์ง ์ฒ๋ฆฌ๊ฐ ๋์ง ์์์ @EntityGraph๋ก Eager๋ก ๊ฐ์ ธ์์ผ ํ๋๊ฒ๋ง fetch join์ ํด์ฃผ์ด์ ์ฟผ๋ฆฌ๋ฌธ์ด ํ๋ฒ๋ง ์คํ๋๊ฒ ํด์ฃผ์๋ค.
3. ํ
์คํธ์ฝ๋ ์คํ ์, ์ค์ DB๋ก ํ
์คํธ๋ฅผ ์งํํ๋ ๋ฌธ์
โ๏ธ ๋ฌธ์ : ์ค์ ๋ก ์ฌ์ฉํ๋ DB๋ฅผ ํ ์คํธ์์๋ ์ฌ์ฉํ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ์ ์ํฅ์ ๋ฏธ์น ์ ์๊ธฐ ๋๋ฌธ์ Memory DB์์ ํ ์คํธ๋ฅผ ์งํํ์ฌ์ผ ํจ
๐ก To-Be (SpringBootTest ์งํ ์ Test ํจํค์ง์ application.properties์, ๋ฉ๋ชจ๋ฆฌDB ์ฌ์ฉ ์ค์ )
๐ก To-Be (RepositoryTest ์งํ ์, @DataJpaTest ์ด๋ ธํ ์ด์ ์ ํ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌDB ํ๊ฒฝ์์ JPA ๊ด๋ จ Bean๋ค๋ง ์ฃผ์ ๋ฐ์ ํ ์คํธ)
4. ํ์ผ ์
๋ก๋ ์, 1mb ์ด์์ ํ์ผ์ด ์
๋ก๋ ๋์ง ์๋ ๋ฌธ์ (NginX)
โ๏ธ ๋ฌธ์ : 1mb ๋ฏธ๋ง์ ํ์ผ์ ์ ์์ ์ผ๋ก ์ ๋ก๋ ๋์ง๋ง, 1mb ์ด์์ ์ ๋ก๋ ๋์ง ์์
โ ์์ธ : NginX์์ ํ์ผ์ ๋ก๋ ์ฉ๋์ 1mb๋ก ์ ํํด๋์์ (๊ธฐ๋ณธ ์ค์ )
๐ก To-Be (nginx.conf ํ์ผ ์์ ์ ํตํ ์ ๋ก๋ ์ ํ ์ฉ๋ ๋ณ๊ฒฝ)
5. ์ ๋ชฉ, ๋ด์ฉ ๋ฑ์ ๊ธด ๊ธ ์์ฑ์ด ๋์ง ์์ ๊ฒฝ์ฐ
โ ์์ธ : MySql์์ Data Type์ด VARCHAR()๋ก ๋์ด ์์ด์, ๊ธ์์ ์ ํ์ด ์กด์ฌํ์์
6. Travis CI ๋ฅผ ํตํ ๋ฐฐํฌ์๋ํ ์งํ ์, properties ํ์ผ์ ๋ณด์ ์ฒ๋ฆฌ ๋ฌธ์
โ ์์ธ : properties ํ์ผ์ ์ค์ ๊ฐ์ ์ฝ์ด์์ผ ํ๊ธฐ ๋๋ฌธ์, .gitignore์ ์ถ๊ฐํ๋ฉด ์ค์ ์ ์ฝ์ ์ ์์ด ๋น๋๋ฅผ ์คํจํจ
๐ก To-Be (์ํธํ๋ฅผ ํ ํ Travis CI์์ ๋ฐฐํฌ ์ ๋ณตํธํ ํ ์ ์๋๋ก ์ค์ )
travis encrypt-file application.properties --add
7. ๊ฒ์๊ธ, ์ฑํ
์ ์๊ฐ์ด ํ๊ตญ ์๊ฐ๊ณผ 9์๊ฐ ์ฐจ์ด๊ฐ ๋๋ ๋ฌธ์
โ ์์ธ : EC2, RDS์ ์๊ฐ ๊ธฐ๋ณธ๊ฐ์ด UTC(ํ์ ์ธ๊ณ์)์ผ๋ก ์ค์ ๋์ด์๊ธฐ ๋๋ฌธ
๐ก To-Be (EC2 ์๊ฐ๋ ๋ณ๊ฒฝ)
# EC2 ์๊ฐ๋ ๋ณ๊ฒฝ sudo rm /etc/localtime sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime
8. ์น์์ผ ์ฐ๊ฒฐ ์๋ ์ ํ ํฐ ์ธ์ฆ ์๋ฌ๊ฐ ๋๋ ๋ฌธ์
โ ์์ธ : Bearer Token์ ์ฌ์ฉํ ํ Bearer ํ์ ๊น์ง ํฌํจ๋ ํ ํฐ ๋ฌธ์์ด์ ์ธ์ฆํ๋ ค๊ณ ํ์๊ธฐ ๋๋ฌธ
๐ก To-Be (Stomp Interceptor์์ ํ์ ๋ถ๋ถ์ ์๋ผ๋)
String jwtToken = accessor .getFirstNativeHeader("Authorization") .substring(7);
๐ Bearer Token์ ์ฌ์ฉํ ์ด์
# Bearer Token์ ์ ์ A security token with the property that any party in possession of the token (a "bearer") can use the token in any way that any other party in possession of it can. Using a bearer token does not require a bearer to prove possession of cryptographic key material(proof-of-possession). ํ ํฐ์ ์์ ํ ๋ชจ๋ ๋น์ฌ์๊ฐ ํ ํฐ์ ์์ ํ ๋ค๋ฅธ ๋น์ฌ์๊ฐ ํ ์ ์๋ ๋ฐฉ์์ผ๋ก ํ ํฐ์ ์ฌ์ฉํ ์ ์๋ ์์ฑ์ด ์๋ ๋ณด์ ํ ํฐ์ด๋ค. ๋ณด์ ์ ํ ํฐ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ณด์ ์๊ฐ ์ํธํ ํค ์๋ฃ(์์ ์ฆ๋ช )์ ์์ ๋ฅผ ์ฆ๋ช ํ ํ์๊ฐ ์๋ค.
# ์ผ๋ฐ์ ์ผ๋ก ํ ํฐ์ ์์ฒญ ํค๋์ Authorization ํ๋์ ๋ด์์ ธ ๋ณด๋ด์ง๋๋ฐ, Authorization์ ์๋์ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ๊ณ ์๋ค. - Authorization: [type] [credential] - Bearer๋ Authorization Type์ ํ ์ข ๋ฅ๋ก, JWT / OAuth์ ๋ํ ํ ํฐ์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ฃผ๋ก ์ฌ์ฉ๋๋ค.
9. EC2 ์ฉ๋์ ํ ๋ฌธ์ ๋ก ๋ฐฐํฌ๊ฐ ๋์ง ์๋ ๋ฌธ์
โ ์์ธ : EC2์ ์ฉ๋ ๊ธฐ๋ณธ ์ค์ ์ด 8GiB๋ก ์ค์ ๋์ด์์ด์, ์ฉ๋ ๋ถ์กฑ์ผ๋ก Build ํ์ผ์ด ๋ฐฐํฌ๋์ง ์์์
๐ก To-Be
# 1. AWS EC2 ์นํ์ด์ง์์ ์ฉ๋ ์ค์ ๋ณ๊ฒฝํด์ฃผ๊ธฐ (8Gib -? 16GiB) # 2. EC2 Ubuntu์์ ์ฉ๋์ด ํ์ฅ๋ ๋์คํฌ ๋ง์ดํธ ์์ผ์ฃผ๊ธฐ ~$ sudo growpart /dev/xvda 1 # 3. Linux ํ์ผ์์คํ ์์ ๋์คํฌ ํ์ฅ ์ ์ฉ ํ๊ธฐ ~$ sudo resize2fs /dev/xvda1
1. ์๋๋ฐฑ ํด๋ฆญ/ํฐ์น ์ ๋์์ฑ ๋ฌธ์
์๋๋ฐฑ์ ์ฌ๋ฌ ์ ์ ๊ฐ ๋์์ ํด๋ฆญํ ๊ฒฝ์ฐ, ๋์์ฑ ๋ฌธ์ ๋ก ์ธํด hit์๊ฐ ์ ๋๋ก ์ ๋ฐ์ดํธ๊ฐ ๋์ง ์์ ์ ์๊ฒ ๋ค๊ณ ์๊ฐํ์์. ์น์์ผ์ ์ฐ๊ฒฐํ์ฌ, ์ ์ํ ์ ์ ๋ค์ด ์ค์๊ฐ์ผ๋ก ์๋๋ฐฑ์ ํ๊ฒฉ ์๊ฐ ์ฌ๋ผ๊ฐ๋๊ฒ์ ํ์ธํ ์ ์๋๋ก ํ๋ ค๊ณ ํ์์ผ๋ ์๊ฐ ๊ด๊ณ ์ ์ ์ฉํ์ง ๋ชปํ์์.
- ๋์ - ์๋๋ฐฑ์ ์น๋ ค๊ณ ํ์ด์ง์ ์ ์ํ ๋, ๋๋ฆฌ๊ธฐ ์ ๊ณผ ํ์ ํ์๋ฅผ ๋ชจ๋ ์๋ฒ๋ก ์ ์กํ์ฌ ๋ ํ์์ ์ฐจ์ด๋ง ์ ๋ฐ์ดํธ ํ๋๋ก ๋ณด์ํ์์.
2. thandbag์ ๋๋ฆฐ ์ฌ๋์ ๋ญํน ์กฐํ ๊ธฐ๋ฅ
thandbag์ ๋๋ฆฐ ์ ์ ๋ค์ ๋ชฉ๋ก๊ณผ ๋ญํน์ด ์กฐํ ๋๋๋ก ํ๊ฒ ํด๋ฌ๋ผ๋ ๊ธฐ๋ฅ์ด ์ฌ์ฉ์ ํผ๋๋ฐฑ์ผ๋ก ์์ผ๋, ์๋ฒ์ ํ๋ก ํธ์๋ ์์ ๋น ๋ฅด๊ฒ ์ ์ฉํ ์ ์๋ ๊ธฐ๋ฅ์ด ์๋์ฌ์ ์ ์ฉํ์ง ๋ชปํจ.
- ๋ฐฑ์๋์์๋ DB์ ๊ทํ์ API ์ถ๊ฐ ๋ฐ ์์ ๋ฑ์ด ํ์ํ ๊ฒ์ผ๋ก ํ๋จ๋๋ฉฐ,
- ํ๋ก ํธ์๋์์๋ ์๋๋ฐฑ๋๋ฆฌ๊ธฐ ๊ธฐ๋ฅ์ ์น์์ผ์ ์ฌ์ฉํ ์ค์๊ฐ ๊ธฐ๋ฅ์ผ๋ก ์ ๋ฐ์ดํธํด์ผ ํ ๊ฒ์ผ๋ก ํ๋จ๋จ.
3. ๊ธฐํ ๊ณ ๋ ค ์ฌํญ์ด์์ง๋ง ์๊ฐ ๊ด๊ณ์ ์ ์ฉํ์ง ๋ชปํ ์
- ๊ฐ๋ ์ฑ ํฅ์ ๋ฐ ํ์ ์๋ฌ ๋ฐฉ์ง๋ฅผ ์ํด queryDSL ์ ์ฉ
- ์๋ฒ์ ๊ณผํ ์์ฒญ์ผ๋ก ๋ถํ๋ฅผ ์ฃผ๊ธฐ ์ฌ์ด like ์์ฒญ ์ ํ ์ฒ๋ฆฌ(redis ์ฌ์ฉ)
- MSA ์ํคํ ์ณ ์ค๊ณ๋ฐฉ์์ ๋ง์ถฐ ๊ธฐ๋ฅ ๋จ์๋ก ์๋ฒ๋ฅผ ๋๋์ด ์๋ฒ ์์ ์ฑ ๊ฐ์