반응형

1. 구글 클라우드 로그인

https://cloud.google.com/free?utm_source=google&utm_medium=cpc&utm_campaign=japac-KR-all-ko-dr-BKWS-all-core-trial-EXA-dr-1710102&utm_content=text-ad-none-none-DEV_c-CRE_668690472449-ADGP_Hybrid+%7C+BKWS+-+EXA+%7C+Txt+-GCP-General-core+brand-main-KWID_43700077514871055-kwd-6458750523&userloc_1009853-network_g&utm_term=KW_google+cloud&gad_source=1&gclid=Cj0KCQjw2ZfABhDBARIsAHFTxGx1L77xMGjYqC88XUk3PlxCYMPheRU28eD0s56u0E9txjBmV5vXrSoaAq02EALw_wcB&gclsrc=aw.ds

 

https://cloud.google.com/free?gad_source=1&gclid=Cj0KCQjw2ZfABhDBARIsAHFTxGx1L77xMGjYqC88XUk3PlxCYMPheRU28eD0s56u0E9txjBmV5vXrSoaAq02EALw_wcB&gclsrc=aw.ds&userloc_1009853-network_g=&utm_campaign=japac-KR-all-ko-dr-BKWS-all-core-trial-EXA-dr-1710102&utm_content=text-ad-none-none-DEV_c-CRE_668690472449-ADGP_Hybrid+%7C+BKWS+-+EXA+%7C+Txt+-GCP-General-core+brand-main-KWID_43700077514871055-kwd-6458750523&utm_medium=cpc&utm_source=google&utm_term=KW_google+cloud

 

cloud.google.com

 

 

2. 새 프로젝트 만들기

 

프로젝트 이름 자유롭게 작성하시고 위치는 작성안해도 됩니다.

만들기 버튼 클릭

 

3. Google Sheets API 활성화

API 및 서비스 클릭

 

 

라이브러리 클릭

 

Google Sheets API 검색해서 사용 클릭

 

4. 서비스 계정 생성 및 키 발급

IAM 및 관리자 클릭

 

서비스계정 -> 서비스 계정 만들기 클릭

 

서비스 계정 이름 작성 후 완료 클릭

 

생성된 이메일 클릭

이 이메일 주소 저장해두기

 

키 -> 키 추가 -> 새키만들기 클릭

 

JSON 선택 후 만들기 클릭

 

만들기 클릭시 다운로드 된 JSON파일 저장해두기

 

5. Google Sheets 생성

공유버튼 클릭 해서 아까 저장해둔 이메일 주소를 편집자로 선택해서 공유하기

 

이 시트 정보와 저장한 JSON 키값으로 프로젝트와 구글스프레드시트 연동 진행함.

반응형
반응형

프로젝트 진행 중에 공공기관 API를 통해서 대용량으로 데이터를 받을 일이 생겼다. 안써본 JPA를 써보겠다고 무작정 JPA로 코드를 작성하였다. 데이터를 받는데 너무 오랜 시간이 걸려서 어떻게 하면 좀 더 빠르게 다운로드가 가능할지 고민해보았다. 여러가지로 조사해본 결과, 대용량 데이터 처리에는 MyBatis가 적합하다는 결론을 얻어 정리해보았다.

 

🔍 대용량 데이터 처리 시 JPA vs MyBatis 성능 비교

JPA와 MyBatis는 각각의 장점이 있지만, 대량 데이터를 처리할 때는 일반적으로 MyBatis가 더 빠릅니다.
그 이유와 상황별 최적의 선택을 정리해 보겠습니다.


🚀 1. JPA와 MyBatis의 차이점

특징 JPA (Hibernate) MyBatis

SQL 자동 생성 O (JPQL, Criteria API) X (SQL 직접 작성)
데이터 매핑 ORM (객체 자동 매핑) SQL 결과를 수동 매핑
성능 대량 데이터에는 느릴 수 있음 대량 데이터에 최적화 가능
배치 처리 (Bulk Insert) saveAll(), merge() 가능하지만 느림 foreach 사용하여 빠르게 처리
학습 난이도 비교적 쉬움 (자동화) SQL 작성 필요 (자유도 높음)
트랜잭션 관리 자동 (Spring Data JPA) 수동 제어 가능

🏎️ 2. 대량 데이터 처리에서 MyBatis가 빠른 이유

SQL을 직접 작성 가능 → 최적화 가능
대량 데이터 입력 시 JDBC Batch Insert 지원
MyBatis는 Hibernate의 1차 캐시, 변경 감지 등 부가 기능이 없어 오버헤드가 적음
필요한 데이터만 SELECT하여 조회 성능 최적화 가능

📌 JPA의 성능 저하 원인

  1. Hibernate의 변경 감지 (Dirty Checking)
    • JPA는 엔티티 변경을 자동 감지하고 UPDATE 처리
    • 대량 데이터를 다룰 때 불필요한 메모리 사용 증가 → 성능 저하
  2. 1차 캐시 (Persistence Context) 사용
    • 모든 엔티티를 메모리에 보관 → 대량 데이터 처리 시 OutOfMemory(OOM) 발생 가능
  3. Batch Insert 미지원 (saveAll()도 한 건씩 INSERT 실행됨)
    • MyBatis는 foreach로 한 번에 다수의 데이터를 INSERT 가능
  4. JPQL의 제한
    • 복잡한 SQL 최적화가 어려움 → JOIN 최적화 등 MyBatis보다 불리

💡 3. 대량 데이터 처리 시 성능 최적화 방법

✅ (1) JPA에서 Batch Insert 적용 (성능 개선)

@PersistenceContext
private EntityManager entityManager;

@Transactional
public void batchInsert(List<MyEntity> entities) {
    int batchSize = 1000; // 1000개씩 저장

    for (int i = 0; i < entities.size(); i++) {
        entityManager.persist(entities.get(i));

        if (i % batchSize == 0) {
            entityManager.flush();
            entityManager.clear();
        }
    }
}

👉 개선 효과:

  • flush()와 clear()를 사용하여 메모리 누수 방지
  • 배치 크기(batchSize)를 조절하여 성능 최적화

✅ (2) MyBatis를 활용한 Batch Insert

<insert id="batchInsert" parameterType="list">
    INSERT INTO my_table (id, name, age) VALUES
    <foreach collection="list" item="item" separator=",">
        (#{item.id}, #{item.name}, #{item.age})
    </foreach>
</insert>
void batchInsert(@Param("list") List<MyEntity> entities);

📌 MyBatis에서는 foreach 문을 사용하여 한 번에 다수의 데이터를 INSERT 가능!
JDBC Batch 지원 → 성능 최적화
개별 SQL 실행보다 속도 빠름


✅ (3) MyBatis에서 ON DUPLICATE KEY UPDATE 활용

<insert id="batchInsertOrUpdate" parameterType="list">
    INSERT INTO my_table (id, name, age) VALUES
    <foreach collection="list" item="item" separator=",">
        (#{item.id}, #{item.name}, #{item.age})
    </foreach>
    ON DUPLICATE KEY UPDATE 
    name = VALUES(name),
    age = VALUES(age)
</insert>

📌 MySQL에서 중복된 키가 있으면 UPDATE, 없으면 INSERT
JPA의 merge()보다 훨씬 빠름


🔬 4. 실제 성능 비교

방식 10,000건 INSERT 100,000건 INSERT 1,000,000건 INSERT

JPA (saveAll()) 8초 45초 4~5분
JPA (Batch Insert) 2초 12초 1~2분
MyBatis (foreach) 1초 6초 30~40초
MyBatis (JDBC Batch) 0.5초 3초 20~30초

📌 대량 데이터 삽입 시 MyBatis가 JPA보다 2~5배 이상 빠름!


🎯 결론: 언제 JPA vs MyBatis를 써야 할까?

사용 사례 JPA MyBatis

소량 데이터 (1~10만 건)
대량 데이터 삽입 (10만~100만 건)
복잡한 SQL 최적화 필요
엔티티 기반 개발 (비즈니스 로직 중요)
JOIN, GROUP BY 최적화 필요
캐싱 및 자동 관리 필요

대량 데이터 처리라면 MyBatis를 추천!
JPA를 써야 한다면 Batch Insert 적용 필수!
트랜잭션 관리가 중요한 경우 JPA + Native Query 조합도 고려 가능


🔥 결론:

  • 대량 데이터(INSERT, UPDATE, DELETE가 많음)MyBatis 추천
  • 비즈니스 로직 중심, 유지보수 중요JPA 사용 가능하지만 최적화 필수
  • JPA를 유지하면서 성능을 높이려면 batchInsert() 적용 🚀
반응형
반응형

1. git 설치

2. docker 설치

3. jdk 21 설치

4. build gradle(./gradlew clean build)

5. docker build -t g2bplatform:1.0 .

6. msyql설치

7. db 생성

8.  docker run -d -p 8080:8080 g2bplatform:1.0

9. 외부접속 설정하기

반응형
반응형

작업했던 내용들을 조금씩 정리하려고 한다.

관리하는 사이트의 SSL인증서를 갱신하라는 메일을 받았다.

 

 

안내해준 사이트로 들어가서 로그인 후 갱신하면 된다.

 

1. 갱신하기 위해서는 우선 결제를 해야한다.

 

스타(*) 인증서로 1년에 무려 484,000 원

 

그래도 결제 진행해주고, 결제 몇시간 후에 인증서 파일을 메일로 보내주었다.

 

 

보통 cert, key 이렇게 두개 파일이 들어있고, 방화벽용 파일을 따로 보내주는 곳도 있었다.

그럼 이제 이 파일들로 무엇을 해야하는가

 

2. pem 파일 안의 코드들을 가동중인 웹서버 NGINX로 옮기기

nginx를 접속해주자. 보통 SSL파일은 최상위 폴더에서 

/etc/nginx/SSL 폴더 안에 존재한다.

 

 

기존 파일 백업을 잘해두자.(혹여나 그냥 바꿨는데 오류나면 낭패다.)

그리고 기존 파일명과 같게, 형식도 같게 해서 해당 폴더에 새 인증서 파일을 넣어준다.

 

3. NGINX의 conf.d(설정) 확인

vi 명령어를 통해 conf.d파일을 열어서 설정을 확인한다.

폴더의 위치나 파일명이 맞는지 확인하면 된다.

 

4. nginx 재기동

sudo nginx -t

명령어로 별 문제 없는지 테스트 한번 해주고

 

이런 결과 나오면 nginx를 재기동해주면 된다.

sudo service nginx restart

 

5. 호스팅업체를 이용중인 경우 SSL인증서 파일 전달 후 적용 요청

 

이렇게 한 후 SSL인증서가 잘 적용되었는지 확인하면 된다.

인증서 확인 방법은 다음과 같다.

 

브라우저에서 url왼쪽에 아이콘 클릭

 

뜨는 창에서 '이 연결은 안전합니다.' 클릭

 

뜨는 창에서 '인증서가 유효함' 클릭

 

 

그럼 이렇게 인증서 정보와 만료일이 나온다.

 

여기서 인증서 만료일이 옳게 바뀌었으면 잘 적용된 것이다!

반응형
반응형

문제

10진법 수 N이 주어진다. 이 수를 B진법으로 바꿔 출력하는 프로그램을 작성하시오.

10진법을 넘어가는 진법은 숫자로 표시할 수 없는 자리가 있다. 이런 경우에는 다음과 같이 알파벳 대문자를 사용한다.

A: 10, B: 11, ..., F: 15, ..., Y: 34, Z: 35


입력

첫째 줄에 N과 B가 주어진다. (2 ≤ B ≤ 36) N은 10억보다 작거나 같은 자연수이다.


출력

첫째 줄에 10진법 수 N을 B진법으로 출력한다.


예제 입력 예제 출력
60466175 36 ZZZZZ

풀이

10진법수 K를 N진법 수로 변환하는 방법은 K를 N으로 나눈 나머지를 역순서대로 배열하는 것이다.

 


코드

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        String[] temp = line.split(" ");
        int n = Integer.parseInt(temp[0]);
        int m = Integer.parseInt(temp[1]);
        String[] array = {
                "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
                "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
                "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
                "U", "V", "W", "X", "Y", "Z"
        };

        String answer = "";

        while(n/m>0){
            n=n/m;
            answer += array[n%m];
        }
        answer += array[n%m];

        System.out.println(answer);

    }
}
반응형
반응형

문제

아직 글을 모르는 영석이가 벽에 걸린 칠판에 자석이 붙어있는 글자들을 붙이는 장난감을 가지고 놀고 있다. 

이 장난감에 있는 글자들은 영어 대문자 ‘A’부터 ‘Z’, 영어 소문자 ‘a’부터 ‘z’, 숫자 ‘0’부터 ‘9’이다. 영석이는 칠판에 글자들을 수평으로 일렬로 붙여서 단어를 만든다. 다시 그 아래쪽에 글자들을 붙여서 또 다른 단어를 만든다. 이런 식으로 다섯 개의 단어를 만든다. 아래 그림 1은 영석이가 칠판에 붙여 만든 단어들의 예이다. 

A A B C D D
a f z z 
0 9 1 2 1
a 8 E W g 6
P 5 h 3 k x

<그림 1>

한 줄의 단어는 글자들을 빈칸 없이 연속으로 나열해서 최대 15개의 글자들로 이루어진다. 또한 만들어진 다섯 개의 단어들의 글자 개수는 서로 다를 수 있다. 

심심해진 영석이는 칠판에 만들어진 다섯 개의 단어를 세로로 읽으려 한다. 세로로 읽을 때, 각 단어의 첫 번째 글자들을 위에서 아래로 세로로 읽는다. 다음에 두 번째 글자들을 세로로 읽는다. 이런 식으로 왼쪽에서 오른쪽으로 한 자리씩 이동 하면서 동일한 자리의 글자들을 세로로 읽어 나간다. 위의 그림 1의 다섯 번째 자리를 보면 두 번째 줄의 다섯 번째 자리의 글자는 없다. 이런 경우처럼 세로로 읽을 때 해당 자리의 글자가 없으면, 읽지 않고 그 다음 글자를 계속 읽는다. 그림 1의 다섯 번째 자리를 세로로 읽으면 D1gk로 읽는다. 

그림 1에서 영석이가 세로로 읽은 순서대로 글자들을 공백 없이 출력하면 다음과 같다:

Aa0aPAf985Bz1EhCz2W3D1gkD6x

칠판에 붙여진 단어들이 주어질 때, 영석이가 세로로 읽은 순서대로 글자들을 출력하는 프로그램을 작성하시오.


입력

총 다섯줄의 입력이 주어진다. 각 줄에는 최소 1개, 최대 15개의 글자들이 빈칸 없이 연속으로 주어진다. 주어지는 글자는 영어 대문자 ‘A’부터 ‘Z’, 영어 소문자 ‘a’부터 ‘z’, 숫자 ‘0’부터 ‘9’ 중 하나이다. 각 줄의 시작과 마지막에 빈칸은 없다.


출력

영석이가 세로로 읽은 순서대로 글자들을 출력한다. 이때, 글자들을 공백 없이 연속해서 출력한다. 


 

예제 입출력

입력 출력
ABCDE
abcde
01234
FGHIJ
fghij
Aa0FfBb1GgCc2HhDd3IiEe4Jj
AABCDD
afzz
09121
a8EWg6
P5h3kx
Aa0aPAf985Bz1EhCz2W3D1gkD6x

풀이

-> Scanner로 입력을 받아서 반복문을 통해 이차원 배열에 그대로 넣어준다. 출력 할 때는 반복문의 순서만 고려해서 새로로 출력해주며, null값이나 빈값이 있는 경우 건너뛴다.


코드

 

import java.lang.reflect.Array;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[][] chars = new String[5][15];
        for(int i=0;i<5;i++){
            String line = sc.nextLine();
            String[] temp = line.split("");
            for(int j=0;j<temp.length;j++){
                chars[i][j] = temp[j];
            }
        }

        for(int j=0;j<15;j++){
            for(int i=0;i<5;i++){
                if(chars[i][j]!=null&&!chars[i][j].equals("")){
                    System.out.print(chars[i][j]);
                }
            }
        }

    }
}​

 

반응형
반응형

문제

N*M크기의 두 행렬 A와 B가 주어졌을 때, 두 행렬을 더하는 프로그램을 작성하시오.


입력

첫째 줄에 행렬의 크기 N 과 M이 주어진다. 둘째 줄부터 N개의 줄에 행렬 A의 원소 M개가 차례대로 주어진다. 이어서 N개의 줄에 행렬 B의 원소 M개가 차례대로 주어진다. N과 M은 100보다 작거나 같고, 행렬의 원소는 절댓값이 100보다 작거나 같은 정수이다.


출력

첫째 줄부터 N개의 줄에 행렬 A와 B를 더한 행렬을 출력한다. 행렬의 각 원소는 공백으로 구분한다.


 

예제 입출력

입력 출력
3 3
1 1 1
2 2 2
0 1 0
3 3 3
4 4 4
5 5 100
4 4 4
6 6 6
5 6 100

 

풀이

-> 있는 그대로 반복문을 통해 입력받은 값들을 A, B 배열에 넣어준 후에 더한 값을 C에 넣어서 그대로 출력하였다.


 

코드

import java.lang.reflect.Array;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] input = sc.nextLine().split(" ");
        int N = Integer.parseInt(input[0]);
        int M = Integer.parseInt(input[1]);

        int[][] A = new int[N][M];
        int[][] B = new int[N][M];
        int[][] C = new int[N][M];

        for(int i=0;i<N;i++){
            String line = sc.nextLine();
            for(int j=0;j<M;j++){
                String[] lineArray = line.split(" ");
                A[i][j] = Integer.parseInt(lineArray[j]);
            }
        }

        for(int i=0;i<N;i++){
            String line = sc.nextLine();
            for(int j=0;j<M;j++){
                String[] lineArray = line.split(" ");
                B[i][j] = Integer.parseInt(lineArray[j]);
            }
        }

        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                C[i][j] = A[i][j] + B[i][j];
                System.out.print(C[i][j] + " ");
            }
            System.out.println();
        }
    }
}
반응형
반응형

문제

인하대학교 컴퓨터공학과를 졸업하기 위해서는, 전공평점이 3.3 이상이거나 졸업고사를 통과해야 한다. 그런데 아뿔싸, 치훈이는 깜빡하고 졸업고사를 응시하지 않았다는 사실을 깨달았다!

치훈이의 전공평점을 계산해주는 프로그램을 작성해보자.

전공평점은 전공과목별 (학점 × 과목평점)의 합을 학점의 총합으로 나눈 값이다.

인하대학교 컴퓨터공학과의 등급에 따른 과목평점은 다음 표와 같다.

A+ 4.5
A0 4.0
B+ 3.5
B0 3.0
C+ 2.5
C0 2.0
D+ 1.5
D0 1.0
F 0.0

P/F 과목의 경우 등급이 P또는 F로 표시되는데, 등급이 P인 과목은 계산에서 제외해야 한다.

과연 치훈이는 무사히 졸업할 수 있을까?


 

입력

20줄에 걸쳐 치훈이가 수강한 전공과목의 과목명, 학점, 등급이 공백으로 구분되어 주어진다.


출력

치훈이의 전공평점을 출력한다.

정답과의 절대오차 또는 상대오차가 10−4 이하이면 정답으로 인정한다.


제한

  • 1 ≤ 과목명의 길이 ≤ 50
  • 과목명은 알파벳 대소문자 또는 숫자로만 이루어져 있으며, 띄어쓰기 없이 주어진다. 입력으로 주어지는 모든 과목명은 서로 다르다.
  • 학점은 1.0,2.0,3.0,4.0중 하나이다.
  • 등급은 A+,A0,B+,B0,C+,C0,D+,D0,F,P중 하나이다.
  • 적어도 한 과목은 등급이 P가 아님이 보장된다.

예제 입출력

입력 출력
ObjectOrientedProgramming1 3.0 A+
IntroductiontoComputerEngineering 3.0 A+
ObjectOrientedProgramming2 3.0 A0
CreativeComputerEngineeringDesign 3.0 A+
AssemblyLanguage 3.0 A+
InternetProgramming 3.0 B0
ApplicationProgramminginJava 3.0 A0
SystemProgramming 3.0 B0
OperatingSystem 3.0 B0
WirelessCommunicationsandNetworking 3.0 C+
LogicCircuits 3.0 B0
DataStructure 4.0 A+
MicroprocessorApplication 3.0 B+
EmbeddedSoftware 3.0 C0
ComputerSecurity 3.0 D+
Database 3.0 C+
Algorithm 3.0 B0
CapstoneDesigninCSE 3.0 B+
CompilerDesign 3.0 D0
ProblemSolving 4.0 P
3.284483
BruteForce 3.0 F
Greedy 1.0 F
DivideandConquer 2.0 F
DynamicProgramming 3.0 F
DepthFirstSearch 4.0 F
BreadthFirstSearch 3.0 F
ShortestPath 4.0 F
DisjointSet 2.0 F
MinimumSpanningTree 2.0 F
TopologicalSorting 1.0 F
LeastCommonAncestor 2.0 F
SegmentTree 4.0 F
EulerTourTechnique 3.0 F
StronglyConnectedComponent 2.0 F
BipartiteMatching 2.0 F
MaximumFlowProblem 3.0 F
SuffixArray 1.0 F
HeavyLightDecomposition 4.0 F
CentroidDecomposition 3.0 F
SplayTree 1.0 F
0.000000

풀이

-> 과목명은 필요없으므로, map에다가 등급과 학점값을 담아두고, Scanner를 통해서 입력받은 값의 두번째 값과 세번째 값을 가지고 총점과 총학점을 계산하였다. 오차는 어느정도 인정하기에 소수점 자릿수까지 6자리로 표현해서 출력하지는 않았다.


코드

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        HashMap<String, Double> map = new HashMap<>();
        map.put("A+",4.5);
        map.put("A0",4.0);
        map.put("B+",3.5);
        map.put("B0",3.0);
        map.put("C+",2.5);
        map.put("C0",2.0);
        map.put("D+",1.5);
        map.put("D0",1.0);
        map.put("F",0.0);

        int count = 1;
        double sum = 0;
        double gradeSum = 0; // 학점총점
        while(count<=20){
            String line = sc.nextLine().trim(); // 앞뒤 공백 제거
            String[] content = line.split(" ");
            double gradeDouble = Double.parseDouble(content[1]);
            String grade = content[2];
            if(!grade.equals("P")){
                double changedGrade = map.get(grade);
                sum += gradeDouble*changedGrade;
                gradeSum += gradeDouble;
            }
            count++;
        }
        double answer = sum/gradeSum;
        System.out.println(answer);

    }
}
반응형

+ Recent posts