본문 바로가기

전체 글36

MariaDB 내 중복된 데이터 삭제하기 MariaDB에서 중복된 데이터를 삭제하는 방법을 알아보겠습니다. SELECT col1, COUNT(col1) FROM tbl GROUP BY col1 HAVING COUNT(col1) > 1; 위 SELECT 쿼리를 통해 특정 열에서 같은 값을 가지는 데이터가 몇개 있는지 추출할 수 있습니다. DELETE t1 FROM tbl t1 JOIN tbl t2 ON t1.col1=t2.col1 WHERE t1.id > t2.id; 위 DELETE 쿼리를 통해 특정 열에서 같은 값을 가지는 데이터중 가장 먼저 생성된 한 행을 제외한 중복 데이터들을 삭제할 수 있습니다. 참조 https://www.mysqltutorial.org/mysql-delete-duplicate-rows/ 2023. 2. 27.
DB 정규화 (제 1정규형 ~ 제 3정규형, BCNF) DB 정규화(제 1정규형 ~ 제 3정규형, BCNF)에 대해 알아보겠습니다. 정규화(Normalization)란? 정규화는 이상현상이 있는 테이블을 기준에 따라 여러개로 나누어 이상현상을 없애는 작업을 말합니다. 이상현상(Anomaly)이란? 이상현상은 세 종류가 있습니다. 삽입 이상: 행(row) 삽입시 특정 컬럼(column)에 해당하는 값이 없어 null을 입력하는 현상 수정 이상: 행 수정시 중복된 데이터의 일부만 수정되는 데이터 불일치 현상 삭제 이상: 행 삭제시 같이 저장된 다른 정보까지 삭제되는 현상 예시를 통해 자세히 알아보겠습니다. 삽입 이상 '자이언츠'라는 작품을 추가한다고 가정해보겠습니다. 자이언츠의 작가는 작품 설명을 따로 등록하고 싶지 않아 작품 설명을 적지 않았습니다. 이 경우 .. 2023. 2. 13.
자주 사용하는 vim 단축키 vim 모드 vim에는 아래와 같이 네 가지 모드가 있다 Normal Mode 기본 모드로 파일 내에서 빠르게 이동할 수 있다. 다른 모드로 이동하기 위한 중간 지점 역할을 한다. Insert Mode 문자를 삽입하거나 변경하여 파일을 수정할 수 있다. Visual Mode 커서, 라인, 블럭 단위 별로 선택할 수 있다. Command Mode 파일 열기, 파일 닫기, 글자 찾아서 바꾸기, 저장 등의 명령을 하는 모드다. 각각의 모드는 Normal Mode에서 해당 키를 입력하여 전환할 수 있다. 각각의 모드에서 Normal Mode로 전환할 때는 esc를 눌러 전환할 수 있다. 지금 어떤 모드를 사용하고 있는지 모를 때는 esc를 눌러 기본 모드로 돌아오도록 하자. 자주 사용하는 vim 단축키 Inse.. 2023. 2. 6.
JPA에서 soft delete 처리하기 (@Where, @Filter) JPA에서 soft delete 처리하는 방법에 대해 알아보겠습니다. hard delete와 soft delete 데이터를 삭제할 때 크게 hard delete(물리 삭제)와 soft delete(논리 삭제) 두 가지 방법이 있습니다. hard delete hard delete는 SQL의 delete 명령어를 사용하여 직접 데이터를 삭제하는 방법입니다. hard delete의 경우 delete 쿼리가 발생하기 때문에 삭제 후 DB에서 조회할 수 없습니다. 장점으로 select시 성능이 soft delete보다 상대적으로 좋습니다. 단점으로 삭제된 데이터를 복구하기 어렵고, 비즈니스에 데이터를 활용할 수 없습니다. soft delete soft delete는 SQL의 update 명령어를 사용하여 특정 컬.. 2023. 2. 1.
ApplicationEventPublisher를 활용하여 서비스 강결합 문제 해결하기 ApplicationEventPublisher를 활용하여 트랜잭션 강결합 문제를 해결하는 방법을 알아보겠습니다. 프로젝트를 진행하다 보면 의도치 않게 서비스끼리 강결합되는 문제가 발생합니다. 아래 예시가 있습니다. UserService @Service @RequiredArgsConstructor @Transactional public class UserService { private final UserRepository userRepository; private final MailService mailService; public Long create(UserReqDto dto) { User user = userRepository.save(User.builder() .email(dto.getEmail()).. 2023. 1. 31.
한 컴퓨터에서 깃허브 계정 분리하여 사용하기 한 컴퓨터에서 여러 개의 깃허브 계정을 사용하는 법을 알아보자. 이 글에서는 편의상 개인용 / 업무용 계정 두 개를 사용한다고 가정하고 진행한다. SSH 키 생성 1. .ssh 폴더로 이동한다. $ cd ~/.ssh 2. 개인용 / 업무용 SSH 키 페어를 생성한다. $ ssh-keygen -t rsa -C "깃허브 이메일 계정" -f "id_rsa_식별자" ex) ssh-keygen -t rsa -C "cjsrhd94@gmail.com" -f "id_rsa_cjsrhd94" 3. 키 페어를 생성하기 위해 아래와 같이 사용할 비밀번호를 입력하라고 나오는데, 엔터를 눌러 넘어간다. Generating public/private rsa key pair. Enter passphrase (empty for no.. 2023. 1. 30.
메모리 스왑 설정하기 사내 개발서버에서 젠킨스를 사용하여 CI/CD 작업을 하고 있다. 그런데 종종 젠킨스가 동작할 때 메모리 점유율이 비정상적으로 높아지며 개발 서버가 다운되는 현상이 발생했다. 이에 메모리 용량을 임시적으로 늘리기 위해 개발서버에 메모리 스왑을 설정했다. 메모리 스왑 방법은 AWS에서 친절하게 안내하고 있다. https://aws.amazon.com/ko/premiumsupport/knowledge-center/ec2-memory-swap-file/ 스왑 파일을 사용하여 Amazon EC2 인스턴스의 스왑 공간으로 메모리 할당 닫기 John 씨의 동영상을 통해 자세히 알아보기(3:37) aws.amazon.com 메모리 스왑 설정 1. dd 명령을 사용하여 스왑 파일을 생성한다. bs는 블록 크기이고, c.. 2023. 1. 15.
Spring에서 AWS RDS MySQL Replication 적용하기 현재 진행하고 있는 개인 프로젝트에서 DB로 AWS RDS MySQL 한 대만 사용하고 있다. 캐시 서버를 운용하여 DB에 가해지는 부하를 줄인다고 하더라도 트래픽의 증가에 따라 한 대 뿐인 데이터베이스에 장애가 발생할 가능성이 있다. 이에 이러한 상황에 대비하기 위해 AWS RDS 환경에서 MySQL Replication을 적용해보았다. 이해를 돕기위해 실제 프로젝트에 사용한 깃허브 레포지토리의 패키지 주소를 공유합니다. 아래 주소를 참고해주세요. https://github.com/ProjectShallWe/shallwe-backend/tree/main/src/main/java/com/project/board/global/datasource AWS RDS 설정 기존 RDS의 읽기 전용 DB 하나를 생성.. 2022. 11. 29.
AWS SSL 인증서 발급 및 LoadBalancer로 Https 적용하기 SSL 인증서 발급 1. AWS에 접속하여 ACM을 검색하여 들어갑니다. 2. 인증서 요청을 클릭한 뒤 퍼블릭 인증서 요청에 체크 후 다음 버튼을 누릅니다. 3. 도메인 이름에 구입한 도메인 이름을 작성합니다. 기본적으로 '도메인 이름.com' , 'www.도메인 이름.com'과 같이 설정할 수 있으며, *.도메인 이름.com과 같이 서브 도메인까지 모두 포함할 수 있습니다. 아래와 같이 기본 설정된 대로 두고 요청 버튼을 클릭합니다. 4. 다음과 같이 몇분 뒤 상태가 '발급됨'으로 변경되면 완료입니다. LoadBalancer 만들기 1. EC2에 들어가서 '로드 밸런서' - '로드 밸런서 생성' 버튼을 클릭합니다. 2. 좌측의 '어플리케이션 로드 밸런서' 생성 버튼을 클릭합니다. 3. 로드 밸런서 이름.. 2022. 11. 14.
서버 확장 전략: 스케일 업(Scale Up) vs 스케일 아웃(Scale Out) 서버를 확장하는데 크게 두가지 전략이 있다. Scale Up Scale Up은 수직적인 확장 방법을 뜻한다. 서버에 CPU나 메모리 등을 추가하여 서버 자체의 성능을 개선하여 처리능력을 향상시키는 방법이다. 장점 서버의 장비를 추가하거나 교체하면 되기 때문에 구축 및 설계가 간단하다. 별도의 컨트롤러나 네트워크 인프라 비용 등이 발생하지 않는다. 별도의 서버를 추가하지 않기 때문에 데이터 정합성 문제에서 자유롭다. 단점 하드웨어 성능 업그레이드에 한계가 있다. 하나의 서버에서 모든 트래픽을 감당해야 하기 때문에 서버가 다운되면 시스템 전체의 장애로 이어질 수 있다. Scale Out Scale Out은 수평적인 확장 방법을 뜻한다. 서버의 대수를 늘려서 처리능력을 향상시키는 방법니다. 장점 필요에 따라 .. 2022. 9. 25.
Querydsl을 활용한 조건 검색 기능 개선 프로젝트 내 검색 기능을 동적 쿼리를 활용해 개선해보고 싶어 개인 프로젝트에 Querydsl을 사용하기로 결정했다. 기존 코드의 문제점 PostController // PostController.class @RestController @RequiredArgsConstructor @RequestMapping("/api/post") public class PostController { private final PostService postService; // controller code... @GetMapping("/search") public Page getPostsBySearchKeywordInBoard( @RequestParam("board") Long boardId, @RequestParam Inte.. 2022. 8. 7.
스프링 S3 연동 오류: No valid instance id defined 오류org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cloud.aws.core.env.ResourceIdResolver.BEAN_NAME': Invocation of init method failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'stackResourceRegistryFactoryBean' defined in class path resource [org/springframework/c.. 2022. 7. 27.
본인 확인은 어떤 layer에서 이루어져야 할까? 개인 프로젝트를 진행하며 고민한 문제가 있다. 현재 프로젝트에서 게시판에 작성된 글이나 댓글을 update하거나 delete할 때, 작성한 본인 혹은 관리자만 삭제할 수 있게 만들고 싶었다. 1. Service Layer // PostService.class @Service @RequiredArgsConstructor public class PostService { private final UserRepository userRepository; private final PostRepository postRepository; // Service code... @Transactional public Long update(String email, Long id, PostUpdateRequestDto updat.. 2022. 7. 22.
bash: ./gradlew: Permission denined 원인AWS EC2 환경에서 어플리케이션 빌드를 하기 위해 ./gradlew clean build 와 같은 명령어를 사용한다.Window 환경에서 작업해서 소스를 깃허브에 push하는 경우, Window 환경에서 파일 생성시 기본 권한이 644로 설정되기 때문에 755로 변경이 필요하다고 한다.해결$ chmod +x gradlew위 코드를 터미널에 입력한 후 다시 ./gradlew clean build를 입력하면 빌드가 되는 것을 확인할 수 있다. 2022. 7. 22.
AWS EC2와 RDS 연결하기 AWS EC2와 RDS를 연결하는 법에 대해 알아보겠습니다. EC2와 RDS 연결하기 1. 우선 작업에 앞서 연결할 EC2 인스턴스 정보창에 들어가 VPC ID, 보안 그룹을 기억한다. 2. 좌측 네트워크 및 보안에서 보안 그룹을 선택한 뒤 '보안 그룹 생성' 버튼을 클릭한다. 3. 보안 그룹 이름과 설명을 작성한다. VPC는 EC2 인스턴스 정보창에 있던 VPC ID를 선택해준다. 사용하는 RDS는 내 로컬 PC와 EC2에서 접근할 수 있어야 한다. 인바운드 규칙 유형은 사용하는 RDS DB를 선택한다. 소스 하나는 EC2 인스턴스 정보창에 있던 보안 그룹을 선택해주고, 나머지 하나는 내 IP를 선택해준다. '보안 그룹 생성' 버튼을 눌러 작업을 완료한다. 4. RDS 인스턴스로 이동해 수정 버튼을 누.. 2022. 7. 21.
FileZilla 사용법 (2023.02.06 최종 수정) 프로젝트를 진행하다보면 내 컴퓨터에서 다른 서버로 파일들을 옮겨 줘야 할 때가 있다. 이럴 경우 ftp 서비스를 이용하여 파일을 쉽게 주고 받을 수 있다. 오늘은 ftp 서비스 중 FileZilla라는 프로그램을 이용하여 , 내 컴퓨터에서 다른 서버로 파일을 손쉽게 옮기는 법을 알아보자. FileZilla 사용법 1. FileZilla 홈페이지에 들어가서 FileZilla 클라이언트를 다운로드 한다. 2. 프로그램 실행 후 아래 빨간색으로 강조한 연결 버튼을 누른다. 3. New site를 클릭해 새로운 사이트를 만들어주고 이름을 식별할 수 있게 바꿔준다. 프로토콜의 종류는 두 가지가 있다. FTP의 경우 일반적인 파일 전송 프로토콜로 보안이 취약하다. 기본값으로 21번.. 2022. 7. 21.
AWS EC2(Ubuntu 22.04)에 자바 설치하기 OpenJDK 설치하기 sudo apt-get update 1. 위 명령어를 입력하여 저장소에서 사용할 패키지의 정보를 얻는다. sudo apt-get install openjdk-11-jdk sudo apt-get install openjdk-11-jre (jre만 설치할 경우) 2. 업데이트가 완료되면 프로젝트에 맞는 OpenJDK 버전을 설치한다. java -version // 다음과 유사하게 출력된다. openjdk version "11.0.15" 2022-04-19 OpenJDK Runtime Environment (build 11.0.15+10-Ubuntu-0ubuntu0.22.04.1) OpenJDK 64-Bit Server VM (build 11.0.15+10-Ubuntu-0ubuntu0... 2022. 7. 19.
AWS EC2(Ubuntu 22.04) 인스턴스 생성하기 인스턴스 생성 1. 우선 인스턴스 시작에 앞서 본인의 리전이 '서울'로 설정되어있는지 확인하고 변경해준다. 2. 상단의 검색창에 EC2를 검색하고, 인스턴스 시작버튼을 누른다. 3. EC2의 이름을 설정해주고, 어떤 OS를 사용할 것인지 정한다. 필자의 경우 Ubuntu Server 22.04 LTS 를 선택하였다. 리눅스와 우분투, 그리고 우분투 LTS 버전 간 약간의 차이가 있을 수 있다. 4. 인스턴스 유형은 프리티어에서 사용 가능한 t2.micro를 선택해준다. 만약 다른 인스턴스 유형을 선택한다면, 과금이 되니 주의하자. 5. 키 페어(로그인) 부분은 '새 키 페어 생성'을 눌러 키 페어 이름을 설정하고 키 페어 유형은 RSA, 프라이빗 키 파일 형식은 .pem으로 설정 한 후 '키페어 생성' .. 2022. 7. 19.
@Column(nullable = false) 와 @NotNull 중 무엇을 사용해야 할까? 개인 프로젝트 도중 Entity에 DB 제약조건을 적용하다가 궁금점이 생겼다. @Column(nullable = false) // User.java @Entity @Table(name = "user_table") @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @EntityListeners(AuditingEntityListener.class) public class User extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(unique = true, nullable = false) @Email private Strin.. 2022. 7. 18.
유클리드 호제법으로 최대공약수 최소공배수 구하기 개념 2개의 자연수 a,b에서 a를 b로 나눈 나머지를 r이라 한다면 (단 a > b), a와 b의 최대공약수는 b와 r의 최대 공약수와 같다. 이 성질에 따라 b를 r로 나눈 나머지 r`를 구하고, 다시 r을 r`으로 나눈 나머지를 구하는 과정을 반복하여 나머지가 0이 되었을 때 나누는 수가 a와 b의 최대공약수이다. 최대공약수 // a > b 일 때, int gcd(int a, int b) { while (b > 0) { int tmp = a; a = b; b = tmp % b; } return a; } 반복문을 사용하여 위와 같이 표현할 수 있다. // a > b 일 때, int gcd(int a, int b) { if (a % b == 0) { return b; } return gcd(b, a%b.. 2022. 7. 17.
Math 클래스 메서드 정리 오늘은 유용하게 사용되는 Math 클래스 메서드들을 정리하려한다. sqrt() 제곱근을 구한다. int num = 16; System.out.println(Math.sqrt(num)); /* double Math.sqrt(double) 출력 결과: 4.0 */ random() 0과 1사이의 실수값을 출력한다.(0 포함) System.out.println(Math.random()); /* double Math.random() 출력 결과: 0.11231300330818705 */ abs() 절대값을 구한다. double num = -15.5; System.out.println(Math.abs(num)); /* double Math.abs(double) 출력 결과: 15.5 */ ceil() 소숫점이 있을 때.. 2022. 7. 14.
String 클래스 메서드 정리 String 클래스는 참조 타입으로 여러 메서드들을 내장하고 있다. charAt() 인덱스에 위치한 문자를 반환하는 메서드이다. String text = "abcdef"; System.out.println(text.charAt(2)); /* char string.charAt(int index) 출력 결과: c */ concat() 문자열을 뒤에 결합한다. String text = "abcdef"; System.out.println(text.concat("g")); /* String String.concat(String s); 출력 결과 : abcdefg */ contains() 문자열을 포함하고 있는지 확인한다. String text = "abcdef"; System.out.println(text.con.. 2022. 7. 14.
외래 키가 있는 테이블을 truncate/delete하는 방법 외래키가 존재하는 테이블 내의 데이터를 삭제할 때 위와 같은 에러 메시지가 발생한다. set FOREIGN_KEY_CHECKS = 0; TRUNCATE user_table; set FOREIGN_KEY_CHECKS = 1; 위와 같이 외래키를 체크 하지 않는 설정으로 변경해준 후, truncate하면 정상적으로 실행되는 것을 알 수 있다. 이후 반드시 외래키를 체크하게 설정을 변경해주어야 한다. 2022. 7. 11.
MySQL 더미 데이터 생성하기 MySQL에서 더미 데이터를 생성하는 법을 알아보겠습니다. 쿼리 성능을 측정하기 위해 더미 데이터를 10만개 정도를 Insert 할 일이 있었습니다. 가장 먼저 사용한 방법은 서버 내부에서 for문을 사용해 Insert 해주는 방법이었습니다. 그러나 이 방법은 1만개 정도의 데이터를 Insert 하는데 분 단위 이상의 시간이 소요되어 다른 방법을 찾아야 했습니다. 다음으로 사용한 방법은 오늘 알아볼 MySQL에 직접 Insert 쿼리를 작성해주는 방법이었습니다. 아래는 더미 데이터를 10만개 생성하는 프로시저 쿼리문입니다. // MySQL Query문 DELIMITER $$ DROP PROCEDURE IF EXISTS loopInsert$$ CREATE PROCEDURE loopInsert() BEGIN.. 2022. 7. 11.
yaml 파일을 그룹으로 관리하기 yaml 파일을 그룹으로 관리하는 법을 알아보자. application-dev.yml application.yml 프로젝트를 진행하다 보니 yaml 파일 내 외부에 유출되서는 안되는 정보들이 늘어났다. 내 프로젝트는 RDS나 S3등 다양한 AWS 서비스들을 사용하여 connection 정보들이 yaml파일 내 산재해 있었다. 이에 외부에 공개해서는 안되는 yaml 파일들을 모듈화시켜 깃허브에 올라가지 않게 관리하기 위해 spring.profiles.group 옵션을 사용하였다. application.yml application-dev.yml application-rds.yml .gitignore spring.profiles.group 옵션은 jar파일 실행시 그룹화된 프로필 내의 모든 설정 정보를 전달한.. 2022. 7. 9.
AWS RDS를 이용하여 MySQL 사용하기 프로젝트를 진행하던중 DB를 어떻게 해야할지 고민이었다. 배포할 예정이 없는데 로컬 환경이 아닌 클라우드 환경에서 RDS를 사용하는 것이 큰 의미가 있을까 싶었다. 그럼에도 기술을 한 번 사용해보는 것이 개인적으로 도움이 될 것이라 생각해 프로젝트에 적용해보기로 하였다. 1. AWS RDS에 들어가 '데이터베이스 생성' 버튼을 누르면 위 화면으로 시작된다. 위와 같이 '표준 생성' - 'MySQL'을 선택해준다. 2. 템플릿은 반드시 '프리티어'를 설정해준다. 그래야 RDS 사용으로 인해 과금될 위험이 줄어들게 된다. DB 인스턴스 식별자는 해당 RDS의 이름이다. 프로젝트와 관련 있는 이름으로 짓는 것이 향후 RDS에 접속했을 때 해당 인스턴스가 어떤 용도로 사용되고 있는 DB인지 확인하기 편하다. 자.. 2022. 7. 7.
Springboot에서 Redis Cache 적용하기 (2022.12.05 최종 수정) 개인 프로젝트를 진행하던 중 페이지 별로 반복 호출되는 API들이 있었다. 대표적으로 게시판 별 추천글 목록, 전체 인기글 목록 등이 있었다. 이러한 반복적으로 호출되는 쿼리를 줄여 부하 분산을 하기 위해 프로젝트에 Spring Cache를 도입하였다. 왜 Redis를 선택했을까? 캐시는 크게 로컬 캐시와 글로벌 캐시 두 가지가 있다. 로컬 캐시는 각각의 WAS 내부 저장소에 캐시를 저장하는 방식이다. WAS의 리소스를 사용하기 때문에 속도는 빠르지만 Scale-Out 방식의 서버 확장시 서버간 데이터 공유가 안되어 일관성 문제가 발생할 수 있다는 문제가 있다. 글로벌 캐시는 별도의 캐시 서버를 두고 WAS에서 캐시서버를 참조하는 방식이다. 캐시 데이터를 얻을 때 마다 .. 2022. 6. 27.
스프링 스케줄러(@Scheduled) 사용하는 법 스프링 스케줄러를 사용하는 법에 대해 알아보자. @Scheduled 우선 스프링 스케줄러를 사용하기 위해서 간단한 세팅을 해주어야 한다. @Configuration @EnableScheduling public class ScheduledConfig { } 1. 스케줄러 설정 클래스를 만들고, @EnableScheduling 어노테이션을 붙여준다. @Scheduled(fixedDelay = 5, initialDelay = 3000) public void helloWorld() { System.out.println("Hello World"); } 2. 사용할 메서드 위에 @Scheduled 어노테이션을 붙이고, 언제 작업을 수행할지 속성을 설정한다. 속성 cron : cron 표현식을 지원한다. (자세한 내.. 2022. 6. 23.
Docker 기본 명령어 이미지 관리 명령어 도커 이미지 목록 $ docker images 도커 이미지 삭제 # docker rmi NAME[:TAG] $ docker rmi ubuntu:16.04 사용하지 않는 모든 컨테이너 삭제 $ docker system prune 컨테이너 제어 명령어 컨테이너 내려받기 # docker pull NAME[:TAG] $ docker pull nginx:latest 컨테이너 실행 # docker run [OPTION] IMAGE[:TAG] [COMMAND] $ docker run -i -t ubuntu:16.04 /bin/bash # 외부에서 5000포트로 해당 컨테이너의 8080포트로 접근할 수 있음. $ docker run -p 5000:8080 cjsrhd94 컨테이너 이름 할당 $ do.. 2022. 4. 2.
Docker 실행 오류: WSL 2 installation is incomplete 오류 원인윈도우에 설치된 도커 커널이 최신버전이 아니라 발생한 문제다. 해결https://docs.microsoft.com/ko-KR/windows/wsl/install-manual 이전 버전 WSL의 수동 설치 단계wsl install 명령을 사용하지 않고 이전 버전의 Windows에 WSL을 수동으로 설치하는 방법에 대한 단계별 지침입니다.docs.microsoft.com 마이크로소프트 공식문서에서 제공하는 방법은 다음과 같다.1. Windows PowerShell을 '관리자 권한으로 실행' 하고 다음을 입력하여 'Linux용 Windows 하위 시스템 사용' 기능을 활성화 시킨다.dism.exe /online /enable-feature /featurename:Microsoft-Windows-Sub.. 2022. 3. 8.