๐ŸšŒCINE-VERSE๐ŸŽฅ ํ”„๋กœ์ ํŠธ

๐ŸšํŒ€๋ช…: ์‹œ๋‚ด๋ฒ„์Šค

๐ŸšŒํŒ€์›

  • ํŒ€์› : ์†ก๋™์ค€

  • ํŒ€์› : ์–‘์ง€ํ˜œ

  • ํŒ€์› : ์œค์žฌ์€

  • ํŒ€์› : ์กฐ์ˆ˜๋นˆ


๊ธฐ์ˆ  ์Šคํƒ

SpringBoot MariaDB Spring Data JPA Jenkins Kubernetes Docker ngrok
SpringBoot MariaDB SpringDataJPA Jenkins Kubernetes Docker ngrok
Python JavaScript Vue HTML CSS
Python JavaScript Vue.js HTML5 CSS3

๊ฐœ๋ฐœ ๋„๊ตฌ

IntelliJ IDEA Visual Studio Code HeidiSQL Visily Miro Github AWS S3
IntelliJ IDEA Visual Studio Code HeidiSQL Visily Miro GitHub AWS S3

๐Ÿ“Œ์˜ํ™” ๋งˆ๋‹ˆ์•„๋“ค์„ ์œ„ํ•œ ์ „๋ฌธ ์ปค๋ฎค๋‹ˆํ‹ฐ ์„œ๋น„์Šค ๊ธฐํš์„œ

1. ์„œ๋น„์Šค ๊ธฐํš ๋ฐฐ๊ฒฝ

  • ํ˜„ ์ƒํ™ฉ:
    ๋งˆ๋‹ˆ์•„๋ฅผ ์œ„ํ•œ ์˜ํ™” ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๋ถ€์žฌ.
    ๋Œ€ํ˜• ํ”Œ๋žซํผ์˜ ์˜ํ™” ์นดํŽ˜๋Š” ๋Œ€๋ถ€๋ถ„ ํ์‡„๋˜์—ˆ๊ณ , ๊ธฐ์กด ์‚ฌ์ดํŠธ๋“ค์€ ํ™”๋ฉด์ด ๋ณต์žกํ•˜๊ณ  ๋‹ค์–‘ํ•œ ์ฃผ์ œ๋ฅผ ์•„์šฐ๋ฅด๊ณ  ์žˆ์–ด ์˜ํ™”๋งŒ์„ ์ „๋ฌธ์œผ๋กœ ๋‹ค๋ฃจ๋Š” ๊ณต๊ฐ„์ด ํ•„์š”.
  • ํ•„์š”์„ฑ:
    ์˜ํ™” ๋งˆ๋‹ˆ์•„๋“ค์ด ์ž์‹ ์˜ ์˜ํ™” ์ทจํ–ฅ์„ ๊ณต์œ ํ•˜๊ณ , ์‹ฌ๋„ ๊นŠ์€ ํ† ๋ก ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์ „๋ฌธ ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ํ•„์š”์„ฑ์ด ๋Œ€๋‘๋จ.

2. ์„œ๋น„์Šค ๋ชฉํ‘œ

  • ์ „๋ฌธ์„ฑ๊ณผ ํŽธ์•ˆํ•จ:
    ์˜ํ™”๋งŒ์„ ์ „๋ฌธ์œผ๋กœ ๋‹ค๋ฃจ๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ ์ œ๊ณต์œผ๋กœ ์‚ฌ์šฉ์ž๋“ค์ด ๋ณด๋‹ค ์‰ฝ๊ฒŒ ์ •๋ณด๋ฅผ ์–ป๊ณ  ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซํผ ๋งˆ๋ จ.
  • ์•ˆ์ „ํ•œ ์ด์šฉ ํ™˜๊ฒฝ:
    ์„œ๋ฒ„์— ์œ„ํ—˜ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๊ณ , ์ด์šฉ์ž์˜ ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ๋ฅผ ์ตœ์šฐ์„ ์œผ๋กœ ํ•จ(์˜ˆ: ์ฟ ํ‚ค์— ํšŒ์›๋“ค์˜ ๊ฐœ์ธ์ •๋ณด๋ฅผ ๋‹ด์ง€ ์•Š์Œ).
  • ํ™œ๋ฐœํ•œ ์†Œํ†ต ๊ณต๊ฐ„:
    ์‚ฌ์šฉ์ž๋“ค์ด ์ž์œ ๋กญ๊ฒŒ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๊ณ , ์˜ํ™”์— ๋Œ€ํ•œ ๋ฆฌ๋ทฐ๋‚˜ ๋น„ํ‰์„ ์ž์œ ๋กญ๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ์˜คํ”ˆํ˜• ์ปค๋ฎค๋‹ˆํ‹ฐ.

3. ์„œ๋น„์Šค ์ฐจ๋ณ„ํ™” ์ „๋žต

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

4. ๊ธฐ๋Œ€ ํšจ๊ณผ

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

์ด๋Ÿฌํ•œ ์‚ฌ์ดํŠธ๋Š” ์˜ํ™” ๋งˆ๋‹ˆ์•„๋“ค์—๊ฒŒ ๋งž์ถคํ™”๋œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์•ˆ์ „ํ•˜๊ณ  ํŽธ์•ˆํ•œ ํ™˜๊ฒฝ์—์„œ ์˜ํ™”์— ๋Œ€ํ•œ ์—ด์ •์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์ ์˜ ๊ณต๊ฐ„์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ‡ด๊ทผ ํ›„ ๐ŸšŒ์‹œ๋‚ด๋ฒ„์Šค ํƒ€๊ณ  ๐ŸŽฅ์˜ํ™” ํ•œ ํŽธ ์–ด๋•Œ์š”?


๐Ÿ“‹์„ค๊ณ„๋ฌธ์„œ

์ƒ์„ธ๋ณด๊ธฐ

๐ŸŒ€์ผ์ • ๊ด€๋ฆฌ

WBS


๐Ÿ“DDD

1. Domain event

2. Command

3. Actor

4. Aggregate

5. Bounded context

6. Context mapping

7. ์ค‘๊ฐ„๊ฐ์ฒด ์—ฐ๊ฒฐ



โš™DB๋ชจ๋ธ๋ง

1. ๊ฐœ๋…๋ชจ๋ธ๋ง

2. ๋…ผ๋ฆฌ๋ชจ๋ธ๋ง

3. ๋ฌผ๋ฆฌ๋ชจ๋ธ๋ง



๐Ÿ’ป์™€์ด์–ด ํ”„๋ ˆ์ž„

1. ๋ฉ”์ธ - ํšŒ์› ๊ด€๋ จ ํŽ˜์ด์ง€ (๋กœ๊ทธ์ธ)

2. ๋ฉ”์ธ - ํšŒ์›ํ”„๋กœํ•„ ๋ฐ ๋ฑƒ์ง€ ํŽ˜์ด์ง€

3. ๋ฉ”์ธ - ์ตœ์‹  ์ด๋ฒคํŠธ, ์ž์œ  ๊ฒŒ์‹œ๊ธ€

4. ๋ฉ”์ธ - ๊ฒŒ์‹œํŒ

5. ์ด๋ฒคํŠธ ๊ฒŒ์‹œํŒ

6. ๋ฆฌ๋ทฐ ๊ฒŒ์‹œํŒ

7. ์ •๋ณด ๊ฒŒ์‹œํŒ

8. ์ž์œ  ๊ฒŒ์‹œํŒ

9. ๋ฌธ์˜ ๊ฒŒ์‹œํŒ



๐Ÿ“š๊ธฐ๋Šฅ/์š”๊ตฌ์‚ฌํ•ญ/ํ…Œ์ŠคํŠธ ๋ช…์„ธ์„œ

1. ๊ธฐ๋Šฅ ๋ช…์„ธ์„œ

2. ์š”๊ตฌ์‚ฌํ•ญ ์ •์˜์„œ

3. ํ…Œ์ŠคํŠธ ๋ช…์„ธ์„œ



๐Ÿ…ฐApi ๋ช…์„ธ์„œ

1. ๋ฆฌ๋ทฐ(๊ฒŒ์‹œ๊ธ€, ๋Œ“๊ธ€)

Swagger Editor_page-0001

2. ์‹ ๊ณ , ํฌ์ธํŠธ, ํšŒ์›

Swagger Editor_page-0002

3. ์ •๋ณด(๊ฒŒ์‹œ๊ธ€, ๋Œ“๊ธ€), ์ž์œ (๊ฒŒ์‹œ๊ธ€, ๋Œ“๊ธ€)

Swagger Editor_page-0003

4. ์ž์œ (๊ฒŒ์‹œ๊ธ€), ์ด๋ฒคํŠธ(๊ฒŒ์‹œ๊ธ€), ์ด๋ฉ”์ผ, ๋ฑƒ์ง€

Swagger Editor_page-0004

5. ๊ฒŒ์‹œ๊ธ€ ์ข‹์•„์š”

Swagger Editor_page-0005

6. ์Šคํ‚ค๋งˆ

Swagger Editor_page-0006 Swagger Editor_page-0007



โœ”๋ฐฑ์—”๋“œ ํ…Œ์ŠคํŠธ

1. ํšŒ์›

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ10

2. ์ •๋ณด ๊ฒŒ์‹œ๊ธ€

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ8

3. ์ •๋ณด ๊ฒŒ์‹œ๊ธ€ ๋Œ“๊ธ€

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ9

4. ์ž์œ  ๊ฒŒ์‹œ๊ธ€

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ7

5. ์ž์œ  ๊ฒŒ์‹œ๊ธ€ ๋Œ“๊ธ€

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ6

6. ๋ฆฌ๋ทฐ ๊ฒŒ์‹œ๊ธ€

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ1

7. ๋ฆฌ๋ทฐ ๊ฒŒ์‹œ๊ธ€ ๋Œ“๊ธ€

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ2

8. ์ด๋ฒคํŠธ ๊ฒŒ์‹œ๊ธ€

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ4

9. ๋ฑƒ์ง€

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ3

10. ์‹ ๊ณ 

๋ฐฑ์—”๋“œํ…Œ์ŠคํŠธ4


๐ŸณCICD ์•„ํ‚คํ…์ฒ˜



๐Ÿ“Ž์ „์ œ ์กฐ๊ฑด ๋ฐ ์„ค์น˜ ํ™˜๊ฒฝ

์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋‹ค์Œ ์†Œํ”„ํŠธ์›จ์–ด์™€ ๋„๊ตฌ๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • IntelliJ: JDK 17 ์„ค์น˜ ํ•„์š”
  • Docker: ๋ฒ„์ „ 4.28
  • Jenkins: ๋ฒ„์ „ 2.452
  • Kubernetes: ๋ฒ„์ „ 1.92.2
  • Ngrok
  • Webhook: GitHub์™€ ์—ฐ๋™ ์„ค์ •


๐Ÿ”งCredential ์„ค์ •

์•ˆ์ „ํ•œ ๊ฐœ๋ฐœ์„ ์œ„ํ•ด ๋‹ค์Œ ํฌ๋ฆฌ๋ด์…œ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  1. MY-GITHUB-KEY: RSA ํ‚ค
  2. DOCKERHUB-PASSWORD: Docker Hub ์—…๋กœ๋“œ๋ฅผ ์œ„ํ•œ ๊ณ„์ • ์ •๋ณด
  3. SECRET-ID: GitHub์— ์—…๋กœ๋“œ๋˜๋ฉด ์•ˆ ๋˜๋Š” application.yml


๐Ÿ”—Jenkins Pipeline ์„ค์ •

Git ์ €์žฅ์†Œ์™€ Webhook ์—ฐ๊ฒฐ

  • ๋ณ€๊ฒฝ์‚ฌํ•ญ ๊ฐ์ง€ ํ›„ Jenkins๊ฐ€ ์ž๋™์œผ๋กœ ๋นŒ๋“œ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

RSA ํ‚ค ์ƒ์„ฑ

  • Jenkins๊ฐ€ Webhook์„ ํ†ตํ•ด ๋ณ€๊ฒฝ๋œ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , SSH์— ์‚ฌ์šฉ๋  RSA ํ‚ค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

Pipeline ์ƒ์„ฑ ๋ฐ ์„ค์ •

  • Jenkins Tools์—์„œ Java (OpenJDK 17) ๋ฐ Gradle (ver 8.7) ์„ค์ •

Plugin ์„ค์น˜

  • Publish Over SSH ๋ฐ Pipeline: Stage View ์„ค์น˜

Pipeline ์Šคํฌ๋ฆฝํŠธ

์ค‘์š”์ฝ”๋“œ
pipeline {
    agent any
    tools {
        gradle 'gradle'
        jdk 'openJDK17'
    }
    environment {
        DOCKERHUB_USERNAME = 'angelajsb'
        GITHUB_URL = 'https://github.com/beyond-sw-camp/be04-4th-6team-CINE-VERSE-CICD.git'
    }
    stages {
        stage('Preparation') {
            steps {
                script {
                    sh 'docker --version' // Docker๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
                }
            }
        }
        stage('Source Build') {
            steps {
                git branch: 'main', url: 'https://github.com/beyond-sw-camp/be04-4th-6team-CINE-VERSE-CICD.git'
                
                withCredentials([file(credentialsId: 'secret-id', variable: 'applicationYml')]) {
                    script {
                        if (fileExists('src/main/resources/application.yml')) {
                            sh 'rm src/main/resources/application.yml' // ํŒŒ์ผ์ด ์กด์žฌํ•˜๋ฉด ์‚ญ์ œ
                        }
                        sh "cp $applicationYml src/main/resources/application.yml"
                    }
                }
                
                sh "chmod +x ./gradlew"
                sh "./gradlew clean build"
            }
        }
        stage('Container Build') {
            steps {
                sh "cp ./build/libs/*.jar ."
    
                sh "docker build -t ${DOCKERHUB_USERNAME}/cine-verse:latest ."

                withCredentials([usernamePassword(credentialsId: 'DOCKERHUB_PASSWORD', usernameVariable: 'DOCKERHUB_USER', passwordVariable: 'DOCKERHUB_PASS')]) {
                    sh "echo $DOCKERHUB_PASS | docker login --username $DOCKERHUB_USER --password-stdin"
                    sh "docker push ${DOCKERHUB_USERNAME}/cine-verse:latest"
                }
            }
        }
    }
}

Jenkins Pipeline ์‹คํ–‰ ๊ณผ์ •

  1. ๋ณ€๊ฒฝ ์ฝ”๋“œ GitHub์— ์—…๋กœ๋“œ
  2. Webhook ํ†ตํ•ด ๋ณ€ํ™” ๊ฐ์ง€
  3. ๊ฐ์ง€๋œ ์ฝ”๋“œ๋ฅผ SSH๋ฅผ ํ†ตํ•ด ๋ณด์•ˆ ์ƒํƒœ๋กœ Jenkins์—์„œ ํด๋ก 
  4. ์‚ฌ์ „์— Credential์— ๋“ฑ๋กํ•œ application.yml์„ Pipeline ์Šคํฌ๋ฆฝํŠธ์— ์ž‘์„ฑ๋œ Groovy ๋ฌธ๋ฒ•์„ ํ†ตํ•ด ๋‹ค์šด๋กœ๋“œ
  5. ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ ์‹คํ–‰(์ž๋™ํ™” ๊ณผ์ •)
  6. ๋นŒ๋“œ๋œ JAR ํŒŒ์ผ์„ ํ†ตํ•ด ์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ›„ Docker Hub์— ํ‘ธ์‹œ

deployment.yml ์ƒ์„ฑ

yml ๋‚ด์šฉ
apiVersion: apps/v1
kind: Deployment
metadata:
  name: boot002dep
spec:
  selector:
    matchLabels:
      app: boot002kube
  replicas: 3
  template:
    metadata:
      labels:
        app: boot002kube
    spec:
      containers:
        - name: boot-container
          image: angelajsb/cine-verse:latest    # DockerHub์— ํ‘ธ์‰ฌ๋œ ๊ฐ€์žฅ ์ตœ๊ทผ image ์‚ฌ์šฉ
          imagePullPolicy: Always    
          ports:
            - containerPort: 8081        # ํ˜„์žฌ boot project ํฌํŠธ๋ฒˆํ˜ธ

service.yml

yml ๋‚ด์šฉ
apiVersion: v1
kind: Service
metadata:
  name: boot002ser
spec:
  type: NodePort
  ports:
    - port: 8081                        # container ๋‚ด๋ถ€ ํ†ต์‹  ํฌํŠธ๋ฒˆํ˜ธ
      targetPort: 8081                  # ํ˜„์žฌ service ์ค‘์ธ ํฌํŠธ๋ฒˆํ˜ธ
      protocol: TCP
      nodePort: 30007                   # ์™ธ๋ถ€ ์ ‘์† ํฌํŠธ๋ฒˆํ˜ธ
  selector:
    app: boot002kube

Kubernetes

  1. deployment.yml -> pod๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์ •๋ณด ์ •์˜
  2. replicas -> ์„ค์ •ํ•œ ๊ฐฏ์ˆ˜์— ๋”ฐ๋ผ pod instance ์œ ์ง€, ๊ณผ๋ถ€ํ•˜๊ฐ€ ๊ฑธ๋ฆฌ๊ฑฐ๋‚˜ ์‹คํŒจํ•œ pod๋ฅผ ์ž๋™ ์žฌ์‹œ์ž‘ ํ•ด ํ•ญ์ƒ n๊ฐœ์˜ pods ์œ ์ง€
  3. service.yml -> pod์— ๋Œ€ํ•œ ๋‹จ์ผ ์ ‘์  ์ œ๊ณต ๋ฐ ๋‚ด๋ถ€์ ์œผ๋กœ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ ์ˆ˜ํ–‰
  4. deployment.yml ๋ฐ service.yml ์ ์šฉ kubectl apply -f boot002dep.yml kubectl apply -f boot002ser.yml
  5. ์†Œ์Šค์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ Kubernetes ์žฌ์‹œ์ž‘ kubectl rollout restart deployment/boot002dep

Vue CI/CD

  1. ์ „์ œ ์กฐ๊ฑด ๋ฐ ์„ค์น˜ ํ™˜๊ฒฝ

    1. VS CODE ์„ค์น˜
    2. VUE3 ์„ค์น˜
    3. Docker Desktop ์„ค์น˜
  2. vue project ๊ฒฝ๋กœ ํ„ฐ๋ฏธ๋„์—์„œ ํ•ด๋‹น project image ์ƒ์„ฑ

docker build -t angelajsb/cine-verse-front .
  1. DockerHub์— ํ•ด๋‹น image ํ‘ธ์‰ฌ
docker push angelajsb/cine-verse-front
  1. deployment.yml ์ƒ์„ฑ

  2. service.yml ์ƒ์„ฑ

  3. deployment.yml ๋ฐ service.yml ์ ์šฉ (๋ช…๋ น์–ด ์ž…๋ ฅ)

kubectl apply -f vue002dep.yml
kubectl apply -f vue002ser.yml
  1. ์†Œ์Šค์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ ์ด๋ฏธ์ง€ ์žฌ์ƒ์„ฑ ํ›„ DockerHub ํ‘ธ์‰ฌ
docker build -t angelajsb/cine-verse-front:latest .
docker push angelajsb/cine-verse-front:latest
  1. Kubernetes ์žฌ์‹œ์ž‘
kubectl rollout restart deployment/vue002dep


โœ…์ถ”๊ฐ€ ๊ธฐ๋Šฅ ์„ค๋ช…์„œ

1. CGV ์‹ค์‹œ๊ฐ„ ์ธ๊ธฐ ์˜ํ™” ์ˆœ์œ„ ํฌ๋กค๋ง

Python์„ ์‚ฌ์šฉํ•˜์—ฌ requests์™€ BeautifulSoup ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ CGV์—์„œ ์˜ํ™” ๋ฐ์ดํ„ฐ(์‹ค์‹œ๊ฐ„ ์ธ๊ธฐ ์˜ํ™” ์ˆœ์œ„ 10)๋ฅผ ํฌ๋กค๋งํ•˜๊ณ  json์œผ๋กœ ์ €์žฅ ๋ฉ”์ธ ํ™”๋ฉด์— ๋“ค์–ด๊ฐ€๋ฉด ์‚ฌ์šฉ์ž๋Š” ์‹ค์‹œ๊ฐ„ ์˜ํ™” ์ •๋ณด๋ฅผ ํ†ตํ•ด ์ตœ์‹  ํŠธ๋ Œ๋“œ๋ฅผ ํŒŒ์•… ๊ฐ€๋Šฅ

์ค‘์š”์ฝ”๋“œ
url = 'http://www.cgv.co.kr/movies/'
res = requests.get(url)
soup = BeautifulSoup(res.text, 'html.parser')

2. OpenAI API๋ฅผ ์ด์šฉํ•œ ์ฑ—๋ด‡ ๋งŒ๋“ค๊ธฐ

API request ์กฐํšŒ ๊ฐ€๋Šฅ

JavaScript๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ OpenAI์˜ API๋กœ๋ถ€ํ„ฐ ์ฑ—๋ด‡์˜ ์‘๋‹ต์„ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„ api ํ‚ค๋Š” .env ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜์ง€ ์•Š๋„๋ก ๋ณด์•ˆ ์ฒ˜๋ฆฌ ์˜ํ™” ์ถ”์ฒœ ๋“ฑ ๋‹ค์–‘ํ•œ ์ฃผ์ œ์— ๋Œ€ํ•œ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธ ๋Œ€ํ™” ๊ฐ€๋Šฅ https://platform.openai.com/usage์—์„œ API request ์กฐํšŒ ๊ฐ€๋Šฅ

์ค‘์š”์ฝ”๋“œ
async function sendMessage() {
  const message = userMessage.value.trim();
  if (message.length === 0) return;

3. S3 ์„œ๋ฒ„ ์ด์šฉํ•œ ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ

Java์™€ Spring Boot๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ AWS S3์— ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์•ˆ์ •์ ์ธ AWS S3๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๋Œ€์šฉ๋Ÿ‰ ์ด๋ฏธ์ง€ ์ €์žฅ ๋ฐ ๊ด€๋ฆฌ ์šฉ์ดํ•˜๊ณ , ๋ฐ์ดํ„ฐ ๋ณด์•ˆ ๊ฐ•ํ™”

์ค‘์š”์ฝ”๋“œ
@Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withRegion(region)
                .build();
    }

try {
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentType(multipartFile.getContentType());
            objectMetadata.setContentLength(multipartFile.getInputStream().available());

            amazonS3Client.putObject(bucketName, storedName, multipartFile.getInputStream(), objectMetadata); 

            String accessUrl = amazonS3Client.getUrl(bucketName, storedName).toString();
            image.setAccessUrl(accessUrl);
            imageRepository.save(image); 
        }

4. SMTP๋ฅผ ํ™œ์šฉํ•œ ์ธ์ฆ ์ด๋ฉ”์ผ ๋ฐœ์†ก ๋ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ

SMTP๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์˜ ์ด๋ฉ”์ผ๋กœ ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ • ์ธ์ฆ์šฉ ๋‚œ์ˆ˜๋ฅผ ๋ณด๋‚ด๊ณ  ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ ๊ตฌํ˜• ์ด๋ฉ”์ผ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์•ˆ์ „ํ•˜๊ฒŒ ์ž์‹ ์˜ ๊ณ„์ •์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์‹ ๋ขฐ์„ฑ์ด ํ–ฅ์ƒ

์ค‘์š”์ฝ”๋“œ
public EmailMessage sendMail(EmailMessage emailMessage) {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8");

            String newPwd = createRandom();
            mimeMessageHelper.setTo(emailMessage.getTo());
            mimeMessageHelper.setSubject("๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ •");
            mimeMessageHelper.setText("์žฌ์„ค์ •๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ: " + newPwd);
            mimeMessageHelper.setFrom(new InternetAddress(from));

            javaMailSender.send(mimeMessage);
            memberService.changePwd(newPwd, emailMessage.getTo());

            emailMessage.setMessage("์žฌ์„ค์ •๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ: " + newPwd);
            emailMessage.setSubject("๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ •");

            return emailMessage;
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }


โœจ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ์˜์ƒ

1๏ธโƒฃ ๋ฉ”์ธํŽ˜์ด์ง€ etc
1-1. ๋ฉ”์ธํŽ˜์ด์ง€ ๋ผ์šฐํ„ฐ
1-2. ๋ฉ”์ธํŽ˜์ด์ง€ ์ธ๊ธฐ ์˜ํ™” ์ˆœ์œ„
1-3. ์ตœ์‹  ์ด๋ฒคํŠธ/์ž์œ  ๊ฒŒ์‹œ๊ธ€
2๏ธโƒฃ ์ฑ—๋ด‡

์ฑ—๋ด‡-ํ…Œ์ŠคํŠธ

3๏ธโƒฃ ํšŒ์› etc
3-1. ํšŒ์›๊ฐ€์ž…

ํšŒ์›๊ฐ€์ž…-ํ…Œ์ŠคํŠธ

3-2. ์•„์ด๋””, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ฐพ๊ธฐ
3-3. ๋กœ๊ทธ์ธ ๋กœ๊ทธ์•„์›ƒ

๋กœ๊ทธ์ธ๋กœ๊ทธ์•„์›ƒ-ํ…Œ์ŠคํŠธ

3-4. ํšŒ์›์ •๋ณด ์ˆ˜์ •

ํšŒ์›์ •๋ณด์ˆ˜์ •-ํ…Œ์ŠคํŠธ

3-5. ํšŒ์›ํ”„๋กœํ•„ ํ™•์ธ

์œ ์ €ํ”„๋กœํ•„-ํ…Œ์ŠคํŠธ

3-6. ํšŒ์› ํƒˆํ‡ด
4๏ธโƒฃ ๋ฑƒ์ง€

๋ฑƒ์ง€-ํ…Œ์ŠคํŠธ

5๏ธโƒฃ ์ •๋ณด ๊ฒŒ์‹œํŒ etc
5-1. ์ •๋ณด(์ž์œ ) ๊ฒŒ์‹œ๊ธ€ ์ „์ฒด/๋‹จ์ผ ์กฐํšŒ

๊ฒŒ์‹œ๊ธ€ ์ „์ฒด ์กฐํšŒ ๋‹จ์ผ ์กฐํšŒ

5-2. ์ •๋ณด ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ

์ •๋ณด ๊ฒŒ์‹œ๋ฌผ ์ž‘์„ฑ

5-3. ์ •๋ณด ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ

์ •๋ณด ๊ฒŒ์‹œ๋ฌผ ์‚ญ์ œ

5-4. ์ •๋ณด ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰

์ •๋ณด ๊ฒŒ์‹œ๋ฌผ ๊ฒ€์ƒ‰

6๏ธโƒฃ ์ž์œ  ๊ฒŒ์‹œํŒ etc
6-1. ์ž์œ  ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ

์ž์œ  ๊ฒŒ์‹œ๋ฌผ ์ž‘์„ฑ

6-2. ์ž์œ  ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ

์ž์œ ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ

6-3. ์ž์œ  ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰

์ž์œ  ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰

7๏ธโƒฃ ์ด๋ฒคํŠธ ๊ฒŒ์‹œํŒ etc
7-1. ์ด๋ฒคํŠธ ๊ฒŒ์‹œ๊ธ€ ์ด๋™ ์ „์ฒด ์กฐํšŒ ๋‹จ์ผ ์กฐํšŒ

์ด๋ฒคํŠธ ๊ฒŒ์‹œ๊ธ€ ์ด๋™ ์ „์ฒด ์กฐํšŒ ๋‹จ์ผ ์กฐํšŒ

7-2. ์ด๋ฒคํŠธ ๊ฒŒ์‹œํŒ ์ž‘์„ฑ

์ด๋ฒคํŠธ ์ž‘์„ฑ

7-3. ์ด๋ฒคํŠธ ๊ฒŒ์‹œํŒ ์‚ญ์ œ

์ด๋ฒคํŠธ ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ

7-4. ์ด๋ฒคํŠธ ๊ฒŒ์‹œํŒ ์ฐธ์—ฌ

์ด๋ฒคํŠธ ์ฐธ์—ฌ

8๏ธโƒฃ ๋Œ“๊ธ€ etc
8-1. ๋Œ“๊ธ€ ์ž‘์„ฑ

๋Œ“๊ธ€ ์ž‘์„ฑ

8-2. ๋Œ“๊ธ€ ์‚ญ์ œ

๋Œ“๊ธ€ ์‚ญ์ œ

๐ŸŒ๊ณ ๋„ํ™” ์˜ˆ์ • ๊ธฐ์ˆ 

  1. ์ด๋ฒคํŠธ ๊ฒŒ์‹œํŒ ํˆฌํ‘œ ๊ตฌํ˜„
  2. spring security ์ ์šฉ
  3. redis๋ฅผ ํ†ตํ•œ ์ด๋ฉ”์ผ ์ธ์ฆ
  4. ๋Œ“๊ธ€ ์ด๋ชจํ‹ฐ์ฝ˜ ๊ตฌํ˜„
  5. ์Šคํฌ์ผ๋Ÿฌ ๋ฐฉ์ง€ ๊ตฌํ˜„
  6. ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •(ํ”„๋ก ํŠธ)
  7. ํšŒ์›์‹ ๊ณ 
  8. qna

โœํ”„๋กœ์ ํŠธ ํšŒ๊ณ 

์ด๋ฆ„ ๋‚ด์šฉ
์†ก๋™์ค€ ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„  ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์› ๋˜ ์ง€์‹๋“ค์„ ๋ฐ”ํƒ•์œผ๋กœ DDD๋กœ ๊ฒŒ์‹œํŒ ์„œ๋น„์Šค ๊ตฌ์กฐ ๋“ฑ์„ ๊ธฐํšํ•˜๊ณ  DB ๋ชจ๋ธ๋ง ์™€์ด์–ด ํ”„๋ ˆ์ž„ ๋“ฑ์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ๊ตฌ์กฐ ์ธํ„ฐํŽ˜์ด์Šค ๋””์ž์ธ์„ ์„ค๊ณ„ํ•œ ํ›„ ๋ฐฑ ์•ค๋“œ์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋ฉด ํ”„๋ŸฐํŠธ์—”๋“œ์—์„œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๋’ค CI/CD๋กœ ๋ฐฐํฌ๊นŒ์ง€ ํ•˜๋Š” ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•˜์˜€๋‹ค ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ์งง์€ ์‹œ๊ฐ„ ๋‚ด์— ๊ฒŒ์‹œ๋ฌผ์„ ๊ตฌํ˜„ํ•ด์•ผ ํ–ˆ๊ธฐ์— ์‹œ๊ฐ„์  ๋ถ€๋‹ด๊ฐ๋„ ์žˆ์—ˆ์œผ๋‚˜ ์˜ค๋ž˜๋ผ์„œ ์ต์ˆ™์ง€ ์•Š์€ ๋ถ€๋ถ„์„ ๋ณต์Šตํ•  ์ˆ˜ ์žˆ์–ด ๊ท€์ค‘ํ•œ ๊ฒฝํ—˜์ด ๋˜์—ˆ๋‹ค ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋ฉด์„œ ๋งŽ์ด ๋ถ€์กฑํ•จ์„ ๋Š๊ผˆ์œผ๋‚˜ ๋” ์ž˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ž์‹ ๊ฐ์ด ์ƒ๊ธฐ๊ณ  ๋งŽ์€ ๊ฒƒ์„ ์–ป์–ด ๊ฐ„ ํ”„๋กœ์ ํŠธ์˜€๋‹ค ๋‹ค์Œ ํ”„๋กœ์ ํŠธ๋Š” ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์„ ๋ณด์™„ํ•˜๊ณ  ๋ฐฑ์—”๋“œ์™€ ํ”„๋ŸฐํŠธ์—”๋“œ์˜ ์›ํ™œํ•œ ์˜์‚ฌ์†Œํ†ต์„ ํ†ตํ•ด ๋” ํšจ์œจ์ ์ด๊ณ  ์ •ํ™•ํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด์•ผ๊ฒ ๋‹ค.
์–‘์ง€ํ˜œ ์‚ฌ์šฉ์ž ์ค‘์‹ฌ ์„ค๊ณ„(UCD)์˜ ์ค‘์š”์„ฑ์„ ๊ณ ๋ คํ•˜๋ฉด์„œ, ์‚ฌ์šฉ์ž์˜ ๋งŒ์กฑ์„ ์šฐ์„ ์œผ๋กœ ์ƒ๊ฐํ•˜๋Š” ์„œ๋น„์Šค ๊ฐœ๋ฐœ์˜ ํ•„์š”์„ฑ์„ ๋”์šฑ ๊นŠ์ด ์ดํ•ดํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ธฐํš - ์™€์ด์–ดํ”„๋ ˆ์ž„ - ํ”„๋ก ํŠธ์—”๋“œ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์น˜๋ฉฐ ์—ฌ๋Ÿฌ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณธ ๊ฒฐ๊ณผ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์Œ“์ด๊ณ , ์‚ฌ์šฉ์ž์˜ ํŽธ์˜๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ๊ธฐํš ๋ฐ ๊ตฌ์ƒํ•˜๋Š” ๋‹จ๊ณ„๊ฐ€ ์ฆ๊ฒ๊ฒŒ ๋‹ค๊ฐ€์™”์Šต๋‹ˆ๋‹ค. ์งง์€ ๊ธฐ๊ฐ„ ๋™์•ˆ ๋งŽ์€ ์ž‘์—…์„ ํ•ด์•ผ ํ•˜๋Š” ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ํŒ€์›๋“ค๊ณผ ๋งค์ผ ์ง„ํ–‰ํ•œ ๊ฐœ๋ฐœ ์ง„์ฒ™๋„ ์ฒดํฌ๋ฅผ ํ†ตํ•ด ํ”„๋กœ์ ํŠธ์˜ ์ผ์ •์„ ๊ด€๋ฆฌํ•˜๊ณ , ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ์ฆ‰์‹œ ํ•ด๊ฒฐ์ฑ…์„ ๋ชจ์ƒ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด ์–ป์€ ๋‹ค์–‘ํ•œ ํ”ผ๋“œ๋ฐฑ ๊ฒฝํ—˜์€ ์•ž์œผ๋กœ ๋‹ค๋ฅธ ์„œ๋น„์Šค๋ฅผ ๊ธฐํšํ•˜๊ณ  ๊ฐœ๋ฐœํ•  ๋•Œ ํฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ฒ˜์Œ์œผ๋กœ ํ”„๋ŸฐํŠธ์— ๋ฐฑ์—”๋“œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์˜€๊ณ , ํ”„๋ŸฐํŠธ์˜ ๋ ˆ์ด์•„์›ƒ ๋ฐ ๋ฐ˜์‘ํ˜• ์ฒ˜๋ฆฌ์— ์„ฑ๊ณตํ–ˆ์„ ๋•Œ ๋ˆ„๊ตฌ๋ณด๋‹ค ๋ฟŒ๋“ฏํ•จ์„ ๋Š๊ผˆ์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ๋„ ์‚ฌ์šฉ์ž์˜ ํŽธ์˜์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ์ข€ ๋” ์„ฑ์‹คํ•˜๊ฒŒ ์„œ๋น„์Šค๋ฅผ ๊ธฐํš ๋ฐ ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
์œค์žฌ์€ ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ์ €ํฌ ํŒ€์˜ ์ฃผ๋œ ๋ชฉํ‘œ๋Š” ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•œ ํ›„ Jenkins, Kubernetes, ๊ทธ๋ฆฌ๊ณ  Ngrok์„ ์ด์šฉํ•ด CI/CD ํ™˜๊ฒฝ์„ ์กฐ์„ฑํ•˜์—ฌ ์ž๋™์ ์ธ ๋นŒ๋“œ์™€ ๋ฐฐํฌ๊ฐ€ ์ด๋ฃจ์–ด์ง€๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์ด์ „ ํ”„๋กœ์ ํŠธ์—์„œ ์‹œ๋„ํ•˜์ง€ ๋ชปํ–ˆ๋˜ S3 ๋ฒ„ํ‚ท์„ ํ†ตํ•œ ํŒŒ์ผ ์—…๋กœ๋“œ์™€ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„์™€ ํ”„๋ก ํŠธ ์„œ๋ฒ„ ๊ฐ„์˜ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์˜€์Šต๋‹ˆ๋‹ค.
ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„ ๋™์•ˆ ๋งค์ผ ์•„์นจ ์Šคํฌ๋Ÿผ ํšŒ์˜๋ฅผ ํ†ตํ•ด ํŒ€์›๋“ค๊ณผ ๊ฐ์ž ๋งก์€ ๋ถ€๋ถ„์— ๋Œ€ํ•œ ํ˜„์žฌ ์ง„ํ–‰ ์ƒํ™ฉ์„ ๊ณต์œ ํ•˜๊ณ , ์•ž์œผ๋กœ์˜ ๊ณ„ํš๊ณผ ๋ฐฉํ–ฅ์„ฑ์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜๋ฉฐ ์ผ์ •์„ ์กฐ์œจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋น„๋ก ๊ฐœ์ธ์˜ ์ง„ํ–‰ ์ƒํ™ฉ์— ๋”ฐ๋ฅธ ์–ด๋ ค์›€๋„ ์žˆ์—ˆ์ง€๋งŒ, ์ง€์†์ ์ธ ๋Œ€ํ™”๋ฅผ ํ†ตํ•ด ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•ด ๋‚˜๊ฐˆ ์ˆ˜ ์žˆ์—ˆ๊ณ , ์ด ๊ณผ์ •์—์„œ ์†Œํ†ต์˜ ์ค‘์š”์„ฑ์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ๊นจ๋‹ซ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
๋ฐฑ์—”๋“œ์˜ ์ „๋ฐ˜์ ์ธ ๊ตฌํ˜„์„ ๋งก์œผ๋ฉด์„œ, ์ด์ „์— ์‹œ๋„ํ•ด๋ณด์ง€ ๋ชปํ–ˆ๋˜ SMTP๋ฅผ ์‚ฌ์šฉํ•œ ๋ฉ”์ผ ๋ฐœ์†ก, S3 ๋ฒ„ํ‚ท์„ ์ด์šฉํ•œ ํŒŒ์ผ ์—…๋กœ๋“œ ๋“ฑ์„ ํ•˜๋‚˜์”ฉ ํ•ด๊ฒฐํ•ด ๋‚˜๊ฐ”์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ธฐ๋Šฅ๋“ค์„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ํ•˜๋‚˜์”ฉ ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉฐ ํฐ ์„ฑ์ทจ๊ฐ์„ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐฑ์—”๋“œ์—์„œ ๋งŒ๋“ค์–ด์ง„ ๊ธฐ๋Šฅ๋“ค์„ ํ”„๋ก ํŠธ์— ์ ์šฉํ•˜์ง€ ๋ชปํ•œ ๋ถ€๋ถ„๊ณผ Redis๋ฅผ ์‚ฌ์šฉํ•œ ์ด๋ฉ”์ผ ์ธ์ฆ์„ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ•จ์—์„œ ์•„์‰ฌ์›€์ด ๋‚จ์ง€๋งŒ ์ด๋ฏธ ๊ตฌํ˜„๋œ ๊ธฐ๋Šฅ๋“ค์€ ํ–ฅํ›„ ๊ณ ๋„ํ™” ๊ณผ์ •์—์„œ ์‰ฝ๊ฒŒ ์ ์šฉ๋  ์ˆ˜ ์žˆ์„๊บผ๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  Redis๋ฅผ ํ™œ์šฉํ•œ ์ด๋ฉ”์ผ ์ธ์ฆ์€ ์ถ”ํ›„ ๊ณ ๋„ํ™” ๊ณผ์ •์—์„œ์˜ ์ƒˆ๋กœ์šด ๋ชฉํ‘œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ ํฌ๋ง์„ ๋Š๋‚๋‹ˆ๋‹ค.
ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด ์•„ํ‚คํ…์ฒ˜๋ฅผ MSA๋กœ ๋‚˜๋ˆ„์ง€ ์•Š๊ณ  ๋ชจ๋†€๋ฆฌ์‹ ๋ฐฉ์‹์œผ๋กœ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ JPA๋งŒ์„ ์‚ฌ์šฉํ•ด ๋ณธ ํ›„ ์ด ๊ฒฝํ—˜์„ ํ†ตํ•ด Spring bootํ™˜๊ฒฝ์˜ ์ „๋ฐ˜์ ์ธ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์„ ๋ณต์Šตํ•  ์ˆ˜ ์žˆ์—ˆ์œผ๋ฉฐ, MyBatis์™€ JPA์˜ ์žฅ๋‹จ์ , ๋ชจ๋†€๋ฆฌ์‹ ์„œ๋น„์Šค์™€ MSA์˜ ์žฅ๋‹จ์ ์„ ์ง์ ‘ ๋น„๊ตํ•ด ๋ณผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
์กฐ์ˆ˜๋นˆ 1. ๊ธฐ๋ณธ ๊ฒŒ์‹œํŒ ๊ธฐ๋Šฅ: ์ด์ „ ํ”„๋กœ์ ํŠธ์—์„œ์˜ ๊ฒฝํ—˜์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ธฐ๋ณธ ๊ฒŒ์‹œํŒ ๊ธฐ๋Šฅ์„ ํšจ์œจ์ ์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ ค ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ฐ˜์„ ๋งˆ๋ จํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜์˜€์œผ๋ฉฐ, ๊ณผ๊ฑฐ์— ๋ฐฐ์šด ๋‚ด์šฉ์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณต์Šตํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
2. ์ƒˆ๋กœ์šด ์ฃผ๋ ฅ ๊ธฐ๋Šฅ: ์ด๋ฒคํŠธ ๊ฒŒ์‹œํŒ์˜ ํ€ด์ฆˆ ๊ธฐ๋Šฅ
์ด๋ฒคํŠธ ๊ฒŒ์‹œํŒ ๋‚ด์— ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ํ€ด์ฆˆ๋ฅผ ๋งŒ๋“ค๊ณ  ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ ํ’€ ์ˆ˜ ์žˆ๋Š” ํ€ด์ฆˆ ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ํ€ด์ฆˆ๋Š” ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์‘์‹œํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ •๋‹ต๋ฅ ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์ง ์™„์„ฑํ•˜์ง€ ๋ชปํ•œ ํˆฌํ‘œ ๊ธฐ๋Šฅ๋„ ์ถ”ํ›„ ๊ณ ๋„ํ™”๋ฅผ ํ†ตํ•ด ์™„์„ฑํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค. Postman์„ ํ™œ์šฉํ•ด ๊ฐœ๋ฐœ ๊ณผ์ • ์ค‘ ๋ฐœ์ƒํ•˜๋Š” ์„ธ๋ถ€์ ์ธ ์˜ค๋ฅ˜๋ฅผ ์‹ ์†ํ•˜๊ฒŒ ํ™•์ธํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
3. DevOps ํ™œ์šฉ ๋ฐ ํ•™์Šต ๊ฒฝํ—˜
Docker, DockerHub, Kubernetes, Jenkins๋ฅผ ์ด์šฉํ•˜์—ฌ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๊ณผ์ •์„ ๋‹ด๋‹นํ–ˆ์Šต๋‹ˆ๋‹ค. ์ดˆ๊ธฐ์—๋Š” ์ด๋Ÿฌํ•œ ๊ธฐ์ˆ ๋“ค์˜ ๊ฐœ๋…์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ์–ด๋ ค์›€์„ ๊ฒช์—ˆ์ง€๋งŒ, ๋‹ค์–‘ํ•œ ์˜ค๋ฅ˜์— ์ง๋ฉดํ•˜๋ฉฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ณผ์ •์„ ํ†ตํ•ด ์ ์ฐจ ์ดํ•ด๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์  ํ‚จ์Šค ์Šคํฌ๋ฆฝํŠธ์˜ ์˜ค๋ฅ˜๋ถ€ํ„ฐ ํ•˜๋“œ์›จ์–ด ์šฉ๋Ÿ‰ ๋ถ€์กฑ์— ์ด๋ฅด๊ธฐ๊นŒ์ง€ ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๋ฅผ ๋‹ค๊ฐ๋„์—์„œ ๋ฐ”๋ผ๋ณด๊ณ  ์ ‘๊ทผํ•˜๋ฉด์„œ, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์™€ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ ๊ธฐ์ˆ ์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ๋ฐฐ์šฐ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
4. ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ์™€ ๊ธฐํš์˜ ์ค‘์š”์„ฑ
์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋Š” ์งง์€ ์‹œ๊ฐ„ ๋‚ด์— ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๊ณผ ํŒŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ์‚ผ์•˜์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ๋ช…ํ™•ํ•œ ๋ชฉํ‘œ ์„ค์ •๊ณผ ์šฐ์„ ์ˆœ์œ„ ์กฐ์ •์˜ ์ค‘์š”์„ฑ์„ ๊นŠ์ด ๋Š๊ผˆ์Šต๋‹ˆ๋‹ค. ๋‹ด๋‹น ๊ธฐ๋Šฅ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํŒ€์›๋“ค๊ณผ์˜ ์›ํ™œํ•œ ํ˜‘์—…๊ณผ ์กฐ์ • ๋Šฅ๋ ฅ์ด ํ”„๋กœ์ ํŠธ ์„ฑ๊ณต์— ํ•„์ˆ˜์ ์ž„์„ ์ธ์‹ํ–ˆ์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ๋„ ํŒ€์›๋“ค๊ณผ ํ˜‘๋ ฅํ•˜์—ฌ ์•„์ง ์™„์„ฑํ•˜์ง€ ๋ชปํ•œ ๊ธฐ๋Šฅ๊ณผ ์ถ”๊ฐ€์ ์ธ ๊ฐœ์„  ์˜๊ฒฌ์„ ๋ฐ˜์˜ํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์—…๊ทธ๋ ˆ์ด๋“œํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค.