728x90
반응형
  • 디자인 패턴은 코드를 잘 작성할 수 있도록 하는 지침서. 레시피라고 말할 수 있다.

생성 패턴

싱글톤 패턴 Singleton

  • 하나의 클래스 인스턴스를 전역에서 접근 가능하게 함
  • 따라서 해당 인스턴스가 한 번만 생성되도록 보장

팩토리 메서드 패턴 Factory Method

  • 객체를 생성하기 위한 인터페이스를 정의하고 서브 클래스에서 어떤 클래스를 인스턴스를 생성할지 결정하는 패턴

추상 팩토리 패턴 Abstract Factory

  • 관련된 객체들의 집합을 생성하는 인터페이스 제공
  • 구체적인 팩토리 클래스를 통해 객체 생성을 추상화하는 패턴

빌더 패턴 Builder

  • 복잡한 객체의 생성 과정을 단순화하고, 객체를 단계적으로 생성하며 구성하는 패턴

프로토타입 패턴 Prototype

  • 객체를 복제하여 새로운 객체를 생성하는 패턴
  • 기존 객체를 템플릿으로 사용
728x90
반응형
728x90
반응형

솔리드 (SOLID) 원칙

  • 솔리드 원칙은 코드를 올바르게 사용할 수 있게 하는 지침서이다
  • 여담으로 디자인패턴은 코드를 잘 만들 수 있게 하는 레시피이다.

단일 책임 원칙 (Single Responsiblity Principle; SRP)

  • 소프트웨어의 컴포넌트는 단 하나의 책임만을 가져야 한다.

개방 폐쇄 원칙 (Open Close Principles; OCP)

  • 확장에 대해선 열려 있어야 하고 수정에 대해선 닫겨 있어야 한다.

리츠코프 치환 원칙 (Liskov Substitution Principle; LSP)

  • 자식 클래스는 부모클래스에서 가능한 행위를 수행할 수 있어야 한다.

인터페이스 분리의 원칙 (Interface Segregation Principle; ISP)

  • 하나의 일반적인 인터페이스 보단 여러 개의 구체적인 인터페이스가 낫다.

*의존관계 역전 원칙 (Dependency Inversion Principle; DIP) *

  • 의존 관계를 맺을 때, 변화하기 쉬운것 보단 변화하기 어려운 것에 의존해야 한다.
728x90
반응형

'백엔드 Backend' 카테고리의 다른 글

[결합도/응집도] 결합도와 응집도란  (0) 2024.10.24
악성코드 종류  (0) 2024.10.16
비동기 Asynchronous 란?  (0) 2024.10.04
[백엔드] REST API 란?  (0) 2024.09.27
[백엔드] gRPC란  (3) 2024.09.26
728x90
반응형

CI / CD

  • CI (Continuous Integration): 지속적 통합
    • 코드에 대한 통합
    • 다수의 개발자들의 코드 베이스를 계속해서 통합한다는 의미
    • 즉 여러 개발자들의 코드를 빠르게 배포함을 의미
  • CD (Continuous Deployment): 지속적 배포
    • 코드 베이스를 사용자가 사용하는 환경에 코드 베이스 배포를 자동화하는 것
  • 즉 CI/CD는 여러명의 개발자들이 개발 환경을 통합하여 사용자가 사용하는 환경에 전달하는 모든 일련의 과정들을 자동화하는 것
    • 여기에는 코드 빌드, 테스트, 배포가 포함됨

젠킨스?

  • Java Runtime Environment에서 동작
    • 플러그인 사용하여 자동화 작업 파이프라인을 설계
    • 파이프라인 마저도 플러그인의 일부
  • Credentials 플러그인을 사용해서 민감정보를 보관

젠킨스 파이프라인

  • Section - 가장 큰 개념
    • Agent Section
      • 오케스트레이션 처럼 slave node에 일 처리 지정
    • Post Section
      • 스테이지가 끝난 이후의 결과에 따른 후속 조치
      • 즉 작업 결과에 따른 행동 조치
    • Stage Section - 카테고리
      • 어떠한 일을 처리할 것인지 stage를 정의
      • Dockerfile의 스테이지를 정의하는 것과 같음
    • Step Section - 카테고리 내부의 동작들
      • 한 스테이지 안에서의 단계
      • 여러 작업들 실행 가능

Declaratives

  • Environment, Stage, Options, Parameters, Triggers, When
  • 각 Stage 안에서 어떠한 일을 할 것인지 정의
  • Environment
    • 환경변수들 정의
  • Parameter
    • 파이프라인 실행시 파라미터를 받음
  • Triggers
    • 파이프라인이 실행되는 트리거 정의
    • 예시: 특정 브랜치에 머지가 감지되었을 때
  • When
    • 수행되는 조건문
    • 예시: 환경변수 BUILD_BRANCH가 dev일 때

예시

  • 깃허브 특정 레포 dev(개발)/main(운영) 브랜치에 머지 인식
    • 미리 Credentials에 등록해 둔 각각 환경에 따라 다른 환경 변수 로드
    • 각각 환경에 따른 이미지 명으로 도커 이미지 빌드
    • 개인 도커 레지스트리에 이미지 푸시
    • 각각 개발/운영 서버에 배포할 서비스 경로 생성
      • docker-compose.yml 파일 복사
      • 빌드하여 푸시한 이미지 가져와서 컨테이너 구동
// 브랜치별 배포 위치

def getDeployTargets(envName) {

targets = [:]



// dev 브랜치

targets['prod'] = [[

    COMPOSE_ENV: 'dev',

    SSH_MODE: 'KEYONLY',

    SSH_IP: '<Server IP>',

    SSH_KEY_ID: 'Key Id From Jenkins Credentials',

    COPY_DIR: '도커 컴포즈 파일 배포할 서버 상의 경로'

]]

    return targets[envName]
}



// 브랜치별 환경 정보

def getBuildBranch(branchName) {
    branches = [
        'origin/main': 'prod',
    ]

    return branches[branchName]
}



pipeline {
    agent any

    //환경변수
    environment {

        //브랜치 선택

        BUILD_BRANCH = getBuildBranch(env.GIT_BRANCH)

        // 도커 설정
        DOCKER_IMAGE = ''
        DOCKER_IMAGE_NAME = '빌드 할 도커 이미지 명'

        // Git, Docker private 레지스트리 로그인 정보 설정    
        GIT_KEY_ID = '깃허브 인증 SSH 키 ID - Credentials에서 관리;'
        REGISTRY_LOGIN_INFO_ID = 'donghquinn_registry'
    }



                        stages {

                            stage('체크아웃') {
                                steps {
                                    echo "작업 브랜치: ${env.GIT_BRANCH}"

                                    git branch: BUILD_BRANCH, credentialsId: GIT_KEY_ID, url: 'git@github.com:donghquinn/<레포 명>.git'

                            }

                        }



                        stage('도커 이미지 빌드') {
                            steps {
                                script {

                                    // 브랜치에 따라 이미지 이름 변경
                                    DOCKER_IMAGE = docker.build(DOCKER_IMAGE_NAME + '-' + BUILD_BRANCH)

                                }

                                echo "Built: ${DOCKER_IMAGE_NAME}-${BUILD_BRANCH}"

                            }
                        }



                        stage('도커 이미지 Push') {
                            steps {
                                script {
                                    // 개발서버 내부 Docker private 레지스트리에 업로드
                                    docker.withRegistry('https://registry.donghyuns.com', REGISTRY_LOGIN_INFO_ID) {

                                    DOCKER_IMAGE.push(env.BUILD_NUMBER)
                                    DOCKER_IMAGE.push('latest')
                                }

                            }
                            echo "Pushed: ${DOCKER_IMAGE_NAME}-${BUILD_BRANCH}:${env.BUILD_NUMBER}"

                            }

                        }



                        stage('도커 컨테이너 배포') {

                        steps {

                            script {

                                def deployTargets = getDeployTargets(BUILD_BRANCH)

                                def deployments = [:]



                                // 배포 타깃별로 병렬 배포

                                for (item in deployTargets) {

                                def target = item



                                deployments["TARGET-${BUILD_BRANCH}"] = {

                                def remote = [:]
                                remote.name = target.SSH_IP
                                remote.host = target.SSH_IP
                                remote.allowAnyHosts = true

                                if (target.SSH_MODE == 'KEYONLY') {

                                    withCredentials([

                                    // DOTENV 파일과 SSH KEY를 가져옴
                                    sshUserPrivateKey(credentialsId: target.SSH_KEY_ID, keyFileVariable: 'SSH_PRIVATE_KEY', usernameVariable: 'USERNAME')
                                    ]) {

                                    // 가져온 키로 ssh 정보 설정
                                    remote.user = USERNAME

                                    remote.identityFile = SSH_PRIVATE_KEY

                                    sshCommand remote: remote, command: """
                                        mkdir -p ${target.COPY_DIR}-${BUILD_BRANCH}/
                                    """

                                    // docker compose 파일 전송
                                    sshPut remote: remote, from: "docker-compose.${BUILD_BRANCH}.yml", into: "${target.COPY_DIR}-${BUILD_BRANCH}/docker-compose.yml", failOnError: 'true'

                                    // 각 상황에 맞는 .env.* 파일 전송

                                   // 각 상황에 맞는 .env.* 파일 전송
                                  sshPut remote: remote, from: DOTENV, into: "${target.COPY_DIR}/.env", failOnError: 'true'

                                    // 도커 이미지 Pull 및 재시작
                                    sshCommand remote: remote, command: """
                                        cd ${target.COPY_DIR}-${BUILD_BRANCH}/
                                        BUILD_BRANCH=${BUILD_BRANCH} docker compose pull
                                        BUILD_BRANCH=${BUILD_BRANCH} docker compose up -d
                                    """
                                }
                            }
                        }

                        parallel deployments

                    }

                }

            }

        }

    }

}
728x90
반응형

+ Recent posts