본문 바로가기
Blog/TIL

[240531] 처음으로 배포를 해보다

by 코젼 2024. 5. 31.
728x90
반응형

🔶코딩테스트

🔶AWS

🔶리눅스


목차

    / 오늘의 TIL /


    코딩테스트

    기존 코드

    더보기
    import java.util.ArrayDeque;
    
    public class Solution {
        /**
         * @param s 문자열
         * @return 성공 1, 실패 0
         */
        public static int solution(String s)
        {
            ArrayDeque<Character> stack = new ArrayDeque<>();
    
            int lenS = s.length();
    
            char[] chars = new char[lenS];
            for (int i = 0; i < lenS; i++) {
                //char 형으로 변환한다.
                chars[i] = s.charAt(i);
            }
    
            //원본 문자열 길이만큼 진행한다.
            for (int i = 0; i < lenS; i++) {
                //stack이 비어있지 않은 경우만 로직 수행 가능
                if (!stack.isEmpty()) {
                    //stack에서 비교할 대상을 꺼낸다.
                    char compare = stack.peek();
    
                    //동일한 값: pop
                    if (compare == chars[i]) {
                        stack.pop();
                    }
                    //다른 값: push
                    else {
                        stack.push(chars[i]);
                    }
                }
                //비어있는 경우는 값을 추가한다.
                else {
                    stack.push(chars[i]);
                }
            }
            return stack.isEmpty() ? 1 : 0;
        }
    
    
        public static void main(String[] args) {
            System.out.println(solution("baabaa"));
        }
    }

    리팩토링

    s.toCharArray(): String 문자열 -> char 문자열로 변경할 수 있다.

    조건문을 적절하게 활용하자 (if - else if - else)

    더보기
    /**
     * @param s 문자열
     * @return 성공 1, 실패 0
     */
    public int solution(String s)
    {
        ArrayDeque<Character> stack = new ArrayDeque<>();
    
        //원본 문자열 길이만큼 진행한다.
        for (char c : s.toCharArray()) {
            //stack이 비어있는 경우 값 추가
            if (stack.size() == 0) {
                stack.push(c);
            }
            //마지막 대상과 문자가 동일한 경우 값 제거
            else if (stack.peek() == c) {
                stack.pop();
            }
            //마지막 대상과 문자가 다른 경우 값 추가
            else {
                stack.push(c);
            }
        }
    
        return stack.isEmpty() ? 1 : 0;
    }

    AWS

    인바운드규칙(방화벽): 서버에 접근하는 포트 번호 허용 규칙

    0.0.0.0/0 로 설정해두면 누구나 이 페이지에 접근할 수 있다.

    터미널로 접속하기

    key-pair를 최초로 생성하면 pem key가 생성된다.

    보안 설정을 해주어야 접속이 가능하다.

    chmod 400 {pem key 경로}

    aws에 접속하기

    ssh -i {pem key 경로} ec2-user@{IP주소}

     

     

    AWS 콘솔로 접속하기

    연결 클릭
    연결 클릭

    (접속 완료. 귀엽다!)

     

    서버 종료

    Ctrl + C

     


    리눅스

    Ctrl + A: 맨 앞으로 이동

    Ctrl + E: 맨 뒤로 이동

    파일 내용물 확인

    파일 직접 접근

    리눅스 편집기 vim 사용

    vi nohup.out

    터미널에서 내용 확인

    #전체 내용 확인
    cat nohup.out
    
    #끝 부분만 확인
    tail nohup.out
    
    #실시간으로 출력해주는 속성
    tail -f nohup.out

    명령어

    mkdir folder1   #폴더 생성
    ls	 	 #목록 확인
    ls -l 		  #목록 데이터 자세한 정보 확인 (ll)

     

    drwxr-xr-x. 2 ec2-user ec2-user 6 May 31 02:45 folder1

    d: 디렉토리 폴더

    r: 읽기

    w: 쓰기

    x: 실행

    폴더 소유자의 권한 / 폴더 소유 그룹의 권한 / 아무나 접근했을 때

     

    2: 폴더에 걸려있는 바로가기 개수

    ec2-user: 폴더의 주인 이름

    ec2-user: 폴더 소유 그룹 이름

    6: 폴더(파일)의 크기 - byte

    시간: 최종 변경 시간

    폴더명

     

    pwd: 현재 경로 확인

    rmdir: 디렉토리 폴더 삭제


    프로그램 최신 버전으로 업데이트

    sudo yum update

    sudo: 관리자 권한 실행

    yum: 리눅스 패키지 관리 프로그램

    update: 현재 설치되어있는 프로그램 최신 버전으로 업데이트

    설치

    git 설치

    sudo yum install git -y

    -y: y를 입력하지 않아도 자동으로 설치된다.

     

    java 설치

    sudo yum install java-11-amazon-corretto -y
    java -version #설치 확인

    mysql 설치

    wget https://dev.mysql.com/get/mysql80-community-release-el7-5.noarch.rpm
    sudo rpm -ivh mysql80-community-release-el7-5.noarch.rpm
    sudo yum install mysql-community-server

    systemctl: 현재 보이지 않는 프로그램을 관리하는 명령어

    sudo systemctl status mysqld
    [ec2-user@ip-172-31-42-56 ~]$ sudo systemctl status mysqld
    ○ mysqld.service - MySQL Server
         Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; preset: disabled)
         Active: inactive (dead)
           Docs: man:mysqld(8)
                 http://dev.mysql.com/doc/refman/en/using-systemd.html

    status가 inactive인 상태는 정상적으로 설치됐으나 아직 활성화되지 않은 상태이다.
    상태를 활성화 시키기 위해서 해당 명령어를 입력한다.

    sudo systemctl restart mysqld
    [ec2-user@ip-172-31-42-56 ~]$ sudo systemctl status mysqld
    ● mysqld.service - MySQL Server
         Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; preset: disabled)
         Active: active (running) since Fri 2024-05-31 05:59:53 UTC; 8s ago
           Docs: man:mysqld(8)
                 http://dev.mysql.com/doc/refman/en/using-systemd.html
        Process: 49069 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
       Main PID: 49182 (mysqld)
         Status: "Server is operational"
          Tasks: 38 (limit: 1114)
         Memory: 423.4M
            CPU: 6.295s
         CGroup: /system.slice/mysqld.service
                 └─49182 /usr/sbin/mysqld

     

    Mysql8 임시 비밀번호 확인 명령어

    sudo cat /var/log/mysqld.log | grep "A temporary password"

     

    임시 비밀번호: A!I4P8j.N&2Y

    [ec2-user@ip-172-31-42-56 ~]$ sudo cat /var/log/mysqld.log | grep "A temporary password"
    2024-05-31T05:59:48.294125Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: A!I4P8j.N&2Y

     

    해당 임시 비밀번호로 mysql 접속

    임시 비밀번호일 경우 ddl이 불가능하다.

    mysql -u root -p

     

    비밀번호 변경

    8자리 이상, 대문자 소문자 숫자 특수문자 포함 필수

    alter user 'root'@'localhost' identified with mysql_native_password by "Abcd1234!";

     

    mysql 종료

    exit;

     


    AWS <-> Github 연동 및 배포

    git clone https://github.com/kdelay/Server-All-In-One.git

    EC2는 메모리가 부족할 수도 있기 때문에, 메모리가 부족한 경우 디스크를 사용하도록 설정한다.

    Swap 설정

    #스왑 메모리 할당 (128M * 16 = 2GB)
    sudo dd if=/dev/zero of=/swapfile bs=128M count=16
    
    #파일 권한 설정
    sudo chmod 600 /swapfile
    
    #스왑 파일 생성
    sudo  mkswap /swapfile
    
    #스왑 파일을 설정할 수 있도록 세팅한다.
    sudo swapon /swapfile
    
    #스왑이 할당되었는지 확인
    sudo swapon -s

     


    빌드

    빌드 후에 build 파일이 생성된다.

    build > libs > jar파일로 서버 실행

    #gradlew를 사용하기 위해 실행할 수 있도록 설정한다.
    chmod +x ./gradlew
    
    #gradle을 이용해 프로젝트를 빌드하고 테스트를 제외하고 빌드한다. (EC2 성능 이슈)
    ./gradlew build -x test

    생성된 아티팩트

    현재 빌드되어있는 결과물 제거

    ./gradlew clean

    자바 실행

    jar파일을 java -jar 명령어로 실행시킨다.

    intelliJ에서 설정해둔 profile을 --spring.profiles.active=dev 속성을 통해 설정한다.

    java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev

    백그라운드로 실행하기

    #nohup [명령어] &
    nohup java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar &

    백그라운드로 실행하고 나면 백그라운드로 실행되고 있는 프로그램의 log가 저장되는 nohup.out 파일이 생긴다.

    [ec2-user@ip-172-31-42-56 Server-All-In-One]$ nohup java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar &
    [1] 50946
    [ec2-user@ip-172-31-42-56 Server-All-In-One]$ nohup: ignoring input and appending output to 'nohup.out'
    
    [ec2-user@ip-172-31-42-56 Server-All-In-One]$ ls
    HELP.md  build  build.gradle  gradle  gradlew  gradlew.bat  nohup.out  settings.gradle  src

    파일 제거

    rm nohup.out

     

    상위 폴더에서 백그라운드로 실행

    nohup java -jar Server-All-In-One/build/libs/library-app-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev &

    백그라운드 서버 종료

    작업관리자 명령어

    ps aux: 현재 실행중인 프로그램 목록을 확인할 수 있다.

     

    java가 들어가는 프로그램을 확인한다.

    ec2-user   50946  4.7 19.5 2539320 190444 pts/1  Sl   06:54   0:13 java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar

    ps aux | grep java

     

    백그라운드 서버 종료

    kill -9 [프로그램번호]

    [1]+  Killed                  nohup java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar

    kill -9 50946

    기타

    gradle 버전 업그레이드

    2.x -> 3.x migration build tool 의존성 제공

    runtimeOnly 'org.springframework.boot:spring-boot-properties-migrator'

    lombok 의존성 추가

    implementation 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

     

    JPA의 한계

    대용량 데이터를 처리할 때 성능이 매우 떨어진다.

    예를 들어, 사과 데이터 1000개를 insert하는 query를 보내고 싶은 경우 JPA의 saveAll 메서드를 사용하면 사과를 하나씩 전달한다.

    query를 1000번 동작하는 불상사가 발생한다...

    JPA는 사과 1000개를 모아서 한 번에 전송하는 방법이 없기 때문에 JdbcTemplate의 batchUpdate를 사용해야 한다.

    //1만 개씩 잘라서 저장
    public void saveAllBatch(List<Fruit> fruits) {
    	for (List<Fruit> chunk : chunks(fruits, 10_000)) {
    		jdbcTemplate.batchUpdate("insert into fruilt (name, price) values (?, ?)", new BatchPreparedStatementSetter()) {
    			@Override
    			public void setValues(PreparedStatement ps, int i) throws SQLException {
    				ps.setString(1, chunk.get(i).getName());
    				ps.setInt(2, chunk.get(i).getPrice());
    			}
    			@Override
    			public int getBatchSize() { return chunk.size(); }
    		}
    	}
    }
    
    //10만건 -> [1만건] / [1만건] / ...
    private static List<List<Fruit>> chunks(List<Fruit> inputs, int chunkSzie) {
    	List<List<Fruit>> result = new ArrayList<>();
    	int size = inputs.size();
    	int currStep = 0;
    
    	while (currStep + chunkSize < size) {
    		result.add(new ArrayList<>(inputs.subList*currStep, currStep + chunkSize)));
    		currStep += chunkSize;
    	}
    	
    	result.add(new ArrayList<>(inputs.subList(currStep, size)));
    	return result;
    }

    application.yml 파일에서 추가 설정 필요

    datasource.url="~~?rewriteBatchedStatements=true"
    728x90
    반응형

    'Blog > TIL' 카테고리의 다른 글

    [240602] JPA 영속성 컨텍스트  (0) 2024.06.02
    [240601] 코딩 테스트 문제 풀기  (0) 2024.06.01
    [240530] 도메인 연관 관계의 중요성  (0) 2024.05.30
    [240529] 직접 해봐야 안다  (0) 2024.05.29
    [240528] 백문이 불여일타!  (0) 2024.05.28

    댓글