전체 글
[Spring] Custom Exception Handler
Spring에서 exception을 다루는 방식에 대해 다룰 것이다. 총 4개의 파일을 만든다. 디렉토리 구성 exception - CustomException.java - ErrorCode.java - ErrorResponse.java - GlobalExceptionHandler.java 이렇게 된다. 1. CustomException RuntimeException을 extend한 것으로, 선언한 ErrorCode를 가지고 있다. exception/CustomException.java @Getter @AllArgsConstructor public class CustomException extends RuntimeException{ private final ErrorCode errorCode; } 2. ..
[Spring + Jwt] Spring Boot + Spring Security + Redis + Jwt를 이용한 회원가입 및 로그인
https://bcp0109.tistory.com/301 이 글을 많이 참고했다. spring security를 이용하는 이유는 spring에서 로그인 기능을 구현하기 위해서이고 session이 아니라 token을 사용하려 하는 이유는 앱 환경에서 로그인을 유지시켜주기 위함이다. jwt는 그 이유 때문이고, redis는 jwt를 관리하기 위함이다. 1. 환경 설정 https://blog.naver.com/jhi990823/222509215989 위 게시글을 따라가면서 docker 위에 redis를 올리면 된다. https://blog.naver.com/jhi990823/222505297298 이후엔 이 게시글을 참조해서 redis를 사용할 수 있는 함수를 만든다. build.gradle implement..
build server 부터 배포까지 - 5. GKE Spring Redis 배포 - Local, CI Server, Deploy Server에서 Redis와 연동
이번엔 로그인 기능에서 사용하는 토큰을 올리기 위해 redis를 올려보고자 한다. 1. Local /application.properties spring.redis.host=127.0.0.1 spring.redis.port=6379 이걸 추가한다. /local/docker-compose.yml version: "3" services: mysql: image: mysql:5.6 environment: MYSQL_DATABASE: bizschema MYSQL_ROOT_PASSWORD: rootpw MYSQL_USER: devroot MYSQL_PASSWORD: devpw LANG: C.UTF-8 volumes: - local-mysqlvol:/var/lib/mysql ports: - 3306:3306 com..
build server 부터 배포까지 - 4. GKE Spring MySQL 배포 - Local, CI Server, Deploy Server에서 MySQL 연동
이전 글에서는 deploy server인 GKE에서 MySQL의 IP를 할당받아서 사용했다. 그러나, 이 방법을 사용하면 test할 때 실 서버의 db를 이용하기 때문에 상당히 위험한 방식이라 생각한다. 이를 보완하기 위해 다른 방법을 이용하고자 한다. 지금 구축되어있는 서버는 크게 3가지이다. 로컬, CI 서버, Deploy 서버. 먼저 로컬과 CI 서버에 추가적으로 docker 위에 mysql을 올리고 임의로 id, pw를 지정한다. 그러면 로컬에서 빌드할 때는 로컬에 있는 docker의 mysql을, CI 서버에서 빌드할 때는 CI 서버의 docker에 있는 mysql을 참조할 것이다. 마지막으로 GKE는 deploy.yml 파일을 작성했을 때 만든, 실제 서비스 DB mysql을 참조하게 될 것이..
build server 부터 배포까지 - 3. GKE Spring MySQL 배포 - MySQL 배포 및 Mysql + Spring 배포
먼저, gcp terminal에서 편집기를 이용할 수 있다! 어제 vs code로 연결할라고 아득바득 할 필요가 없었다... 1. mysql 배포 GKE 기반 kubenertes에서 mysql을 수행하기 위해서는 pvc 생성, deploy 및 service가 필요하다. /home/hyelie/k8s-test/mysql-pvc.yml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi GKE에서 1Gi의 pvc를 만들겠다는 것이다. 그냥 kubernetes만 사용하낟면 pvc, pv도 생성해야 하지만 gke이기 때..
build server 부터 배포까지 - 2. GKE Spring MySQL 배포 - GKE 클러스터 생성 및 spring 예제 배포
내 프로젝트에서 FE가 필요없고 BE와 DB만 있으면 되기 때문에 이에 대한 kubernetes 환경을 구축하고자 한다. 1. GKE 클러스터 생성 공부하는 게 목적이니까, 표준으로 일단 해보자. 기본 사항에선 딱히 건들 게 없고, 수정할 거라면 default-pool - 노드 - 머신 계열 정도만 골라주면 될 것이다.그러면 클러스터 하나가 생성된다. VM instance 목록에 들어가 보면 3개의 vm이(노드들) 생성되어 있다. 이후 우상단의 gcloud shell을 실행시킨다. 나는 지금 활성화되어 있어서 꺼져 있다. https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl?hl=ko 그러면 master node..
[GCP] GKE 중지시키기
gcloud shell에서 아래 명령어를 입력하면 된다. 우상단의 gcloud shell을 활성화 시키고, 위치를 본다. gcloud container clusters resize $NAME --size=0 --zone=$LOCATION 위 명령어에서 $NAME은 컨테이너 이름인 cluster-1을, $LOCATION은 위치인 us-central1-c를 입력하면 된다. 이걸 하면 vm instance에 있던 node들이 사라지는 걸 볼 수 있다.
[GCP] Cloud IP가 바뀌었을 때, 수정해야 할 것
바로 앞 포스팅에서 cloud의 external/public ip가 바뀌면 4가지를 바꾸어야 한다. 1) jenkins - gitlab webhook ip 변경 jenkins 구성 - gitlab webhook ip를 gitlab에 재등록해야 함. 2) sonarqube ip 재등록 jenkinsfile에 있는 stage('SonarQube Analysis'){ steps{ withSonarQubeEnv('sonar-server'){ sh './gradlew sonarqube -Dsonar.projectKey=ciserver -Dsonar.host.url=http://35.225.76.162:9000 -Dsonar.login=8ec502617dd7b039e3179fadb5ec83f0127544cc' } ..
build server 부터 배포까지 - 1. GCP + Docker + Jenkins + Gitlab + JUnit + SonarQube + GCR image push
그럼 이제 GCP 위에 docker를 올리고, docker 위에 jenkins, sonarqube를 올리고 gitlab webhook으로 pull받아서 build 후 GCR push까지, 한 번에 다뤄보고자 한다. 자세한 모든 화면은 이전 포스팅들을 참고. *** 지금 이 글대로 구성하면, ci server에서 jenkins data가 저장될 곳이 없어 재시작하면 전부 날아간다. 이를 고려해서, volume을 추가하는 것을 권장한다. 1. docker-compose로 GCR 위에 docker, docker 위에 jenkins, sonarqube 설치 /home/hyelie/compose/docker-compose.yml version: "3" services: jenkins: container_name:..
[GCP] GCP 기본 설정 - SSH로 접속하기 & 포트 열기 & docker 설치 & 고정 IP
먼저, AWS kubernetes 환경을 구성하려 했는데 AWS는 이것저것 설정할게 너무 많아서 GCP로 넘어가려 한다. 1. SSH 접속 https://ruuci.tistory.com/6 위 글을 참고했다. 먼저 C:\gcp 폴더를 만든다. 이후 vs code에서 C:\gcp에 접근해서 ssh-keygen -t rsa -f "파일 이름" -C "내 GCP 계정" 을 입력한다. 생성된 public key를 vm instance - metadata - ssh key에 복사한다. 이후 vs terminal에서 ssh -i "private key 경로.private key 파일이름" "사용자 이름"@"VM 외부 IP" 로 접속할 수 있다. 여기서 사용자 이름은 생성할 때 hyelie@postech.ac.kr ..
EC2 Docker Jenkins Spring Gitlab 자동 빌드 - 6. 수정사항, ECR push
1. 수정사항 원래는 docker 안에 jenkins가 있고, jenkins에서 docker로 접속하는 방식을 택했다. 근데 ECR에 push하기 위해서는 jenkins에서 docker를 실행해야 한다. 그래서 docker-compose.yml 파일을 조금 수정한다. /home/ec2-user/compose/docker-compose.yml version: "3" services: jenkins: container_name: jenkins image: jenkins/jenkins:lts user: root ports: - "8081:8080" volumes: - /var/run/docker.sock:/var/run/docker.sock - /home/ec2-user/compose/jenkins:/var/..
EC2 Docker Jenkins Spring Gitlab 자동 빌드 - 5. jenkins pipeline - JUnit + SonarQube
앞에서는 build step을 이용해서 추가했다. 그러나 jenkins에서 이걸 언제 하나하나 다 만지고 있나. 프로그래머처럼 code를 이용해서 각각의 step을 design할 수 있으며 - 이것이 jenkins pipeline이다. MSA는 빠른 배포가 목적이기 때문에 JUnit, SonarQube 등의 품질검사 pipeline을 구성한다. pipeline은 gradle build - JUnit test - SonarQube test - docker build, push - kubernetes deploy 이렇게 될 것임. pipeline으로 이것을 구성해 볼 것이다. 만약 2개 이상의 프로젝트가 있으면, 각각의 프로젝트를 jenkins project에 연결시켜서 각각 프로젝트의 image만 buil..
[Spring + Redis] Spring Redis 연동
dependency implementation 'org.springframework.boot:spring-boot-starter-data-redis' application.properties spring.redis.host=127.0.0.1 spring.redis.port=6379 RedisUtil.java import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; @Component ..
[Docker] Redis + Docker + 간단한 명령어
다른 db와 마찬가지로 docker에 올렸다. docker-compose.yml 중 일부 redis: image: redis:alpine hostname: redis-local ports: - 6379:6379 container_name: local-redis 실행 docker exec -it {container-id} redis-cli 기본적으로 redis는 key, value가 쌍으로 저장되는 database이다. key 조회 keys * 값 삽입 set {key} {value} ex) set key_one value_one key에 해당하는 value 조회 get {key} ex) get key_one 갱신 : 삽입과 동일. set {key} {value} ex) set key_one value_o..
[JPA] JPA Join 이슈, FETCH JOIN의 사용
Join 방향 이슈 A : B = 1 : N의 관계일 때 일반적으로 B에서 ManyToOne을 가지고 있다. 이 경우 B Join FETCH A는 되지만 A Join FETCH B를 하면 작동하지 않는다. 왜냐하면 B에서 A 정보는 있지만 A에서 B 정보는 없기 때문이다. 이를 해결하기 위해서는 - 양방향 관계를 넣던가, - B.getA()로 A 정보를 가져오던가, - SQL JOIN하듯 SELECT b FROM A a JOIN B b ON b.A = a; 이렇게 하면 된다. 그냥 INNER JOIN하는 것 처럼 된다. 다만 이러면 join을 해버리는 것이기 때문에 성능상 이슈를 생각해야 한다. Fetch Join의 사용 이유 그리고 또 하나. FETCH JOIN을 사용하는 이유를 깨달은 것 같은데. 처..
[JPA] JPQL FROM절 subquery를 해결하는 방법 (inline view)
문제 상황 - JPA의 FROM절에 subquery를 넣는 상황. 문제 상황은 다음과 같다. 킥보드 사용량에 대한 consumption entity가 있고, 킥보드의 이동 경로에 대한 coordinate entity가 있다. consumption : coordinate는 1 : n 관계이며, coordinate entity에 다대일 매핑만 되어 있다. @Entity @Getter @NoArgsConstructor @AllArgsConstructor @Table(name = "consumption") public class Consumption { @Id @Column(name = "consumption_id") @GeneratedValue(strategy = GenerationType.IDENTITY) ..
[Troubleshooting] Jenkins 잘 되던 build가 안 될 때
잘 되었던 build가 안되는 경우가 생겼다. 코드는 변함없는데. 그래서 이것저것 해보다가 용량 부족임을 알게 되었다. 쌓인 image, build log를 지우고 gcr에도 쌓인 image를 삭제하니 잘 된다. stage('Docker unused image remove'){ steps{ script{ sh 'docker image prune -a' } } } -a 옵션은 사용되지 않는 모든 image 삭제이다. build server에서는 실행중인 jenkins, mysql, sonar-qube 이외의 image는 사용되지 않기 때문에 모든 image를 삭제하게 했다.
[Spring] DTO와 Entity 간의 변환
Spring을 쓴다면 MVC 구조를 사용한다는 것을 전제로 깔고 갈 것이다. 따라서 Controller, Service, Repositoy, DB 순으로 flow가 이동하며, 이 과정에서 entity라는 객체와 DTO라는 객체를 사용한다. 정의를 먼저 살펴보자면, entity는 DB의 row 하나와 매핑되는 객체인 반면, DTO는 Data Transfer Object, 데이터를 옮기는 데 사용하는 객체이다. DTO의 필요성 DTO의 필요성에 대해서는 말할 필요도 없다. 만약 DTO가 없다고 가정해 보자. 그러면 entity를 사용자에게 노출시켜야 하는데, entity는 DB의 모든 column에 대한 정보를 가지고 있기 때문에 이를 사용자에게 노출시키는 것은 좋지 않다. 또한 entity에 내용이 부족해..
[JPA] JPA @IdClass에 관해,,,
JPA에서 IdClass는 entity의 key를 1개 이상의 column으로 지정할 수 있게 해 주는 기능이 있다. 구체적으로는 implements serializable 를 이용하는데, 이 idclass에 꼭 구현되어야 하는 함수가 2가지 있다. 바로 - equals : 두 객체의 내용이 같은지 equality를 비교해주는 함수 - hashCode : 두 객체가 같은 객체인지 identity를 비교해 주는 함수 이다. 이것을 구현해 주어도 되지만, @EqualsAndHashCode annotation을 사용해서 method를 생성할 수 있고, @Data annotation을 이용할 수도 있다. 왜냐하면 @Data annotation은 - @Getter - @Setter - @RequiredArgsCo..
[DB] MySQL 등 ERD에서 id를 long으로 두는 이유
먼저, sql table의 primary key를 id라는 이름으로, 특별한 값을 넣지 않고 long이나 int형으로 숫자로 많이 두곤 한다. sql에서 join이나 data 탐색 등의 경우의 수를 생각해 봤을 때, primary key에 유의미한, 그리고 식별이 되는 값을 넣는게 좋지 않을까? 실제로 성능은 이게 더 나올 것이다. 그러나 이렇게 하지 않는 이유는 1) 보안상의 이유 2) 확장성의 이유 크게 2가지가 있다고 생각한다. 먼저 primary key는 어떤 일이 있더라도 겹치면 안 된다는 것은 기본이다. 예를 들어서 member라는 table에 id를 member가 회원가입할 때 등록했던 id로 지정했다고 해 보자. 그러면 member.id는 varchar형태일 것이고, id는 중복이 되지 않..