Skip to content

JoSihun/AI-Prompt-Quiz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation


๐Ÿ“† ๊ธฐ๊ฐ„

2024.04.08~2024.05.17

๐Ÿ’– ํ”„๋กœ์ ํŠธ ๊ธฐํš

  • ํ˜„๋Œ€ ์‚ฌํšŒ์—์„œ๋Š” ์ƒ์„ฑํ˜• AI์˜ ์‚ฌ์šฉ์ด ์ฆ๊ฐ€ํ•จ์— ๋”ฐ๋ผ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์— ๋”ฐ๋ผ ์ƒ์„ฑ๋˜๋Š” ๊ฒฐ๊ณผ๋ฌผ์ด ๋งค์šฐ ๋‹ค์–‘ํ•ด์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ ํ”„๋กฌํ”„ํŠธ ์—”์ง€๋‹ˆ์–ด๋ง ๊ต์œก๋„ ํ™•๋Œ€๋˜๊ณ  ์žˆ์œผ๋ฉฐ, ํ”„๋กฌํ”„ํŠธ์˜ ๋ฏธ๋ฌ˜ํ•œ ์ฐจ์ด๋ฅผ ์ดํ•ดํ•˜๊ณ  ์ค„์ด๋Š” ๊ธฐ์ˆ ์ด ์ค‘์š”์‹œ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋Ÿฌํ•œ ์‚ฌํšŒ์  ํ๋ฆ„ ์†์—์„œ, ๊ฐœ๋ฐœ์— ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค๋„ ํ”„๋กฌํ”„ํŠธ์˜ ์„ธ๋ถ€์ ์ธ ์ฐจ์ด๋ฅผ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒŒ์ž„ ๊ธฐ๋ฐ˜์˜ ํ•™์Šต ํ”Œ๋žซํผ์„ ๋งŒ๋“ค๊ณ ์ž ํ•ด๋‹น ํ”„๋กœ์ ํŠธ๋ฅผ ๊ธฐํšํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’• ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

  • ์‚ฌ์šฉ์ž๋“ค์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ•จ๊ป˜ ๊ฒŒ์ž„์„ ํ•˜๋ฉด์„œ ์ƒ์„ฑํ˜• AI๊ฐ€ ๋งŒ๋“  ์ด๋ฏธ์ง€์˜ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋งž์ถœ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒŒ์ž„์€ ๊ฐ๊ด€์‹๊ณผ ์ฃผ๊ด€์‹ ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์œผ๋กœ ๋‚˜๋‰˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฃผ๊ด€์‹ ๊ฒŒ์ž„์—์„œ๋Š” ์‹œ๊ฐ„์ด ๊ฒฝ๊ณผํ•˜๋ฉด ์ดˆ์„ฑ ํžŒํŠธ๊ฐ€ ์ œ๊ณต๋˜์–ด ์ •๋‹ต์„ ๋” ์‰ฝ๊ฒŒ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ฐ ์ž…๋ ฅ๋งˆ๋‹ค ์œ ์‚ฌ๋„๊ฐ€ ์ œ๊ณต๋˜์–ด ์ •ํ™•๋„๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ „์ฒด ์‚ฌ์šฉ์ž๋Š” ์ž์‹ ์ด ์ฐธ์—ฌํ•œ ๊ฒŒ์ž„์—์„œ ๋žญํ‚น ์ ์ˆ˜๋ฅผ ๋ถ€์—ฌ๋ฐ›์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐœ์ธ ์ ์ˆ˜์— ๋”ฐ๋ฅธ ์ˆœ์œ„๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…์„ ํ†ตํ•ด ๋‹จ์ˆœํžˆ ํ˜ผ์ž ์ฆ๊ธฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋“ค๊ณผ ํ•จ๊ป˜ ์†Œํ†ตํ•˜๋ฉฐ ๊ฒŒ์ž„์„ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๐Ÿƒ ๊ฐœ๋ฐœ ์ธ์›

์„œ๋‹ค์ฐฌ (ํŒ€์žฅ) ๊น€์˜์šฑ ์กฐ์‹œํ›ˆ ์„œํ•ด๊ด‘ ์œ ์ง€์›… ์ด๋ฏผ์šฐ

๋ฐฑ์—”๋“œ

๋ฐฑ์—”๋“œ

๋ฐฑ์—”๋“œ & ์ธํ”„๋ผ

ํ”„๋ก ํŠธ์—”๋“œ

ํ”„๋ก ํŠธ์—”๋“œ

ํ”„๋ก ํŠธ์—”๋“œ & ๋ฐฑ์—”๋“œ

๐Ÿ’› ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

  • Front : React, TypeScript
  • Back-end : Spring Boot, JPA, FastAPI, Uvicorn, Mysql, InfluxDB, Redis
  • ๋ฒ„์ „๊ด€๋ฆฌ : Gitlab
  • ํ˜‘์—… ํˆด : Notion, Jira
  • ๋ฐฐํฌ : Jenkins, Docker
  • ๋ชจ๋‹ˆํ„ฐ๋ง : Grafana, Prometheus

๋นŒ๋“œ ๋ฐฉ๋ฒ•

1. Spring Boot

  • ๋นŒ๋“œ
$ ./gredlew build
  • ์‹คํ–‰
$ java -jar build.jar

2. FastAPI

  • ํŒจํ‚ค์ง€ ๋‹ค์šด๋กœ๋“œ
$ pip install -r requirements.txt
  • ์‹คํ–‰
$ uvicorn chatdaAPI.main.app:app --host 0.0.0.0 --reload

3. React

  • ํŒจํ‚ค์ง€ ๋‹ค์šด๋กœ๋“œ
$ npm i
  • ๋นŒ๋“œ
$ npm run build

๐Ÿ’š ์ปค๋ฐ‹ ์ปจ๋ฒค์…˜

prefix ์„ค๋ช…
feat ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์ถ”๊ฐ€
fix ๋ฒ„๊ทธ ์ˆ˜์ •
docs ๋ฌธ์„œ ์ˆ˜์ •
style ์ฝ”๋“œ ํฌ๋งทํŒ…, ์„ธ๋ฏธ์ฝœ๋ก  ๋ˆ„๋ฝ, ์ฝ”๋“œ ๋ณ€๊ฒฝ์ด ์—†๋Š” ๊ฒฝ์šฐ
refactor ์ฝ”๋“œ ๋ฆฌํŽ™ํ† ๋ง
test ํ…Œ์ŠคํŠธ ์ฝ”๋“œ, ๋ฆฌํŽ™ํ† ๋ง ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€
chore ๋นŒ๋“œ ์—…๋ฌด ์ˆ˜์ •, ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € ์ˆ˜์ •
etc ๊ธฐํƒ€ ์—…๋ฌด

๐Ÿ’œERD

A509_ERD_V0.0.5.png

๐Ÿ–คAPI ๋ช…์„ธ์„œ

image.png

๐Ÿ’› ์†Œ์ผ“ ์—ฐ๊ฒฐ Dto

dsf.png

๐Ÿ’š ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

image-1.png

๐Ÿ’› ๊ธฐ๋Šฅ๋ณ„ ์†Œ๊ฐœ

๋กœ๊ทธ์ธ

๋กœ๊ทธ์ธ

์ฑ„ํŒ…

์ฑ„ํŒ…

๊ฒŒ์ž„๋ฐฉ ์ƒ์„ฑ

๊ฒŒ์ž„๋ฐฉ์ƒ์„ฑ

๊ฐ๊ด€์‹

๊ฐ๊ด€์‹

์‹œ์ž‘

์‹œ์ž‘

์ฃผ๊ด€์‹

์ฃผ๊ด€์‹

๋ผ์šด๋“œ ์ค€๋น„ ํƒ€์ด๋จธ

ํƒ€์ด๋จธ

๐Ÿ’™ ๋ฒ„๊ทธ ๋ฆฌํฌํŠธ

1. DB ์ตœ์ ํ™”

  • ์ดˆ๊ธฐ ํ”„๋กœ์ ํŠธ ์„ค๊ณ„์‹œ ๊ฒŒ์ž„๊ณผ ๊ด€๋ จ๋œ ๋ฐ์ดํ„ฐ๋Š” Redis๋กœ ๊ด€๋ฆฌํ•˜๋ฉฐ ์กฐํšŒ ์†๋„๋ฅผ ํ–ฅ์ƒ์‹œํ‚ค๊ณ  ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚ฌ์„๋•Œ ์‚ญ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ Redis์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒ๋ฅผ ํ•จ์— ์žˆ์–ด Key-value๊ฐ€ ์•„๋‹Œ ๋ณ„๋„์˜ Indexed๋ฅผ ํ†ตํ•ด ์ปฌ๋Ÿผ์„ ์ง€์ •ํ•ด์„œ ์กฐํšŒํ•ด์•ผํ•˜๋Š” ์ƒํ™ฉ์ด ๋Š˜์–ด๋‚ฌ๊ณ  ํ•ด๋‹น ๋ฌธ์ œ ๋•Œ๋ฌธ์— ๊ฒŒ์ž„๋ฐฉ ์ƒ์„ฑ ์‹œ๊ฐ„์ด ์ง€์—ฐ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฒŒ์ž„์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํ•„์š”ํ•œ ํ€ด์ฆˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•จ์— ์žˆ์–ด ํ•œ ๊ฒŒ์ž„์— ๋งŽ๊ฒŒ๋Š” 200๊ฐœ์˜ ํ€ด์ฆˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด insert์‹œ๊ฐ„์€ 200๊ฐœ ๊ธฐ์ค€ 50์ดˆ์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค.

  • ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ธฐ์กด์— Redis๋กœ ์ €์žฅํ•œ ๋ฐ์ดํ„ฐ ์ค‘ RDB๋กœ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ๋“ค์€ RDB๋กœ ๋ถ„๋ฆฌ๋ฅผ ์‹œ์ผœ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ตœ์ ํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋กœ์จ 200๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ• ๋•Œ ๊ธฐ์กด 50์ดˆ์˜ ์‹œ๊ฐ„์ด 2์ดˆ์˜ ์‹œ๊ฐ„์œผ๋กœ ๊ฐ์†Œํ•˜๋Š” ์ด์ ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์ดˆ๊ธฐ์—๋Š” Redis๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ์ดํ„ฐ๋Š” Memory์—์„œ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๊ธฐ์— ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ ๋น ๋ฅผ ๊ฒƒ์ด๋ผ ์˜ˆ์ƒํ–ˆ์—ˆ์ง€๋งŒ ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ• ๋•Œ๋Š” RDB๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ์ ์œผ๋กœ ์šฐ์ˆ˜ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

2. ์†Œ์ผ“ ์„ธ์…˜ ๊ด€๋ฆฌ

  • ์†Œ์ผ“ ์—ฐ๊ฒฐ๊ณผ ๊ด€๋ จํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ ๊ธฐ์กด์—๋Š” ํ”„๋ก ํŠธ์—”๋“œ์—์„œ 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());
        }
    }

About

AI-Prompt-Quiz

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •