Git Action

준비 환경

  • Amazon RDS (mysql , postgresql 중 택1, 포트 설정)
  • AWS EC2 (node.js, jdk17, Docker 등 필요한 기능 설치되어있어야함, 22, 8080, 80 포트 설정)
  • Elastic IP 설정 (고정 IP 필수)

deploy.yml 파일 생성

  1. 깃 최상위 경로에 /.github/workflows/deploy.yml 폴더와 파일을 생성한다. (경로와 파일명이 동일해야 git에 인식됨)
  2. deploy.yml 에 자신의 프로젝트 환경에 맞는 빌드 스크립트를 작성한다.

ex. Demo project 의 경우 Frontend (React+Vite) 와 Backend (SpringBoot) 이고, 프론트 dist 파일을 Backend static 에 올려서 함께 배포한다.

name: Deploy to EC2

on:
  push:
    branches: [ feature/awscicd ]  # 배포 원하는 브렌치 설정

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    env:
      GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
      GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
      # ... 환경변수들 git 에서 설정

    steps:
      - name: Checkout 코드
        uses: actions/checkout@v3

      - name: Node.js 설치
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Frontend Build
        run: |
          cd frontend
          npm ci
          npm run build
          cp -r dist/* ../backend/src/main/resources/static/  # Front 경로 맞추기

      - name: EC2에 .env 파일 생성
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
            mkdir -p /home/ec2-user/app/backend/build/libs  # Backend 경로 맞추기
            cd /home/ec2-user/app/backend/build/libs

            echo "GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }}" > .env
            echo "GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET }}" >> .env
            # ...
            
            echo "======= .env 파일 생성 완료 ==========="

            echo "======== .env 내용 확인 ========="
            cat .env

            echo "======== 환경변수 적용 ========"
            # 환경변수 적용
            if [ -f .env ]; then
              echo ".env 파일이 존재합니다. 환경변수를 적용합니다."
              set -a
              source .env
              set +a
            else
              echo ".env 파일이 존재하지 않습니다. 배포를 중단합니다."
              exit 1
            fi

      - name: Backend Build
        run: |
          cd backend
          chmod +x ./gradlew
          ./gradlew build --no-daemon -x test  # 테스트 설정

      - name: EC2에 JAR 파일 복사
        uses: appleboy/scp-action@v0.1.4
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          source: "backend/build/libs/*.jar"   # 경로 맞추기
          target: "/home/ec2-user/app/"

      - name: EC2에서 JAR 실행
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
            cd /home/ec2-user/app/backend/build/libs

            echo "======== JAR 파일 확인 ========"  # 파일명 확인
            ls -al backend-0.0.1-SNAPSHOT.jar || echo "=== JAR 파일이 존재하지 않습니다"

            echo "======== 자바 실행 ========="
            nohup java -jar backend-0.0.1-SNAPSHOT.jar > app.log 2>&1 & disown
            sleep 5

            echo "======== 실행된 자바 프로세스 확인 ========"
            pgrep -af java || echo "실행 중인 자바 없음"

            echo "========= 자바 로그 출력 ========"
            tail -n 50 app.log

참고

  • pkill -f 'java' || true 이걸 넣으면 Git Action 프로세스까지 다 정지되어서 다른 방법 찾아야함. → pm2로 jar 관리가능
  • disown 제거해도됨.
  • profiles 설정 (--spring.profiles.active=dev 추가)
nohup java -jar backend-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev > app.log 2>&1 & disown

해당 최상단 위치에서 deploy.yml 커밋 후 실행하고 싶지만 GitHub은 2021년부터 패스워드 방식 인증을 막았기 때문에GitHub 비밀번호로는 더 이상 PUSH 안됨. → ssh key 생성 필요

 


 

Git 용 SSH Key 생성

1. git commit HTTPS → SSH 인증 방식으로 바꾸기

  1. git 폴더 경로 터미널에서 ssh 키 만들기 (이미 있으면 생략):
ssh-keygen -t rsa -b 4096 -C "hellou@example.com"

Enter passphrase for "cat ~/.ssh/id_rsa.pub" (empty for no passphrase): 다 엔터로 그냥 넘어가기

    2. 공개키 확인하기

cat ~/.ssh/id_rsa.pub
ssh-rsa A~~~~~~~~

2. git settings 에 등록

  1. GitHub → Settings > SSH and GPG keys → New SSH Key → 붙여넣기
  • 아까 ssh-rsa 로 시작했던 값 입력하기 

   2. GitHub remote 주소 변경:

git remote set-url origin git@github.com:{자신의 git 리포지토리 주소}

 


 

deploy.yml 실행

git add .
git commit -m "ci: github actions 배포 추가"
git push origin develop
  • 배포 원하는 브랜치인지 확인할것

 

GitHub 에서 Action 워크플로우 확인

  1. GitHub 레포 열기
  2. 상단 탭 중에서 Actions 클릭
  3. Deploy to EC2 워크플로우가 실행되고 있는지 확인
  4. 각 step(log)을 클릭해서 npm, gradle, ssh, scp 성공 여부 확인

 


 

EC2 서버에서 배포확인

  1. .env 파일이 잘 생성되었는지 확인
  2. jar 파일이 경로에 생성되었는지 확인
  3. app.log 로 app 실행 로그 확인
  4. 디비 연결 잘 되는지 확인
  • EC2에서 AWS RDS 연결 테스트 (생성한 DB 환경에 맞춰 수정하여 테스트)
psql -h database 엔드포인트 \\
     -p 5432 \\
     -U name_a \\
     -d demodb

# jdbc:postgresql://{database앤드포인트}:5432/{dbname}
  • 연결 성공 시:
psql (16.1, server 13.4)
Type "help" for help.

demodb=>
  • 전체 테이블 보기 (현재 스키마 기준)
\\dt

 

  5. EC2 서버와 연결된 Elastic IP 로 접속하면 된다.

 


 

Git secrets text 환경변수 설정

  1. Repository 에 필요한 환경변수들을 적용한다.

OAuth 

OAUTH (Open Standard for Authorization)

    • 로그인에서 사용되는 프로토콜
    • SSO는 서비스,  OAUTH는 규약(프로토콜)
    • SSO는 OAUTH 방식을 이용해서 설계된다
    • 국제 인터넷 표준화 기구(Internet Engineering Task ForceIETF) - IETF OAuth 워킹그룹에 의해 표준 프로토콜로 발표되고있다.
    • 2006년 Twitter와 Google이 정의한 개방형 Authorization 표준이며, API 허가(Authorize)를 목적으로 JSON(JavaScript Object Notation) 형식으로 개발됨
    • 사용자는 번의 인가 절차로 다른 서비스를 이용할 , 로그인 자격 증명 (예를 들면 단일 ID 비밀번호) 같은 개인정보를 전송하지 않고도 자신의 접근 또는 기타 권한을 부여 있도록 ( 대한 공개 표준)

 

인증 - Authentication : 사용자의 신원을 확인

인가 - Authorization : 권한을 임시로 승인

 

Oauth1.0

  •    Resource Owner, OAuth Client, OAuth Server 로 구성됨

* Oauth1.0 의 문제

  • Scope 개념의 부제
  • 역할이 확실히 나누어 지지 않음
  • 토큰 유효기간의 문제
  • Client 구현 복잡성
  • 제한적인 사용환경

 

Oauth2.0

  • Scope 기능 추가 (접근 범위 설정 가능)
  • Client 복잡성 간소화 (암호학적 보안을 위한 서명 원문이 필요했는데 (Http Method, Base URL, Parameter(Author, Body) 등 복잡한 요소들이 필요했다.) 2에서는 Bearer Token + TLS 로 처리함)   - Bearer Token 해당 토큰 보유만으로도 사용인정_권한 생김, TLS(대표적으로 HTTPS 를 강제함)
  • 토큰 탈취 문제 개선 (1은 Access Token이 너무 길었다. 그래서 2는 AT 기간을 짧게 하고 따로 유효기간이 긴 리프레시토큰 만들었다)
  • 제한적인 사용환경 문제 개선 (1은 웹브라우저 환경에서만 사용하기 최적화 되어있었다. 2는 Grant 개념을 추가함. 여러가지 사용환경에 대한 플로우를 나타내는 인증방식)

 

 - Grant 

  • Authorization Code (Access Token을 위한 권한 인증 코드를 받을 때 사용하는 인증 발급 방식)
  • Implicit (권한 인증 코드Authorization Code 없이 바로 직접적으로 로그인 인증 후 토큰 발급 받는 방식)
  • Resource owner password credentials (직접 아디 비번 받아서 클라이언트가 요청하는 방식, 주로 자체 서비스등 외부 개발자가 사용할 수 없는 안전한 환경에서 사용함)
  • Client credentials (사용자User 가 아닌 Client 프로그램을 직접적으로 api호출을 통해 토큰 발급 받는 방식)

Grant 결과로 클라이언트는 접근 토큰 Access Token을 발급받는다. (JSON 방식의 JWT를 access token 형식으로 발급 받음)

 

 

Oauth2.1

 1. 더 보안적으로 민감한 사용처들의 프로토콜 채택

   (2.0에서 클라이언트가 복잡해서 보안을 위해 볼톤 시큐리티 방식으로 새로운 RFC가 보완책으로 등장함. PKCE,BCP… 2.1은 이런 것들을 합쳐 스펙화 시킴)

 

  1. Implicit, Resource owner password credentials  스펙아웃
  2. Device Authorization Grant 새로 추가 (다양한 IOT들에 사용하기 적합한 Grant_기기 바꿔서 인증 가능)
  3. Authorization Code grant 에 PKCE 확장팩 추가
  4. BCP : Refresh Token 회전 방식 (AT, RT 둘다 일회용방식)

 

 

Open ID Connect

  • 인가를 사용한 Pseudo 인증이 가능하다
  • 그래서 Oauth2.0 + Open Id(JWT 기반 ID Token 인증)를 합친 = open Id connect 인증계층 나타남
  • open Id connect  이걸 사용하면 JWT ID Token 도 함께 받을 수 있음 
  • ID Token 안에는 토큰발급자, 발급시간, 토큰사용자(client 식별자), 사용자 식별자, 토큰만료시간 등이 포함되어있다. 이를 아이디 토큰을 파싱하고 서명값을 검증하면 따로 api 콜을 안해도 사용자 정보를 가져올수있음. 통신부하 줄임

 

 

인증/인가의 미래, GNAP*

  • 새로운 GNAP 계획중이다 (하위호환은 안됨. start, finish 개념이 들어있는 json 기반의 과정까지 정할 수 있는 보안인증 방식, 접근범위 정밀 제어 및 여러 토큰 요청 가능, 
  • JWT, 인증서 기반 Client 보안 내장)

 

 

출처 -[NHN FORWARD 22] 로그인에 사용하는 OAuth : 과거, 현재 그리고 미래

 

 

 

참고

https://d2.naver.com/helloworld/24942

https://youtu.be/DQFv0AxTEgM

두가지 보안 프로토콜로 이메일 보내는 기능을 만들어야 했다. 

 

 


  @Bean
  public JavaMailSender LoginMailSender() {
    JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
    mailSender.setHost(host);
    mailSender.setPort(port);

    mailSender.setUsername(username);
    mailSender.setPassword(password);

    Properties props = mailSender.getJavaMailProperties();

    if (isTls) {
      log.info("=======isTLS : true");
      props.put("mail.transport.protocol", "smtp");  //smtps 하면 ssl 이군 isSSL true // google은 프로토콜안해도 보내짐
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.auth", "true");
    }
    if (isSsl) {
      log.info("========isSSL : true");
      props.put("mail.transport.protocol", "smtps");
      props.put("mail.smtps.ssl.checkserveridentity", "true");
      props.put("mail.smtps.ssl.trust", "*");
      props.put("mail.smtps.ssl.enable", "true");
      props.put("mail.smtps.auth", "true");
      props.put("mail.smtps.timeout", "5000");
      props.put("mail.smtps.connectiontimeout", "5000");
    }

    props.put("mail.debug", "true");
    return mailSender;
  }

저 protocol : smtps 이 부분을 찾는데 오래 걸렸다................

다른 곳은 mail.smtp.ssl.enable : true   이것만 하면 알아서 protocol : smtp 여도 ssl 이 잘 보내진다던데 안보내졌다. 

isSsl : false 로 호출하며 아예 smtp 시스템 자체가 접속이 안되었다. 

그래서 smtps 로 프로토콜 방식을 변경하니 smtps 에는 ssl.enable 이 default : true 라 isSsl : true 로 호출이 되었다....

이렇게 @Bean 으로 JavaMailSender 을 등록하고

 

                                                                                                         
  public void sendTmpPwMail(EmailMessage emailMessage) throws MessagingException {                       
    if (emailMessage.getTo().length < 1) {                                                               
      throw new MessagingException("보낼 이메일은 하나 이상이어야 합니다.");                                             
    }                                                                                                    
    subject = emailMessage.getSubject();                                                                 
    toEmail = emailMessage.getTo()[0];                                                                   
    fromEmail = username;                                                                                
    templateArgs = emailMessage.getTemplateArgs();  // name, tmpPw                                       
    String domain = emailMessage.getImgUrlDomain()!=null ? emailMessage.getImgUrlDomain(): "http://sample.com";
    content = getTmpPwEmailTemplate(domain, templateArgs);                                               
    this.sendMail();                                                                                     
  }                                                                                                      
                                                                                                         
  public void sendMail() throws MessagingException {                                                     
                                                                                                         
/*  SimpleMailMessage message =  new SimpleMailMessage();                                                
    message.setFrom(fromEmail);                                                                          
    message.setTo(toEmail);                                                                              
    message.setSubject(subject);                                                                         
    message.setText("testetsets");                                                                       
    emailSender.send(message);        */                                                                 
                                                                                                         
    MimeMessage message = emailSender.createMimeMessage();                                               
    MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");                            
    helper.setFrom(fromEmail);                                                                           
    helper.setTo(toEmail);                                                                               
    helper.setSubject(subject);                                                                          
    helper.setText(content, true);                                                                       
    emailSender.send(message);                                                                           
  }

이렇게 사용한다. 

템플릿의 한글깨짐을 방지하기 위해 MimeMessageHelper 에서 UTF-8 설정을 해준다. 

 

 

 

'개발자 > TIL' 카테고리의 다른 글

AWS + Git Action 사용법  (0) 2025.06.15
OAuth  (0) 2023.01.26
[JPA]queryDsl 에서 다중 IN 조건, where 절 서브쿼리  (0) 2021.06.09
[Node] Node Express 서버에 Oracle DB 연결하기  (0) 2021.05.12
[SOCKET] SOCKET 연결  (0) 2021.03.24

QueryDsl 에서 다중 In 조건을 사용하여 개발

 

1
2
3
4
5
6
7
8
9
10
11
12
13
List<Tuple> list = from(member)
            .where(
                    Expressions.list(member.agtNm, member.sessId).in(
                            JPAExpressions
                                    .select(Expressions.list(member.agtNm, member.sessId))
                                    .from(member)
                                    .where(member.regYmd.between(stDate, edDate))
                                    .groupBy(member.agtNm,member.sessId)
                                    .having(member.sessId.count().gt(1))
                    )
            )
            .groupBy(member.agtNm)
        .select(member.agtNm, member.count()).fetch();
cs

 

  • querydsl 에서 다중 in 조건을 사용하려면 Expressions.list 를 사용해야한다.
  • querydsl은 select, where 에서만 서브쿼리를 지원하고 있다. 
  • (select절 서브쿼리 : 스칼라서브쿼리, From절 서브쿼리 : 인라인뷰 서브쿼리, where절 서브쿼리 : 중첩서브쿼리)
  • JPAExpressions를 통해 서브쿼리를 생성한다.
  • select 에서는 ExpressionUtils.as( JPAExpressions.select(
  • where 절의 서브쿼리에서는 그냥 JPAExpressions 만 사용하면 된다.

 

 

 

참고

[Querydsl] 서브쿼리 사용하기

https://jojoldu.tistory.com/379

QueryDSL multiple subselect - (a,b) in (select c,d)

https://kic1.tistory.com/102

[ Oracle ] SQL 서브쿼리 SELECT, FROM, WHERE

https://mjn5027.tistory.com/51

https://mozi.tistory.com/233

'개발자 > TIL' 카테고리의 다른 글

OAuth  (0) 2023.01.26
[JavaMail] SMTP 메일 보내기 (ssl, tls)  (0) 2022.06.12
[Node] Node Express 서버에 Oracle DB 연결하기  (0) 2021.05.12
[SOCKET] SOCKET 연결  (0) 2021.03.24
Gradle 과 Maven 둘 다 사용하고 느낀점  (0) 2020.12.16

 

1. Node Express 서버에 oracle DB를 사용하기 위해 oracledb 설치

npm install --save oracledb

 

설치 확인

 

 

2. C++을 지원하는 C 컴파일러 설치

Visual Studio 2019 Version 설치

경로 : support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0

Visual Studio Installer 설치하면서 C/C++ 데스크탑 개발을 추가로 선택해서 설치한다.

 

 

 

3. Python 설치

node-oracledb를 컴파일 하기 위해 필요함.

경로 : https://www.python.org/downloads/

 

 

 

4. Oracle Instant Client 설치

설치를 안했을경우 윈도우에서 아래와 같은 에러 발생.

cx_Oracle error. DPI-1047: Cannot locate a 64-bit Oracle Client library

윈도우에서 실행 시 발생한 에러 

 

설치경로 : www.oracle.com/database/technologies/instant-client/downloads.html

 

컴퓨터 환경에 맞는 client 로 설치 한다. 

zip 파일을 받고 C 드라이브 아래 위치시킨다.

내 PC 환경변수 > Path 에 C:\dev\instantclient_19_10  등록한다.

 

 

 

설치, path 설정 완료 후 Visual Studio Code 로 프로젝트를 다시 오픈 하면 

TedisPool 정보가 나타나며 서버 실행이 된다.

 

 

 

 

참고

stackoverflow.com/questions/56119490/cx-oracle-error-dpi-1047-cannot-locate-a-64-bit-oracle-client-library

 

cx_Oracle error. DPI-1047: Cannot locate a 64-bit Oracle Client library

I installed the library and when trying to access SQL in jupyter notebook with my credentials the following error appears: DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "The

stackoverflow.com

willbesoon.tistory.com/120

+ Recent posts