- ๊ฐ๋ฐ ๊ธฐ๊ฐ : 24.02.26 ~ 24.04.05
- ํ๋ก์ ํธ ์ด๋ฆ : MovieToGather
- ํ๋ก์ ํธ ์ค๋ช : ์ํ๋ฅผ ๋ง์์ด ๋ง๋ ์ฌ๋๋ผ๋ฆฌ ํจ๊ป ์ฆ๊ธฐ๊ธฐ ์ํ ํ๋ซํผ์ ๋๋ค!
- ํ์ฅ ์ค์ฌ์
- github
- ์ญํ
- PM
- ๋ชจ๋ํฐ๋ง ์๋ฒ
- ์ง๋ API
- ํ ์คํธ ์ฝ๋
- ํ๋ก ํธ์๋ ํ๋ฉด ๊ตฌ์ฑ
- ๋ถํ์ฅ ๋ฐ์ฌ์
- github
- ์ญํ
- ๋ฐฑ์๋ ์๋ฒ CI/CD
- ์ํ ๊ฒ์ API
- ํ์ ๊น์ฒ ํ
- github
- ์ญํ
- ์ ๋ฐ์ ์ธ ๊ฒ์ ๊ธฐ๋ฅ
- ๋ฒ ์คํธ ๋ฆฌ๋ทฐ
- ์ข์์ ๊ธฐ๋ฅ
- ์ฑํ
- ํ์ ๊ฐ๊ตฐํธ
- github
- ์ญํ
- ์์ ๋ก๊ทธ์ธ
- ๊ทธ ์ธ ํ์๊ฐ์ ๊ด๋ จ ์ ๋ฐ
- ํ์ ์งํ์
- github
- ์ญํ
- ๋ฆฌ๋ทฐ CRUD
- ๋ชจ์ CRUD
- Spring Boot: 3.2.2
- Kotlin: 1.9.22
- Data
- Spring JPA: 3.2.3
- QueryDsl: 5.0.0
- Security
- Spring Security: 6.2.0
- JWT: io.jsonwebtoken:jjwt-api:0.12.3
- Oauth 2.0
- PostgreSql : 16
- Redis
- Prometheus
- Grafana
- Html5
- CSS
- JavaScript
- Vue.js 3
- Bootstrap
- Quasar
- Git, GitHub Issue, Slack
- Prometheus & Grafana
- ์คํ ์์ค์ธ ์ ์ด ์ค์ํ๊ฒ ์์ฉ
- Spring Actuator์ Spring Metrics์ ์กด์ฌ๋ก ์ฌ์ฉ์ด ํธ๋ฆฌํ ์
- ๋ค์ํ ํํ์ ๋ฉํธ๋ฆญ์ ์์งํ๋ exporter๋ ์ญ์ ์คํ ์์ค์ธ ์
- ์ ์ฅ ๊ณต๊ฐ์ด ๋ชจ์๋ ์์๋ ํ๋์จ์ด ์ฉ๋์ ๋๋ ค์ผ ํ์ง๋ง, ํ์ฌ ํ๋ก์ ํธ์์ ์์ง๋๋ ๋ฉํธ๋ฆญ์ด ์์ด ๊ทธ๋ ๊ฒ ๋ง์ง๋ ์์ ๊ฒ์ด๋ผ๊ณ ํ๋จํ ์
- Spring์์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ Dashboard UI๋ฅผ ์ ๊ณตํ๋ค๋ ์
- Github Actions
- Github ์ ์ฅ์๋ฅผ ์ฌ์ฉํด์จ ์น์ํจ์ด ๊ฐ์ฅ ํฌ๊ฒ ์์ฉ
- ์ถ๊ฐ์ ์ธ ์ค์น ํ์ ์์ด Github ํ๊ฒฝ์์ ์ด์ฉ ๊ฐ๋ฅ
- ํน์ ์ฌ์ฉ๋๊น์ง ๋ฌด๋ฃ๋ก ์ ๊ณต
- Docker
- ๋ฐฐํฌ ํ๋ก์ธ์ค์ ๊ฐ์ํ
- ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ฑ๊ณผ ์ข ์์ฑ์ ์บก์ํํ๊ธฐ ๋๋ฌธ์ ํ๊ฒฝ์ ์ผ๊ด์ฑ์ ๋ณด์ฅํ ์ ์๋ ์
- ํ๋ก์ ํธ์ ์ฌ์ฉํ๋ ๋ฐฑ์๋, ํ๋ก ํธ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋จ์ผ ์๋ฒ์์ ์คํ ๊ฐ๋ฅํ ์
- ๊ฐ์ธ ์ฌ์ฉ์๋ก์ ๋ฌด๋ฃ ๋ฒ์ ํ์ฉ ๊ฐ๋ฅ
- Spring JPA
- MyBatis๋ ์ฟผ๋ฆฌ๋ฌธ์ ์ง์ ์์ฑํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด์ ์ฟผ๋ฆฌ๋ฌธ์ ํจ๊ป ๊ด๋ฆฌํด์ฃผ์ด์ผ ํ๋ ๋ฐ๋ฉด JPA๋ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค์ง ์์๋ ๋๋ค๋ ์
- JPA๋ DTO๊น์ง ์์ ํด์ผ ํ๋ MyBatis์ ๋ฌ๋ฆฌ ๋ฐ์ดํฐ ์ ๋ณด๋ง ๋ฐ๋์ด๋ ๊ฐ์ฒด๋ง ์์ ํด ์ฃผ๋ฉด ๋๋ค๋ ์
- ์๋ฐ ์ง์์์ ์ฌ์ฉํ๋ ํ์ค ORM์ด๋ผ๋ ์
- JPA๋ ๋ณต์กํ ์ฟผ๋ฆฌ๋ฅผ ํด๊ฒฐํ๊ธฐ ํ๋ค์ง๋ง, ์ด๋ฐ JPA์ ๋จ์ ์ QueryDsl๊ฐ์ ๊ธฐ์ ์ด ํด์ํด ์ค ์ ์๋ค๋ ์
- QueryDsl
- QueryDsl๊ณผ Criteria๋ JPQL์ ๋ ์ ์ฌ์ฉํ ์ ์๊ฒ ํด ์ฃผ๊ณ , ์ปดํ์ผ ์์ ์ ์๋ฌ๋ฅผ ๋ฐ์์ํค๊ฒ ํด ์ฃผ๋ JPQL ๋น๋
- Criteria๋ QueryDsl์ ๋นํด ํ์ต ๋์ด๋๋ ๋์ผ๋ฉด์, ์ฝ๋์ ๊ฐ๋ ์ฑ ์ธก๋ฉด์์๋ ์ข์ง ์์ ๋ฟ๋๋ฌ
- ํ์๋ค์ด QueryDsl์ ์ต์ํ ์ํฉ์์ Cretiral์ ํน์ฅ์ ์ ์ฐพ์ง ๋ชปํด์ ์ด์ฉ
- Spring Security
- SecurityContextHolder๋ฅผ ํตํด ์ธ๊ฐ ์ฒ๋ฆฌ๋ฅผ ์์ํ๊ฒ ์งํํ ์ ์๋ ์
- PasswordEncoder๋ฅผ ํตํด ํจ์ค์๋ ์ํธํ๋ฅผ ์์ฝ๊ฒ ๊ตฌํํ ์ ์๋ ์
- JWT
- ์น ํ์ค์ ๋ฐ๋ฅด๊ธฐ ๋๋ฌธ์ ๋ค์ํ ์ธ์ด๋ก ๊ตฌํ์ด ๊ฐ๋ฅ
- Http๋ฅผ Statelessํ๊ฒ ์ ์งํ ์ ์์
- ๋ค๋ฅธ ์ธ์ฆ ๋ฐฉ์์ ๋นํด, ์๋น์ค๋ฅผ ํ์ฅํ๋ ์ธก๋ฉด์์ ์ ๋ฆฌํจ
- PostgreSql
- MySql์ด PostgreSql์ ๋นํด ๋ฐ์ดํฐ ์ฝ๊ธฐ ์ฑ๋ฅ์ ๊ฐ์ ์ด ์์ด ์ฌ์ค MySql์ ์ด์ฉํด๋ ๋๋ ํ๋ก์ ํธ๋ผ๊ณ ์๊ฐ
- ๊ทธ๋ฌ๋ PostgreSql์ ๊ฒฝ์ฐ, ๋๊ท๋ชจ ๋ฐ์ดํฐ ๊ด๋ฆฌ๋ ํธ๋์ญ์ ๋ฑ์ ๊ด๋ฆฌํ๊ธฐ ๋ ์์ํ ๊ฒฝํฅ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์๋น์ค๊ฐ ํ์ฅ๋ ์์ ๋ ์ ๋ฆฌํ ์ธก๋ฉด์ด ์๋ค๊ณ ํ๋จํ์ผ๋ฉฐ
- ํ์๋ค์ด MySql๋ณด๋ค PostgreSql์ ๋ ์ต์ํ ์ํฉ์์ MySql์ ์ฌ์ฉํด์ผ ํ ์ ๋์ ์ฝ๊ธฐ ์ฑ๋ฅ์ด ์๊ตฌ๋์ง๋ ์๋๋ค๊ณ ํ๋จ
- WebSocket
- ์ก์ ๋ง ํ ๊ฒฝ์ฐ HTTP ํ๋กํ ์ฝ์ผ๋ก ์ถฉ๋ถ
- ์ฑํ ์์คํ ์ ์ก์์ ์ด ๋์ด์ผ ๋๊ธฐ๋๋ฌธ์ ํด๋ง, ๋กฑํด๋ง, ์น์์ผ๋ฑ ์์ ํ๋ ๊ธฐ๋ฒ์ ๊ฐ์ด ์ฌ์ฉํด์ผ๋๋ค
- ํด๋ง, ๋กฑํด๋ง์ ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์ ์ ๋ฉ์์ง์ ๋ํ ์์ฒญ์ ๋ณด๋ด๊ณ ์๋ต์ ๋ฐ์ ํ ์ฐ๊ฒฐ์ ์ข ๋ฃํ ๋ค์ ์์ฒญํ์ฌ ๋ฐ๋ณตํ๋ ํ์์ด๋ค
- ์น์์ผ์ ํ๋ฒ ์ฐ๊ฒฐ์ด ๋๋ฉด ํญ๊ตฌ์ ์ด๋ฉฐ ์๋ฐฉํฅ์ผ๋ก ์ฐ๊ฒฐ๋๋ฉด์ ์๋ฒ๋ ํด๋ผ์ด์ธํธ์๊ฒ ๋น๋๊ธฐ์ ์ผ๋ก ๋ฉ์์ง๋ฅผ ์ ์กํ ์ ์๊ฒ ๋๋ค
- ๊ทธ๋์ ์น์์ผ ๋์ HTTP๋ฅผ ์ฌ์ฉํ ์ด์ ๊ฐ ์๋ค๊ณ ์๊ฐ
- RestClient
- ์ด์ ์ ์ฌ์ฉํด์ค๋ HTTP Client ์ธ restTemplate ์ webClient ์ ๋นํ์ฌ ์ฌ์ฉ๋ฐฉ๋ฒ์ด ์ง๊ด์ ์ด๊ณ ๋ค๋ฅธ ์์กด์ฑ์ด ํ์ํ์ง ์์ ๋ฌ๋์ปค๋ธ๊ฐ ์ ์ ์
- Redis
- In-Memory : ๋์คํฌ(DB)๋ฅผ ์กฐํํ๋ ๊ฒ ๋ณด๋ค ๋น ๋ฅธ ์์ ์๋
- Single Thread : ํ๋ก๊ทธ๋จ์ ๋ณต์ก๋๊ฐ ๊ฐ์ํ๊ณ , ์ฑ๋ฅ์ ์ธ ๋ฉด์์๋ ์ ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ณด์กฐ์ ์ธ ์๋จ์ผ๋ก ์ฌ์ฉํ๊ธฐ์๋ ์ข์
- Key : Value ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ๋ค์ํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ง์
- ๋ค์ํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ๊ธฐ๋ฅ ๊ตฌํ์ ์ฅ์ ์ด ์์
- Vue.js
- React.js์ ๋นํด ์๋์ ์ผ๋ก ๋ฌ๋ ์ปค๋ธ๊ฐ ์๋งํ ์
- Thymeleaf์ ๋นํด ๋์ ์ธ ํ๋ฉด ๊ตฌํ์ด ์ฌ์ด ์
- Quasar
- infinite scroll์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๊ธฐ์ ์ด์ฉ
- ๋ค์ํ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ ์ ์๊ณ Vue.js์ ํนํ๋์ด ์์ผ๋ฉฐ ๊ณต์ ๋ฌธ์๊ฐ ์ดํดํ๊ธฐ ์ฝ๊ฒ ์ฐ์ฌ ์๋ ์
- Bootstrap
- ๋ฐฑ์๋ ํ๋ก์ ํธ์ ์ค์๋๋ฅผ ๋๊ฒ ์ก์๊ธฐ์ Vue.js๋ฅผ ์ง์ํ๋ ํ ํ๋ฆฟ์ ์ฌ์ฉ
- ํด๋น ํ ํ๋ฆฟ์ Bootstrap์ด ์ ์ฉ
- CI/CD
- ๋ฌธ์
- ํ์ดํ๋ผ์ธ ๊ตฌ์ถ ์ค, ๋น๋ ๊ณผ์ ์์ contextLoads() ์๋ฌ ๋ฐ์
MovieToGatherApplicationTests > contextLoads() FAILED java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:180 Caused by: io.github.cdimascio.dotenv.DotenvException at DotenvParser.java:76
- ec2 ์ธ์คํด์ค ๋ด์์ ์ง์ ๋น๋ or ๋ก์ปฌ์์ dotenv ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋นํ์ฑํํ์ ๋ -> ๋์ผํ ์๋ฌ ๋ฐ์
- ํ์ดํ๋ผ์ธ ๊ตฌ์ถ ์ค, ๋น๋ ๊ณผ์ ์์ contextLoads() ์๋ฌ ๋ฐ์
- ์์ธ
- ec2 ์ธ์คํด์ค ๋ด์์ ./gradlew bootRun ์คํ ์ ์ ์ ์๋ -> ./gradlew build ์ ./greadlew bootRun์ ์๋ ๋ฐฉ์์ ์ฐจ์ด์ ์์ธ์ด ์์ ๊ฒ์ด๋ผ ์๊ฐํ๊ณ ๊ทธ ์ฐจ์ด๋ฅผ ํ์ต
- ./gradlew build
- resources ๋๋ ํ ๋ฆฌ์ ์๋ ํ์ผ๋ค์ classpath resource๋ก ์ธ์ํ๊ณ ์๋ ๋ก๋
- ./gradlew bootRun
- root ๋๋ ํ ๋ฆฌ๋ฅผ ๊ธฐ์ค์ผ๋ก classpath resource ์ค์
- ํด๊ฒฐ
- .env ํ์ผ์ด ํ๋ก์ ํธ์ root ๋๋ ํ ๋ฆฌ์ ์์นํด ์์๊ณ , ํ์ดํ๋ผ์ธ ๊ณผ์ ์์๋ .env ํ์ผ์ root ๋๋ ํ ๋ฆฌ์ ์์ฑ
- ๊ทธ ๊ฒฐ๊ณผ, build ๊ณผ์ ์ ํ๊ฒฝ ๋ณ์๋ฅผ ๋ก๋ํ์ง ๋ชปํด contextLoads() Failed ๊ฐ ๋ฐ์
- resources ๋๋ ํ ๋ฆฌ ํ์๋ก .env๋ฅผ ์์ฑํ์๊ณ ์ ์ ์คํ ํ์ธ
- ๋ฌธ์
- Oauth2
- ๋ฌธ์
- redirect๋๋ ์์ ์ URI์ ํ ํฐ ์ ๋ณด๊ฐ ๋ ธ์ถ
- ์์ธ
- Implicit Grant Type์ผ๋ก ํ ํฐ ๋ฐํ (Only Oauth 2.0)
- ํ ํฐ์ด ์ธ์ฆ ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก ๋ฆฌํด๋ ๋ QueryString์ผ๋ก ์ ๋ฌ
- ๋คํ์ฑ์ธ ํ ํฐ์ด ํ์ทจ๋๋ฉด ๋ฆฌ์์ค๊น์ง ์ ๊ทผ ๊ฐ๋ฅ
- Implicit Grant Type์ผ๋ก ํ ํฐ ๋ฐํ (Only Oauth 2.0)
- ํด๊ฒฐ
- Oauth 2.0 Grant Type์ Authorization Code Grant Type์ผ๋ก ๋ณ๊ฒฝ
- 1ํ์ฑ Authorization Code ๋ฐํ -> ์ฝ๋๊ฐ ํ๋ ค๋ ์ฆ์ ํ๊ธฐ
- Oauth 2.0 Grant Type์ Authorization Code Grant Type์ผ๋ก ๋ณ๊ฒฝ
- ๋ฌธ์
- WebSocket
- ๋ฌธ์
- WebSocket์ ํตํด message๋ฅผ ์์ฑํด๋ ์๋๋ฐฉ์๊ฒ ์ ๋ฌ์ด ๋์ง์๋ ๋ฌธ์ ๋ฐ์
- ์์ธ
- message ์ ์ก ๊ด๋ จ Handler
- ๋ณธ์ธ์ด ์์ฑํ message์ ๊ดํด ์ค์ O
- ์๋๋ฐฉ์๊ฒ ์ ๋ฌํ๋ ์ค์ X
- message ์ ์ก ๊ด๋ จ Handler
- ํด๊ฒฐ
- chat ์
์ฅํ๊ฒ ๋๋ฉด ํด๋น ๋ฐฉ์ session์ ์ถ๊ฐ๋๋๋ก ๋ณ๊ฒฝ
- WebSocketSession์ ์ด์ฉํ์ฌ session ๊ตฌํ
- message ์ ์กํ์๋ ํด๋น ๋ฐฉ์ ์๋ ๋ชจ๋ session๋ค์๊ฒ ์ ๋ถ ์ ์ก
- chat ์
์ฅํ๊ฒ ๋๋ฉด ํด๋น ๋ฐฉ์ session์ ์ถ๊ฐ๋๋๋ก ๋ณ๊ฒฝ
- ๋ฌธ์
- ํ์๊ฐ์ /๋ก๊ทธ์ธ/์ ์ ์ ๋ณด ํ์ธ
- Spring Security ํ์ฉ
- ์์ ๋ก๊ทธ์ธ๋ง์ผ๋ก ํ์ ๊ด๋ฆฌ ์งํ
- ๊ตฌ๊ธ / ์นด์นด์ค / ๋ค์ด๋ฒ ๋ก๊ทธ์ธ
- ๋ฆฌ๋ทฐ Best 3
- ๋ฆฌ๋ทฐ ๊ฒ์ํ๊ธฐ
- ๋ฆฌ๋ทฐ ์์ฑ/์์ /์ญ์ ํ๊ธฐ
- ๋ฆฌ๋ทฐ ์์ฑ ์ ์ํ ๊ฒ์
- ๋ชจ์ ๊ฒ์ํ๊ธฐ
- ๋ชจ์ ์์ฑ/์์ /์ญ์ ํ๊ธฐ
- ๊ฐ์ ๋ชจ์์๋ค๋ผ๋ฆฌ ์ฑํ ํ๊ธฐ