no image
공유 캘린더 만들기 #5 (API 문서화 및 UI 구성)
API 문서화 (Swagger) Swagger를 이용하여 API 문서화를 진행하였다. SwaggerConfig.java @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return testDocket("API", (s) -> true); } private Docket testDocket(String groupName, Predicate selector) { return new Docket(DocumentationType.OAS_30) .useDefaultResponseMessages(false) .securityContexts(List.of(securityContext())) // Security..
2023.08.03
no image
헬스장 이용권 #2 (Entity 구성)
회원가입 로그인은 Spring Security와 JWT를 이용하였고, 이전 프로젝트에서 다루었으므로 참고하시면 됩니다. https://jeonsg99.tistory.com/3 공유 캘린더 만들기 #2 (JWT를 이용한 회원가입 로그인) JWT를 이용한 회원가입 로그인 본격적인 프로젝트를 구성하면서 가장 먼저 회원가입 로그인을 구현하려 한다. Spring boot를 이용해서 인증 인가 메커니즘을 구현하기 위해 Spring security 와 JWT를 이 jeonsg99.tistory.com Entity 구성을 들어가기 전에 프로젝트 구성에 필요한 Table를 생각해보자 1. Member (유저 정보를 기록) 2. Authority (접근 권한을 이용한 관리자와 사용자 구분) 3. GymMembership ..
2023.08.03
헬스장 이용권 #1 (Springboot+AWS+Docker)
1. 프로젝트 개요 - 헬스장을 운영하는 관리자와 이용하는 사용자 측면에서 편리성을 제공하고자 함 - 사용자는 남은 헬스장과 PT 이용권 기간 및 횟수를 확인할 수 있다. - 관리자는 헬스장 이용자 등록, 현황을 확인하고, 담당 회원 PT이용 시간표를 손쉽게 볼 수 있다. 2. 사용 기술 - Spring boot - Spring security - JWT - Spring Data JPA - Docker - AWS EC2, S3, Code Deploy, RDS(MySQL) - Github actions 본 프로젝트에서 Back-End 부분을 담당했기 때문에 프론트 부분은 포함되어있지 않습니다. 프로젝트 초기 구성 프로젝트가 프론트 둘 백엔드 하나로 구성되어 있기 때문에 가장 먼저 서버 배포를 구현하였습니다..
2023.08.03
no image
백준 11657(타임머신)
문제를 보면 최단거리 구하는 문제인걸 바로 알 수 있다. 최단거리 알고리즘인 세가지를 생각해 볼 수 있다. 1. 다익스트라(Dijkstra) 2. 벨만-포드(Bellman-Ford) 3. 플로이드-워셜(Floyd-Warshall) 시작점이 정해져 있으니 다익스트라(Dijkstra), 벨만-포드(Bellman-Ford)중에 하나를 사용하면 되고, 조건에서 보면 C distance[start] + time: distance[end] = distance[start] + time # 출발노드가 무한대가 아니고 종료 노드 값 < 출발 노드 값 + 에지 가중치일때 # distance[end] 값을 출발 노드 값 + 에지 가중치로 변경해준다. mCycle = False # 음의 사이클 여부 for start, end..
2023.08.03
no image
Spring boot + Docker + Github Actions + AWS 를 이용한 자동 배포화
과정 1. Github main 브랜치에 Push 2. Github Actions에서 AWS S3에 빌드 파일 및 Dockerfile, deploy.sh 등 업로드 3. Github Actions이 AWS CodeDeploy에 배포 요청 4. CodeDeploy가 배포 실행 5. 도커 빌드 및 실행 위와 같은 과정으로 자동 배포화가 진행됩니다. Github Actions -> S3 빌드 및 업로드 - S3 버킷 생성 IAM 사용자를 통해 S3 저장소에 접근 할 것이기 때문에 모든 퍼블릭 액세스를 차단합니다. 아래와 같이 버킷이 생성된 것을 확인 할 수 있습니다. IAM 설정 IAM > 사용자 > 사용자 추가 - 정책 추가 GitHub Actions 워크플로우에서 AWS 리소스를 사용하기 위해 Amazon..
2023.07.29
no image
Attack Range (ALGORITHM JOBS)
(1) (i,j) ~ (x,y) 까지 거리를 구한다. (2) 이 거리가 R안에 들어오는가?? import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int X = sc.nextInt(); int Y = sc.nextInt(); int R = sc.nextInt(); //사거리 int arr[][] = new int[105][105]; for(int i = 1 ; i
2023.07.29
no image
점수 계산 (ALGORITHM JOBS)
문제는 위와 같다. 자바를 기반으로 작성하였지만, 구조는 c언어와 비슷하게 작성을 하였다. import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int sum=0; int ed =0; // 전의 값이 1일때 값이 쌓이는 곳 int num = sc.nextInt(); for(int i = 0 ; i
2023.07.29
no image
네트워크 프로토콜(5)
Router & Switch 라우터와 스위치 모두 다 데이터를 저장하고 전달하는 기능을 해준다. 이 둘의 차이점은 주로 사용되는 계층이 다르다는 것인데, 라우터는 Network-layer, 스위치는 Link-layer에서 주로 사용된다. 처음에는 완전히 그 계층에서만 사용되는 것인줄 알았는데 그렇지만은 않은 것 같다. 그 계층의 장비인것은 맞지만 3계층 스위치도 존재하고, 라우터도 2계층을 건드린다고 볼 수 있다고 한다. Ethernet Ethernet는 데이터링크층 프로토콜이다. 6개의 필드로 구성되어있는데, preamble, 목적지주소(DA), 발신지 주소(SA), Type, 상위 계층의 Data, FCS로 이루어져있다. Preamble를 제외한 뒤의 필드를 frame라고 한다. Preamble는 물..
2023.07.29

목차

     

    API 문서화 (Swagger)

    Swagger를 이용하여 API 문서화를 진행하였다. 

     

    SwaggerConfig.java

    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
    
        @Bean
        public Docket api() {
            return testDocket("API", (s) -> true);
        }
    
        private Docket testDocket(String groupName, Predicate<String> selector) {
            return new Docket(DocumentationType.OAS_30)
                    .useDefaultResponseMessages(false)
                    .securityContexts(List.of(securityContext())) // SecurityContext 설정
                    .securitySchemes(List.of(apiKey())) // ApiKey 설정
                    .groupName(groupName)
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.example.Capstone.api"))
                    .paths(PathSelectors.any())
                    .build();
        }
    
        // JWT SecurityContext 구성
        private SecurityContext securityContext() {
            return SecurityContext.builder()
                    .securityReferences(defaultAuth())
                    .build();
        }
    
        private List<SecurityReference> defaultAuth() {
            AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
            AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
            authorizationScopes[0] = authorizationScope;
            return List.of(new SecurityReference("Authorization", authorizationScopes));
        }
    
        // ApiKey 정의
        private ApiKey apiKey() {
            return new ApiKey("Authorization", "Authorization", "header");
        }
    }

     

     

     

    UI 구성 (Front - End)

    Front - End에서 구성한 UI를 간단하게 정리해보자.

     

    - Front 구축에 있어 디테일한 구성들이 더 있지만 프로젝트 구현 핵심 내용을 위주로 작성했습니다.

    - Front에서는 React를 기반으로 개발을 하였고, Fullcalendar 라이브러리를 사용하였습니다.

     

    1. Main View

    FullCalendar 기본 UI를 주로 사용 하였다.

     

    2. 일정 생성

    일정을 생성할 때 알림 설정 여부를 선택할 수 있고, 선택 그룹 일정 작성 및 공유 대상 설정도 할 수 있도록 했다.

    공유된 일정은 일정 공유자에게 메시지 형태로 알림이 가고 이를 통해 참여 여부를 결정할 수 있다.

    알람을 설정한 시간에 문자로 알림이 오도록 하였다. (더 좋은 방법을 모색해보자..)

     

    3. Menu

    내가 해당하는 그룹에서 체크박스를 두어 체크한 일정만 우측의 캘린더에 출력이 되도록 구축하였다.

    이 방법은 구글캘린더에서 아이디어를 얻어 적용을 했다.

     

    4. 일정 공유 (그룹)

     좌측 사이드 바에서 공유를 누르면 카카오톡 링크 공유로 넘어가게 되고, 초대코드를 받은 사용자는 초대 코드를 입력할 수 있는 form이 있다. 

    단일 일정 공유와 마찬가지로 초대코드를 입력하면 그룹 오너에게 그룹 참여 메시지가 전송되고, 이를 통해 참여 여부를 결정할 수 있다.

     

     

    5. Todo List

    Todo List를 이용하여 오늘 할 일을 생성 및 체크할 수 있도록 구성하였다.   

    목차

      회원가입 로그인은 Spring Security와 JWT를 이용하였고, 이전 프로젝트에서 다루었으므로 참고하시면 됩니다.

      https://jeonsg99.tistory.com/3

       

      공유 캘린더 만들기 #2 (JWT를 이용한 회원가입 로그인)

      JWT를 이용한 회원가입 로그인 본격적인 프로젝트를 구성하면서 가장 먼저 회원가입 로그인을 구현하려 한다. Spring boot를 이용해서 인증 인가 메커니즘을 구현하기 위해 Spring security 와 JWT를 이

      jeonsg99.tistory.com

       

       

      Entity 구성을 들어가기 전에 프로젝트 구성에 필요한 Table를 생각해보자

      1. Member (유저 정보를 기록)

      2. Authority (접근 권한을 이용한 관리자와 사용자 구분)

      3. GymMembership (헬스장 이용권)

      4. PTSubscription (PT 이용권)

      5. Reservation (예약 정보)

      6. Trainer (트레이너 정보)

       

      이제부터 하나씩 구성해보자.

       

      Member.java

      @Entity
      @Getter
      @Setter
      @NoArgsConstructor
      public class Member {
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
      
      
          @Column(nullable = false)
          private String email;
      
          @Column(nullable = false)
          private String password;
      
          @Column(nullable = false)
          private String name;
      
          @Column(nullable = false)
          @Pattern(regexp = "^(Male|Female)$", message = "성별은 Male 또는 Female이어야 합니다.")
          private String gender;
      
          @Enumerated(EnumType.STRING)
          private Authority authority;
      
          @OneToOne(fetch = FetchType.LAZY, mappedBy = "member")
          private PTSubscription ptSubscription;
      
          @OneToOne(fetch = FetchType.LAZY, mappedBy = "member")
          private GymMembership gymMembership;
      
          @OneToMany(mappedBy = "member")
          private List<Reservation> reservations;
      
      
      
          public Member(Long memberId) {
              this.id = memberId;
          }
      
      
          public void setNickname(String nickname) {
              this.name = name;
          }
      
          public void setPassword(String password) {
              this.password = password;
          }
      
      
          @Builder
          public Member(Long id, String email, String password, String name, String gender, Authority authority) {
              this.id = id;
              this.email = email;
              this.password = password;
              this.name = name;
              this.gender = gender;
              this.authority = authority;
          }
      }

       

      Authority.java

      public enum Authority {
          ROLE_USER, ROLE_ADMIN
      }

       

      GymMembership.java

      - 기본적인 시작날짜와 종료날짜만 구성해주었다.

      @Entity
      @Getter
      @Setter
      @NoArgsConstructor
      public class GymMembership {
      
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
      
          private LocalDate startDate;
          private LocalDate endDate;
          @OneToOne(fetch = FetchType.LAZY)
          @JoinColumn(name = "member_id")
          private Member member;
      }

       

      PTSubscription.java

      @Entity
      @Getter
      @Setter
      @AllArgsConstructor
      @NoArgsConstructor
      public class PTSubscription {
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
      
          private int availableCount=0; // 사용 가능한 횟수
          private int usedCount=0; // 사용된 횟수
      
          @OneToOne(fetch = FetchType.LAZY)
          @JoinColumn(name = "member_id")
          private Member member;
      }

       

      Reservation.java

      - expired를 예약시간의 만료 유무를 판단하기 위해 bollean형식으로 두었다.

      @Entity
      @Getter
      @Setter
      @AllArgsConstructor
      @NoArgsConstructor
      public class Reservation {
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
      
          private LocalDateTime reservationTime; // PT 예약 시간
      
          @ManyToOne
          @JoinColumn(name = "member_id")
          private Member member;
      
          @ManyToOne
          @JoinColumn(name = "trainer_id")
          private Trainer trainer;
      
          @Column(nullable = false)
          private boolean expired = false;
      
      }

       

      Trainer.java

      @Getter
      @Setter
      @AllArgsConstructor
      @NoArgsConstructor
      @Entity
      public class Trainer {
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
      
          @Column(nullable = false)
          private String name;
      
          @Column(nullable = false)
          @Pattern(regexp = "^(Male|Female)$", message = "성별은 Male 또는 Female이어야 합니다.")
          private String gender;
      
          @OneToMany(mappedBy = "trainer")
          private List<Reservation> reservations;
      }

       

      DB Tables

      목차

        1. 프로젝트 개요

        - 헬스장을 운영하는 관리자와 이용하는 사용자 측면에서 편리성을 제공하고자 함

        - 사용자는 남은 헬스장과 PT 이용권 기간 및 횟수를 확인할 수 있다.

        - 관리자는 헬스장 이용자 등록, 현황을 확인하고, 담당 회원 PT이용 시간표를 손쉽게 볼 수 있다.

         

        2. 사용 기술

        - Spring boot

        - Spring security

        - JWT

        - Spring Data JPA

        - Docker

        - AWS EC2, S3, Code Deploy, RDS(MySQL)

        - Github actions

         

        본 프로젝트에서 Back-End 부분을 담당했기 때문에 프론트 부분은 포함되어있지 않습니다.

         

        프로젝트 초기 구성

        프로젝트가 프론트 둘 백엔드 하나로 구성되어 있기 때문에 가장 먼저 서버 배포를 구현하였습니다.

        서버 배포는 AWS EC2 인스턴스를 이용했고, git에 배포하는 과정도 자동 배포화를 이용하여 효율적인 프로젝트 구성을 준비하였습니다.

         

        AWS 프리티어를 사용하고 있으므로, 메모리가 부족 할 경우를 대비하여 

        AWS 공식 홈페이지에 있는 스왑 파일을 이용한 메모리 확보 방법을 사용했습니다.

        https://repost.aws/ko/knowledge-center/ec2-memory-swap-file

         

        스왑 파일을 사용하여 Amazon EC2 인스턴스의 스왑 공간으로 메모리 할당

        Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스에서 스왑 파일로 사용할 메모리를 할당하려고 합니다. 어떻게 해야 하나요?

        repost.aws

         

        자동배포화 하는 과정은 아래 글을 참고하시면 됩니다.

        https://jeonsg99.tistory.com/15

         

        Spring boot + Docker + Github Actions + AWS 를 이용한 자동 배포화

        과정 1. Github main 브랜치에 Push 2. Github Actions에서 AWS S3에 빌드 파일 및 Dockerfile, deploy.sh 등 업로드 3. Github Actions이 AWS CodeDeploy에 배포 요청 4. CodeDeploy가 배포 실행 5. 도커 빌드 및 실행 위와 같은

        jeonsg99.tistory.com

         

        백준 11657(타임머신)

        핑구우
        |2023. 8. 3. 00:23

        목차

           

          문제를 보면 최단거리 구하는 문제인걸 바로 알 수 있다. 

          최단거리 알고리즘인 세가지를 생각해 볼 수 있다.

          1. 다익스트라(Dijkstra) 

          2. 벨만-포드(Bellman-Ford)

          3. 플로이드-워셜(Floyd-Warshall)

           

          시작점이 정해져 있으니 다익스트라(Dijkstra), 벨만-포드(Bellman-Ford)중에 하나를 사용하면 되고, 조건에서 보면 C<0인 경우도 다루고 있기때문에 가중치가 음수일때 사용하는 벨만-포드(Bellman-Ford)를 사용하면 된다.

           

          문제는 벨만-포드(Bellman-Ford)알고리즘를 이용해서 음의 사이클이 존재하는가를 확인하면 된다. 

          (노드 개수-1)까지 반복하면 모든 노드는 최단거리로 연결이 되고, 이후에 한번 더 반복 비교를 했을때 가중치가 update되면 음의 사이클이 존재한다고 볼 수 있다.

           

           

          import sys
          input = sys.stdin.readline
          N, M = map(int, input().split()) # N(노드 개수) M(에지 개수)
          edges = [] # 에지 정보 저장 리스트
          distance = [sys.maxsize] * (N+1) # 거리 리스트(충분히 큰 수로 저장한다.) 
          #distance의 길이를 N+1까지 저장하여 index 1부터 시작하도록 한다. 
          
          
          for i in range(M):
              start, end, time = map(int, input().split())
              edges.append((start, end, time))
          
          distance[1] = 0 # 시작점은 0으로 초기화
          
          for _ in range(N-1):
              for start, end, time in edges:
                  if distance[start] != sys.maxsize and distance[end] > distance[start] + time:
                      distance[end] = distance[start] + time
                      # 출발노드가 무한대가 아니고 종료 노드 값 < 출발 노드 값 + 에지 가중치일때 
                      # distance[end] 값을 출발 노드 값 + 에지 가중치로 변경해준다.
          
          mCycle = False # 음의 사이클 여부
          
          for start, end, time in edges:
              if distance[start] != sys.maxsize and distance[end] > distance[start] + time:
                  mCycle = True
                  # N-1까지 반복한 후에 한번 더 반복 했을때 update가 된다면 음의 사이클이 존재한다.
          
          if not mCycle:
              for i in range(2, N+1):
                  if distance[i] != sys.maxsize:
                      print(distance[i])
                  
                  else:
                      print(-1)
          
          else:
              print(-1)

           

           

           

          '알고리즘' 카테고리의 다른 글

          백준 13549 (숨바꼭질 3)  (0) 2023.08.11
          백준 1260(DFS와 BFS)  (0) 2023.08.07
          Attack Range (ALGORITHM JOBS)  (0) 2023.07.29
          점수 계산 (ALGORITHM JOBS)  (0) 2023.07.29
          백준 17298(오큰수)  (0) 2023.07.29

          목차

            과정
            1. Github main 브랜치에 Push
            2. Github Actions에서 AWS S3에 빌드 파일 및 Dockerfile, deploy.sh 등 업로드
            3. Github Actions이 AWS CodeDeploy에 배포 요청
            4. CodeDeploy가 배포 실행
            5. 도커 빌드 및 실행

             

            위와 같은 과정으로 자동 배포화가 진행됩니다.

            Github Actions -> S3 빌드 및 업로드

            - S3 버킷 생성

             

            

            IAM 사용자를 통해 S3 저장소에 접근 할 것이기 때문에 모든 퍼블릭 액세스를 차단합니다.

             

             

            아래와 같이 버킷이 생성된 것을 확인 할 수 있습니다.

            IAM 설정

            IAM > 사용자 > 사용자 추가

            - 정책 추가

            GitHub Actions 워크플로우에서 AWS 리소스를 사용하기 위해

            AmazonS3FullAccess와 AWSCodeDeployFullAccess 정책을 추가한다.

             

            - Access Key 생성

            보안 자격 증명 -> 액세스 키 만들기

            위와 같이 설정 해줍니다.

             

            생성된 액세스 키는 csv 파일로 저장해둡니다. 이후에 Github Actions에서 secreats 를 설정해줘야 합니다.

             

            - 역할생성

            IAM -> 역할 -> 역할 만들기

             

            1. EC2 역할 생성

            CodeDeploy 서비스를 사용하여 EC2 인스턴스에 애플리케이션을 배포하기 위해 AmazonEC2RoleforCodeDeploy 역할을 추가한다.

             

             

            2. CodeDeploy 역할 생성

            자동으로 권한이 추가된다.

             

            - EC2 IAM 역할 수정

            사용중인 EC2 인스턴스 접속 후에 작업 -> 보안 -> IAM 역할 수정을 해준다. 

            설정한 role-ec2-codedeploy로 역할을 수정해준다. (이후에 인스턴스 재부팅 한 번 해야한다.)

             

            CodeDeploy 설정

            CodeDeploy-> 배포 -> 애플리케이션 -> 애플리케이션 생성

             

            - 배포그룹 생성

            환경 구성의 키 값은 사용중인 인스턴스 값을 사용한다.

             

             


            Github 설정

            - Secrets

            github -> settings -> secrets and variables -> Actions

            위에 IAM 설정에서 가져온 액세스 키의 정보들을 AWS_ACCESS_KEY_ID 와 AWS_SECRET_ACCESS_KEY에 저장하고, APPLICATION에는 spring boot 프로젝트 내의 application.yml 파일 내용을 넣습니다.

             

            - Github Actions Workflow

             Actions에서 새로운 Wokrflow를 생성해준다.

            main-deploy.yml

            # This workflow uses actions that are not certified by GitHub.
            # They are provided by a third-party and are governed by
            # separate terms of service, privacy policy, and support
            # documentation.
            # This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
            # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
            
            name: Deploy to Production
            
            on:
              push:
                branches:
                  - main
            jobs:
              deploy:
                runs-on: ubuntu-latest
            
                steps:
                  - name: Checkout source code
                    uses: actions/checkout@master
            
                  - name: Set up JDK 11
                    uses: actions/setup-java@v3
                    with:
                      java-version: '11'
                      distribution: 'temurin'
            
                  - name: Gradle Caching
                    uses: actions/cache@v3
                    with:
                      path: |
                        ~/.gradle/caches
                        ~/.gradle/wrapper
                      key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
                      restore-keys: |
                        ${{ runner.os }}-gradle-
                  - name: Make application.yml
                    run: |
                      cd ./src/main
                      mkdir resources
                      cd ./resources
                      touch ./application.yml
                      echo "${{ secrets.APPLICATION }}" > ./application.yml
                    shell: bash
            
                  - name: Grant execute permission for gradlew
                    run: chmod +x gradlew
            
                  - name: Build with Gradle
                    run: ./gradlew build
            
                  - name: Make zip file
                    run: |
                      mkdir deploy
                      cp ./appspec.yml ./deploy/
                      cp ./Dockerfile ./deploy/
                      cp ./scripts/*.sh ./deploy/
                      cp ./build/libs/*.jar ./deploy/
                      zip -r -qq -j ./spring-build.zip ./deploy
            
                  - name: Configure AWS credentials
                    uses: aws-actions/configure-aws-credentials@v2
                    with:
                      aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
                      aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
                      aws-region: ap-northeast-2
            
                  - name: Upload to S3
                    run: |
                      aws s3 cp \
                        --region ap-northeast-2 \
                        ./spring-build.zip s3://jeonsg2-bucket
            
                  - name: Code Deploy
                    run: aws deploy create-deployment --application-name spring-deploy
                      --deployment-config-name CodeDeployDefault.OneAtATime
                      --deployment-group-name spring-deploy-group
                      --s3-location bucket=jeonsg2-bucket,bundleType=zip,key=spring-build.zip

             

             

            EC2 설정

            S3에 있는 파일을 담을 app 폴더를 생성한다.

            mkdir ~/app

             

            Docker 설치

            sudo apt update //우분투 패키지 인덱스 업데이트
            sudo apt install docker.io -y //도커 설치
            sudo service docker start //도커 시작
            sudo systemctl status docker.service //확인

             

            프로젝트 파일 설정

            Dockerfile (프로젝트 루트 디렉토리에 넣어주면 된다.)

            FROM openjdk:11
            
            WORKDIR /Toy-project
            
            COPY Toy_project-0.0.1-SNAPSHOT.jar app.jar
            
            ENTRYPOINT ["java","-jar","app.jar"]

             

            scripts/depoly.sh

            #!/bin/bash
            
            echo "> 현재 실행 중인 Docker 컨테이너 pid 확인" >> /home/ubuntu/deploy.log
            CURRENT_PID=$(sudo docker container ls -q)
            
            if [ -z $CURRENT_PID ]
            then
              echo "> 현재 구동중인 Docker 컨테이너가 없으므로 종료하지 않습니다." >> /home/ubuntu/deploy.log
            else
              echo "> sudo docker stop $CURRENT_PID"   # 현재 구동중인 Docker 컨테이너가 있다면 모두 중지
              sudo docker stop $CURRENT_PID
              sleep 5
            fi
            
            cd /home/ubuntu/app
            sudo docker build -t imagee:v1.0 .
            sudo docker run -d -p 8080:8080 imagee:v1.0

             

            appspec.yml

            version: 0.0
            os: linux
            files:
              - source: /
                destination: /home/ubuntu/app
                overwrite: yes
            
            permissions:
              - object: /
                pattern: "**"
                owner: ubuntu
                group: ubuntu
            
            hooks:
              ApplicationStart:
                - location: deploy.sh
                  timeout: 60
                  runas: ubuntu

             

             

            배포 자동화 결과

            GitHub Actions Workflows
            S3 bucket
            CodeDeploy 자동 배포 성공
            EC2 인스턴스 내에서 실행되는 docker image

             

            1. Spring boot 프로젝트에서 GitHub로 push를 하게 되면 GitHub Actions는 push event를 감지하여 자동으로 시작된다.

            2. Actions는 빌드 도구 Gradle를 사용하여 Spring boot 애플리케이션을 빌드한다.

            3. 빌드가 성공하면 빌드 된 애플리케이션 아티팩트 JAR를 생성한다.

            4. Actions는 해당 JAR파일을 S3 버킷에 업로드한다.

            5. CodeDeploy는 S3 버킷에서 애플리케이션 아티팩트를 가져와 EC2 인스턴스에 배포한다.

            6. 배포가 성공하면 최신 버전의 애플리케이션 EC2 인스턴스에서 실행된다.

             

            위의 순서와 같이 자동 배포화가 이루어집니다.

            목차

              (1) (i,j) ~ (x,y) 까지 거리를 구한다.

              (2) 이 거리가 R안에 들어오는가??

              import java.util.Scanner;
              public class Main{
                  public static void main(String[] args){
                  Scanner sc = new Scanner(System.in);
              
                  int N = sc.nextInt();
                  int X = sc.nextInt();
                  int Y = sc.nextInt(); 
                  int R = sc.nextInt(); //사거리
                  int arr[][] = new int[105][105];
              
                  for(int i = 1 ; i<=N ; i++){
                    for(int j = 1; j<=N ; j++){
                      int a = X-i; 
                      int b = Y-j;
                      if(a<0)a*=-1; // 단순 거리 계산이기 때문에 부호를 변경해야함
                      if(b<0)b*=-1; // 단순 거리 계산이기 때문에 부호를 변경해야함
              
                      int dist = a+b;
                      if(dist==0)arr[i][j]=-1;
                      else if(dist<=R)arr[i][j]=dist;
                    }
                  }
                  for(int i = 1 ; i<=N ; i++){
                    for(int j = 1; j<=N ; j++){
                      if(arr[i][j]==-1) System.out.print("x ");
                      else System.out.print(arr[i][j]+" ");
                    }
                    System.out.println();
                  }
                     // Please Enter Your Code Here
              
                  }
              }

              입력

              8
              4 5 3

              출력

              0 0 0 0 3 0 0 0
              0 0 0 3 2 3 0 0
              0 0 3 2 1 2 3 0
              0 3 2 1 x 1 2 3
              0 0 3 2 1 2 3 0
              0 0 0 3 2 3 0 0
              0 0 0 0 3 0 0 0
              0 0 0 0 0 0 0 0

              8x8 크기의 형태로, (4,5)위치의 플레이어 x값에 사거리가 3인 x

              x를 기준으로 가로, 세로 길이 합이 3인 좌표들을 구해야한다.

              a+b의 값을 dist에 집어넣고 dist가 0이라면 그 좌표는 플레이어 x의 좌표이다.

              arr은 int형이므로 x의 좌표에 "x"를 넣지 못하므로 -1을 넣는다.

              이 후에 -1 값을 "x"로 출력한다.

              '알고리즘' 카테고리의 다른 글

              백준 13549 (숨바꼭질 3)  (0) 2023.08.11
              백준 1260(DFS와 BFS)  (0) 2023.08.07
              백준 11657(타임머신)  (0) 2023.08.03
              점수 계산 (ALGORITHM JOBS)  (0) 2023.07.29
              백준 17298(오큰수)  (0) 2023.07.29

              목차

                문제는 위와 같다.

                자바를 기반으로 작성하였지만, 구조는 c언어와 비슷하게 작성을 하였다.

                import java.util.Scanner;
                public class Main{
                    public static void main(String[] args){
                    Scanner sc = new Scanner(System.in);
                    int N = sc.nextInt();
                    int sum=0;
                    int ed =0; // 전의 값이 1일때 값이 쌓이는 곳
                    int num = sc.nextInt();
                    for(int i = 0 ; i<N ; i++){
                      if (i==0){
                        if(num==1) sum++; //맨 처음 i는 num이 1일때 +1
                      }
                      else{
                         int ied = num; //num이 넘어가기 전 값을 저장한다.
                         num = sc.nextInt();
                      if(num==1) {  //
                        sum++; //num이 1이면 일단 +1
                        if(ied==1){ 
                          sum+=ed+1; //전의 값이 1일때는 값을 쌓아간다.
                          ed++; // 값을 쌓는 과정
                        }
                        else ed=0; //전의 값이 0이면 ed초기화
                       }
                      }
                
                    }
                    System.out.println(sum);
                
                
                    }
                }

                입력

                10
                1 0 1 1 1 0 0 1 1 0

                출력

                10

                '알고리즘' 카테고리의 다른 글

                백준 13549 (숨바꼭질 3)  (0) 2023.08.11
                백준 1260(DFS와 BFS)  (0) 2023.08.07
                백준 11657(타임머신)  (0) 2023.08.03
                Attack Range (ALGORITHM JOBS)  (0) 2023.07.29
                백준 17298(오큰수)  (0) 2023.07.29

                목차

                  Router & Switch

                  라우터와 스위치 모두 다 데이터를 저장하고 전달하는 기능을 해준다.

                  이 둘의 차이점은 주로 사용되는 계층이 다르다는 것인데, 라우터는 Network-layer, 스위치는 Link-layer에서 주로 사용된다. 처음에는 완전히 그 계층에서만 사용되는 것인줄 알았는데 그렇지만은 않은 것 같다. 그 계층의 장비인것은 맞지만 3계층 스위치도 존재하고, 라우터도 2계층을 건드린다고 볼 수 있다고 한다.

                  Ethernet

                  Ethernet는 데이터링크층 프로토콜이다.

                  6개의 필드로 구성되어있는데, preamble, 목적지주소(DA), 발신지 주소(SA), Type, 상위 계층의 Data, FCS로 이루어져있다.

                  Preamble를 제외한 뒤의 필드를 frame라고 한다. 

                  Preamble는 물리계층에서 생성 된 것으로 프레임의 시작을 나타내고, 동기화할때 사용된다.

                  Frame의 구조

                  Frame의 구조는 위와 같이

                  목적지주소 6바이트, 발신지 주소 6바이트,

                  상위 레이어 프로토콜의 종류를 알려주는 Type 2바이트

                  상위 레이어 프로토콜의 데이터를 담고있는 46~1500바이트의 크기를 가진 Data,

                  그리고 마지막으로 4바이트 길이의 오류 검출 정보를 갖고있다.

                  '네트워크' 카테고리의 다른 글

                  네트워크 프로토콜(4)  (0) 2023.07.29
                  네트워크 프로토콜 (3)  (0) 2023.07.29
                  네트워크 프로토콜 (2)  (0) 2023.07.29
                  네트워크 프로토콜 (1)  (0) 2023.07.29