
기존 사용중이던 GCP Cloud SQL의 비용이 너무 비싸서(하루에 약 6,000원) Oracle Cloud ATP(Autonomous Transaction Processing)으로 이주하기로 하였습니다. 프리티어 기준 20GB까지 스토리지를 무료로 제공해주기 때문에 변경하지 않을 이유는 없었습니다.
문제는 기존에 사용하던 방식(호스트 주소&포트)과 달리 TNS 방식으로 연결해야 하며, 해당 과정에서 클라우드 전자지갑(Wallet)을 사용해야 하는데, 이를 CI/CD 파이프라인을 구축할 때 함께 고려해야 한다는 점이었습니다.
기본적인
스프링부트 + GAE + github actions를 이용한 CI/CD는 여기를 참고해주세요.
Oracle Cloud에서 ATP 인스턴스를 생성 후, 데이터베이스 접속 버튼을 누르면 다음과 같은 화면을 확인할 수 있습니다.

여기서 전자 지갑 다운로드를 눌러 Wallet을 다운해줍니다.(*.zip) TNS 이름 중 _high를 사용할 것이므로 해당 TNS 이름을 기억해줍니다.
각 TNS 이름(TNS_NAME)에 대한 간략한 설명은 다음과 같습니다.
high : 동시성은 낮으나, 가장 리소스가 높고 쿼리가 병렬로 실행됩니다.
medium : 리소스가 줄어들었으나 그만큼 동시성이 높아집니다. 쿼리가 병렬로 실행됩니다.
low : 리소스가 최소이며 최고의 동시성을 갖습니다. 쿼리가 연속적으로 실행됩니다.
참고 : Database Service Names for Autonomous Data Warehouse
다음과 같은 코드를 dependencies에 추가합니다.
runtimeOnly 'com.oracle.database.jdbc:ojdbc8'
implementation 'com.oracle.database.security:oraclepki'
implementation 'com.oracle.database.security:osdt_core'
implementation 'com.oracle.database.security:osdt_cert'
다음과 같은 코드를 추가합니다.
spring.datasource.url=jdbc:oracle:thin:@[TNS_NAME]?TNS_ADMIN=./src/main/resources/OracleCloud
spring.datasource.username=ADMIN
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
자세한 설명은 다음과 같습니다.
jdbc:oracle:thin:@[TNS_NAME]?TNS_ADMIN=./src/main/resources/OracleCloud./src/main/resources/OracleCloud에 위치시킬 것이므로 TNS_ADMIN을 해당 경로로 설정하였습니다.ADMIN입니다.${DB_PASSWORD}와 같이 작성하였습니다.로컬에서 OCI ATP가 제대로 연결되었는지 테스트해보려면 다음과 같은 과정을 거치면 됩니다.
아까 전에 다운 받은 Wallet의 압축을 풀어 ./src/main/resources/OracleCloud에 위치시켜주세요.

전자 지갑은 github에 push되지 않도록 .gitignore 설정을 해두었습니다.
DB_PASSWORD를 시스템 환경 변수에 등록해두어야 합니다.
시스템 환경 변수 편집 검색환경 변수 버튼 클릭새로 만들기 버튼 클릭 후, 변수 이름에 DB_PASSWORD, 변수 값에 OCI ATP 비밀번호 입력 후 적용~/.bash_profile 또는 ~/.bashrc 파일을 열고 export DB_PASSWORD=[OCI ATP 비밀번호] 줄 추가~/.zshrc 파일을 열고 같은 줄을 추가source ~/.bash_profile 또는 source ~/.zshrc을 실행하여 적용.다음과 같은 코드를 추가하여 연결을 테스트합니다. 연결 성공 시 화면에 Success가 출력됩니다.
@RestController
public class TestController {
@Autowired
private JdbcTemplate jdbcTemplate;
@GetMapping("/test")
public String testConnection() {
String sql = "SELECT 'Success' FROM dual";
return jdbcTemplate.queryForObject(sql, String.class);
}
}
기존 PROJECT_ID, GCP_SA_KEY와 더불어 두 개를 더 추가해주어야합니다.
OCI ATP 비밀번호를 등록해주면 됩니다.
Wallet zip 파일을 base64로 인코딩한 결과(텍스트)를 등록해주면 됩니다. base64로 인코딩하려면 다음과 같은 코드를 사용하면 됩니다.
macOS/Linux
base64 -i OracleCloud.zip -o OCI_WALLET.txt
Windows
certutil -encode OracleCloud.zip OCI_WALLET.txt
즉, 총 4개의 Secrets이 존재해야합니다.

name: CICD
on:
push:
branches: [ develop ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
- name: Decode and Unzip OCI Wallet
run: |
echo "${{ secrets.OCI_WALLET }}" | base64 --decode > oci-wallet.zip
unzip oci-wallet.zip -d ./src/main/resources/OracleCloud
- name: Set DB_PASSWORD for Github Env
run: echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> $GITHUB_ENV
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Setup app.yaml with secrets
run: |
cd ./src/main/appengine
echo "" >> app.yaml
echo "env_variables:" >> app.yaml
echo " DB_PASSWORD: ${{ secrets.DB_PASSWORD }}" >> app.yaml
- name: Auth to GCP
uses: 'google-github-actions/auth@v1'
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Deploy to App Engine
uses: 'google-github-actions/deploy-appengine@v1'
with:
deliverables: build.gradle
project_id: ${{ secrets.PROJECT_ID }}
github actions는 기본적으로 JDK 11을 사용하므로, JDK17 사용 시 따로 설정해주어야 합니다.
아까전에 인코딩했던 OCI_WALLET을 다시 디코딩하여 ./src/main/resources/OracleCloud 위치에 압축 해제합니다.
테스트 코드에서 DB가 연결되었는지 검사하므로, github actions 서버 내의 DB_PASSWORD 환경 변수를 설정하여야 build 시 문제가 발생하지 않습니다.
app.yaml에 추가적으로 DB_PASSWORD 환경 변수에 대한 코드가 다음과 같이 들어가야 GAE 내에서 문제 없이 Oracle Cloud ATP에 접근할 수 있습니다.
env_variables:
DB_PASSWORD: [OCI ATP 비밀번호]
하지만 해당 코드를 직접 작성하는 것은 비밀번호 유출의 문제가 있으므로, 해당 단계를 통해 app.yaml에 코드를 추가합니다.


성공적으로 자동 배포되고, Oracle Cloud ATP에 정상적으로 연결됨을 확인할 수 있습니다.