- ํ๋ ์ฌํ์์๋ ์์ฑํ AI์ ์ฌ์ฉ์ด ์ฆ๊ฐํจ์ ๋ฐ๋ผ ํ๋กฌํํธ ์ ๋ ฅ์ ๋ฐ๋ผ ์์ฑ๋๋ ๊ฒฐ๊ณผ๋ฌผ์ด ๋งค์ฐ ๋ค์ํด์ง๊ณ ์์ต๋๋ค. ์ด์ ๋ฐ๋ผ ํ๋กฌํํธ ์์ง๋์ด๋ง ๊ต์ก๋ ํ๋๋๊ณ ์์ผ๋ฉฐ, ํ๋กฌํํธ์ ๋ฏธ๋ฌํ ์ฐจ์ด๋ฅผ ์ดํดํ๊ณ ์ค์ด๋ ๊ธฐ์ ์ด ์ค์์๋๊ณ ์์ต๋๋ค.
- ์ด๋ฌํ ์ฌํ์ ํ๋ฆ ์์์, ๊ฐ๋ฐ์ ์ต์ํ์ง ์์ ์ฌ๋๋ค๋ ํ๋กฌํํธ์ ์ธ๋ถ์ ์ธ ์ฐจ์ด๋ฅผ ๋ณด๋ค ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ํ๋ ๊ฒ์ ๊ธฐ๋ฐ์ ํ์ต ํ๋ซํผ์ ๋ง๋ค๊ณ ์ ํด๋น ํ๋ก์ ํธ๋ฅผ ๊ธฐํํ์ต๋๋ค.
- ์ฌ์ฉ์๋ค์ด ์ค์๊ฐ์ผ๋ก ํจ๊ป ๊ฒ์์ ํ๋ฉด์ ์์ฑํ AI๊ฐ ๋ง๋ ์ด๋ฏธ์ง์ ํ๋กฌํํธ๋ฅผ ๋ง์ถ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- ๊ฒ์์ ๊ฐ๊ด์๊ณผ ์ฃผ๊ด์ ๋ ๊ฐ์ง ์ ํ์ผ๋ก ๋๋์ด ์์ต๋๋ค. ์ฃผ๊ด์ ๊ฒ์์์๋ ์๊ฐ์ด ๊ฒฝ๊ณผํ๋ฉด ์ด์ฑ ํํธ๊ฐ ์ ๊ณต๋์ด ์ ๋ต์ ๋ ์ฝ๊ฒ ์ ์ถํ ์ ์์ต๋๋ค. ๋ํ ๊ฐ ์ ๋ ฅ๋ง๋ค ์ ์ฌ๋๊ฐ ์ ๊ณต๋์ด ์ ํ๋๋ฅผ ํ์ ํ ์ ์์ต๋๋ค.
- ์ ์ฒด ์ฌ์ฉ์๋ ์์ ์ด ์ฐธ์ฌํ ๊ฒ์์์ ๋ญํน ์ ์๋ฅผ ๋ถ์ฌ๋ฐ์ ์ ์์ผ๋ฉฐ ๊ฐ์ธ ์ ์์ ๋ฐ๋ฅธ ์์๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
- ์ค์๊ฐ ์ฑํ ์ ํตํด ๋จ์ํ ํผ์ ์ฆ๊ธฐ๋ ๊ฒ์ด ์๋๋ผ ๋ค๋ฅธ ์ฌ์ฉ์๋ค๊ณผ ํจ๊ป ์ํตํ๋ฉฐ ๊ฒ์์ ์งํํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค.
์๋ค์ฐฌ (ํ์ฅ) | ๊น์์ฑ | ์กฐ์ํ | ์ํด๊ด | ์ ์ง์ | ์ด๋ฏผ์ฐ |
---|---|---|---|---|---|
๋ฐฑ์๋ |
๋ฐฑ์๋ |
๋ฐฑ์๋ & ์ธํ๋ผ |
ํ๋ก ํธ์๋ |
ํ๋ก ํธ์๋ |
ํ๋ก ํธ์๋ & ๋ฐฑ์๋ |
- Front : React, TypeScript
- Back-end : Spring Boot, JPA, FastAPI, Uvicorn, Mysql, InfluxDB, Redis
- ๋ฒ์ ๊ด๋ฆฌ : Gitlab
- ํ์ ํด : Notion, Jira
- ๋ฐฐํฌ : Jenkins, Docker
- ๋ชจ๋ํฐ๋ง : Grafana, Prometheus
- ๋น๋
$ ./gredlew build
- ์คํ
$ java -jar build.jar
- ํจํค์ง ๋ค์ด๋ก๋
$ pip install -r requirements.txt
- ์คํ
$ uvicorn chatdaAPI.main.app:app --host 0.0.0.0 --reload
- ํจํค์ง ๋ค์ด๋ก๋
$ npm i
- ๋น๋
$ npm run build
prefix | ์ค๋ช |
---|---|
feat | ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ |
fix | ๋ฒ๊ทธ ์์ |
docs | ๋ฌธ์ ์์ |
style | ์ฝ๋ ํฌ๋งทํ , ์ธ๋ฏธ์ฝ๋ก ๋๋ฝ, ์ฝ๋ ๋ณ๊ฒฝ์ด ์๋ ๊ฒฝ์ฐ |
refactor | ์ฝ๋ ๋ฆฌํํ ๋ง |
test | ํ ์คํธ ์ฝ๋, ๋ฆฌํํ ๋ง ํ ์คํธ ์ฝ๋ ์ถ๊ฐ |
chore | ๋น๋ ์ ๋ฌด ์์ , ํจํค์ง ๋งค๋์ ์์ |
etc | ๊ธฐํ ์ ๋ฌด |
- ์ด๊ธฐ ํ๋ก์ ํธ ์ค๊ณ์ ๊ฒ์๊ณผ ๊ด๋ จ๋ ๋ฐ์ดํฐ๋ Redis๋ก ๊ด๋ฆฌํ๋ฉฐ ์กฐํ ์๋๋ฅผ ํฅ์์ํค๊ณ ์ผ์ ์๊ฐ์ด ์ง๋ฌ์๋ ์ญ์ ๊ฐ ๋ ์ ์๋๋ก ์ค๊ณ๋ฅผ ํ์ต๋๋ค.
- ํ์ง๋ง Redis์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํ๋ฅผ ํจ์ ์์ด Key-value๊ฐ ์๋ ๋ณ๋์ Indexed๋ฅผ ํตํด ์ปฌ๋ผ์ ์ง์ ํด์ ์กฐํํด์ผํ๋ ์ํฉ์ด ๋์ด๋ฌ๊ณ ํด๋น ๋ฌธ์ ๋๋ฌธ์ ๊ฒ์๋ฐฉ ์์ฑ ์๊ฐ์ด ์ง์ฐ๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.
- ๊ฒ์์ ์งํํ๋ฉด์ ํ์ํ ํด์ฆ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํจ์ ์์ด ํ ๊ฒ์์ ๋ง๊ฒ๋ 200๊ฐ์ ํด์ฆ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด insert์๊ฐ์ 200๊ฐ ๊ธฐ์ค 50์ด์ ์๊ฐ์ด ๊ฑธ๋ ธ์ต๋๋ค.
- ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ๊ธฐ์กด์ Redis๋ก ์ ์ฅํ ๋ฐ์ดํฐ ์ค RDB๋ก ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ค์ RDB๋ก ๋ถ๋ฆฌ๋ฅผ ์์ผ ๋ฐ์ดํฐ ๋ฒ ์ด์ค ์ต์ ํ ์์ ์ ์ํํ์ต๋๋ค.
- ์ด๋ก์จ 200๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ ๊ธฐ์กด 50์ด์ ์๊ฐ์ด 2์ด์ ์๊ฐ์ผ๋ก ๊ฐ์ํ๋ ์ด์ ์ ๊ฐ์ ธ์ฌ ์ ์์์ต๋๋ค.
- ์ด๊ธฐ์๋ Redis๋ก ๊ด๋ฆฌํ๋ ๋ฐ์ดํฐ๋ Memory์์ ์ง์ ๊ด๋ฆฌํ๊ธฐ์ ๋ฌด์กฐ๊ฑด์ ์ผ๋ก ๋น ๋ฅผ ๊ฒ์ด๋ผ ์์ํ์์ง๋ง ๊ด๊ณ๊ฐ ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ ๋๋ RDB๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ฑ๋ฅ์ ์ผ๋ก ์ฐ์ํ๋ค๋ ๊ฒ์ ๊นจ๋ฌ์ ์ ์์์ต๋๋ค.
- ์์ผ ์ฐ๊ฒฐ๊ณผ ๊ด๋ จํ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ฉฐ ๊ธฐ์กด์๋ ํ๋ก ํธ์๋์์ disconnect() ํจ์๋ง์ผ๋ก ์ฐ๊ฒฐ์ด ๋๊ฒผ์๋ ๊ธฐ์กด ์ธ์ ๊ฐ์ ์ญ์ ํ๋ ๋ฐฉ์์ผ๋ก ๊ด๋ฆฌ๋ฅผ ํ์ต๋๋ค.
- ํ์ง๋ง ๋ง์ฝ ์์ผ ์ฐ๊ฒฐ์ด ๋น์ ์์ ์ผ๋ก ์ข ๋ฃ๋๋ ๊ฒฝ์ฐ(์๋ก๊ณ ์นจ, ์ฐฝ๋ซ๊ธฐ) ์ด๋ฌํ disconnectํจ์๊ฐ ํธ์ถ๋์ง ์๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํด ์ธ์ ์ ๋ณด๊ฐ ๋จ์์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
public disconnect(): void {
if (this.client !== null) {
this.client.deactivate();
console.log('WebSocket disconnected');
}
}
- ๋๋ฌธ์ ๊ธฐ๋ณธ ์ธ์ ์ฐ๊ฒฐ์ ์ฒ์ ์๋ํ ๋ ๋๋คํ๊ฒ ๋ฐ๊ธ๋๋ sessionID์ userId๋ฅผ ๋งคํํ ํ ์ด๋ธ์ ์์ฑํ๊ณ ์ฌ์ฉ์์ ๋์(๊ฒ์๋ฐฉ ์ ์ฅ, ์ฑ๋ ์ ์ฅ ๋ฑ)์ ๋ฐ๋ผ ์ธ์ ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์๋๋ก Spring์์ event listener๋ฅผ ๊ตฌํํ์ต๋๋ค.
@EventListener
public void handleWebSocketConnectListener(SessionConnectedEvent event) {
logger.info("Received a new web socket connection(event: " + event + ")");
String sessionId = parsingSessionIdFromEvent(event);
socketService.addSession(sessionId);
}
@EventListener
public void handleWebSocketSubscribeListener(SessionSubscribeEvent event) {
logger.info("Received a new web socket subscribe(event: " + event + ")");
String sessionId = parsingSessionIdFromEvent(event);
SocketEventUrlParser parser = new SocketEventUrlParser(parsingUrlFromEvent(event));
if (parser.isOk()) {
socketService.editSession(sessionId, parseUserId(event), parser.getUuid(), parser.getType());
} else {
logger.info("destination format does not match.");
}
}
@EventListener
public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
logger.info("Received a web socket disconnection(event: " + event + ")");
try{
String sessionId = parsingSessionIdFromEvent(event);
socketService.kickOutUser(sessionId);
socketService.deleteSession(sessionId);
}catch (Exception e){
logger.debug("Socket Disconnect Exception : " + e.getMessage());
}
}