hstory0208의 등록된 링크

키자드에 등록된 총 346개의 포스트를 확인하실 수 있습니다.

Tistory

[ELK] Logstash 401 Unauthorized 에러

Kibana에 로그가 전달이 되질 않아서 Docker Desktop으로 logstash의 로그를 확인해보니 다음과 같은 에러가 발생했다. [2023-10-04T08:03:23,112][WARN ][logstash.outputs.elasticsearch][main] Attempted to resurrect connection to dead ES instance, but got an error {:url=>"http://logstash_internal:xxxxxx@elasticsearch:9200/", :exception=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError, :message=>"Got response code '..

Tistory

[ELK] ElasticSearch란? ELK란? 내부 구조, 장단점, RDB와 차이

ElasticSearch란? Elasticsearch는 Apache Lucene기반의 Java 오픈 소스 분산 검색 엔진이다. Elasticsearch를 통해 방대한 양의 데이터를 신속하게(거의 실시간) 저장, 검색, 분석을 수행할 수 있다. Elasticsearch는 검색 엔진으로 단독으로 사용되기도 하며, ELK(Elasticsearch / Logstash / Kibana) 스택으로 사용되기도 한다. 이러한 Elasticsaerch는 대규모 로그 파일 관리나 실시간 검색 서비스 등과 같이 대용량 데이터를 빠르게 처리해야 하는 경우 유용하게 사용될 수 있다. 데이터 저장 방법 (RDBMS와 차이점) RDB는 정규화된 스키마에 따라 데이터를 구조화하지만, Elasticsearch는 JSON 문서 형태로 ..

Tistory

[무중단 배포] Nginx를 사용해 EC2에 무중단 배포 적용하기

무중단 배포란? 단순히 CI / CD만 적용하면 배포단계에서는 애플리케이션이 종료된다는 문제가 있다. 만약 실제 서비스에서 사용자들이 서비스를 이용하는 도중에 갑자기 서비스가 중단된다면 좋지 않은 사용자 경험을 줄 것이다. 이 문제를 해결 해주는 것이 바로 "무중단 배포"이다. 무중단 배포는 말 그대로 서버를 중단 없이 배포하는 것이다. 무중단 배포에 대한 더 자세한 내용은 아래 포스팅에서 설명한다. 무중단 배포란? 무중단 배포 전략에 대해 알아보자. 무중단 배포란? 무중단 배포를 사용하지 않을 경우 실제 서비스를 서버 한대만을 사용해 운영한다고 가정해보자. 현재 서비스 중인 서비스는 application-V1을 배포한 서비스이다. 그런데 기능이 업 hstory0208.tistory.com 무중단 배포를..

Tistory

Docker Desktop WSL 2 based engine 끄고 Hyper-V 활성화 방법

WSL 2를 사용하지 않고 Docker Desktop의 Hyper-V 기반 엔진을 사용하려면, 먼저 Hyper-V를 활성화해야한다. 1. "제어판" -> "프로그램 및 기능" 으로 이동 그리고 Windows 기능 켜기/끄기 클릭 2. Hyper-V 체크 3. Docker Desktop 설정에서 "Use the WSL 2 based engine" 옵션 체크 해제 후 재시작 4. 이제 이 이후에 도커 컨테이너 실행시 나오는 알림창 Share it을 클릭해주면 정상적으로 권한 문제 없이 파일 공유가 가능하다.

Tistory

[Spring] no main manifest attribute 에러

무중단 배포를 하는 도중에 jar 파일이 실행되지 않아서 계속 heath 체크가 실패하는 문제가 발생했다. 원인을 찾고자 해당 jar 실행 로그가 들어있는 파일을 열어 봤더니 아래 로그만 덩그러니 있었다. no main manifest attribute, in /home/ec2-user/app/deploy/mall-1.0.1-SNAPSHOT-20230927114334-plain.jar 이 에러는 jar파일에서 애플리케이션이 실행되는 @SpringBootApplication이 붙은 메인 클래스를 찾지 못했다는 뜻이다. java -jar로 jar파일을 실행 시키면 JVM이 jar파일의 메인 클래스를 호출하는데 이를 찾지 못해서 발생하는 문제이다. Spring boot 2.5.0 버전 이상 부터는 gradle..

Tistory

[ElastiCache Redis] ElastiCache Host 연결 문제 (RedisConnectionFailureException)

프로젝트의 서버로 EC2를 사용하면서 기존에서 로컬에서 사용하던 redis를 AWS의 ElastiCache를 사용하는 방법으로 변경했다. 그런데 호스트의 주소를 잘못 적었는지 계속 위와 같은 연결 문제가 있었다. ElastiCache Redis를 생성하면 다음과 같이 마스터 노드와 내구성을 위해 읽기 전용인 노드가 2개가 기본으로 생긴다. 처음에는 읽기전용인 마스터 노드의 엔드포인트를 호스트로 작성해줘야하는 줄 알고 "리더 엔트포인트"를 호스트로 작성했다가 연결오류가 발생했다. 이렇게 지정하니 Read Only ~ 에러가 발생하면서 읽기 전용 노드에 접근하려고 하고 있었다. 그래서 이번에는 노드 중 primary를 지정해서 호스트 엔드포인트를 작성했다. 이제는 ReadOnly는 발생하지 않지만 Redis..

Tistory

[Spring] kafka와 SSE(Server Send Event)를 사용한 실시간 알림 전송 방법

Kafka 선택 이유 알림 전송에 Kafka를 도입한 이유는 다음과 같다. 필자의 과일샵 쇼핑몰 프로젝트는 아래 처럼 회원 서버와 어드민 서버로 나뉘어져 있다. 두 서버가 DB는 공유하고 있지만 ,어드민 서버에서 발생한 이벤트를 실시간으로 회원 서버로 전달할 수가 없었다. 바로 이 문제를 해결하기 위해 Kafka를 도입하게 되었다. Kafka외에도 RabbitMQ나 Redis를 고려 해 볼 수도 있었지만, 분산 시스템이 적용되어 있는 큰 기업들에서 사용하고 있어 경험해보기 위해 Kafka를 선택하게 되었다. [Kafka] 카프카란 ? 주요개념 정리 및 Pub/Sub 모델 비교 카프카(kafka) 란? Kafka는 대규모 실시간 데이터 스트리밍을 처리하는 데 사용되는 분산 이벤트 스트리밍 플랫폼이다. 먼저..

Tistory

[Spring AOP] 모든 페이지의 공통 헤더 영역에 공통 데이터 Model에 담아 전달

아래와 같이 모든페이지에는 Layout으로 적용한 Header 부분이 공통적으로 들어간다. 그렇기 때문에 모든 페이지에서 해당 알림 데이터 리스트들이 필요하다. 하지만 현재 해당 헤더가 적용된 view를 반환하는 컨트롤러 코드들은 로그인과 회원가입 페이지들을 제외하면 총 9개가 있다. 이 많은 컨트롤러마다 일일히 패키지를 열어서 알림 테이블에서 회원별 알림 내역을 조회한 데이터들을 model에 담아 일일이 View에 뿌려줘야할까? 공통으로 사용되는 부분을 단순 반복 작업을 통해 추가하는건 너무 개발자스럽지 않다. 이 공통으로 사용되는 로직을 스프링 AOP를 적용해 해당 Contoller들의 Model에 알림 데이터들을 추가 해보자. AOP 적용 우선 먼저 build.gradle에 해당 의존성을 추가해주어..

Tistory

spring_session' doesn't exist 세션 테이블 생성이 안되는 오류

유저 서버와 어드민 서버를 분리하면서 유저 서버는 session 저장소를 redis, 어드민은 jdbc로 가져가도록 했다. 어드민은 jdbc로 가져가게 된 이유는 어드민 유저의 수는 일반 유저에 비해 많이 적기 때문에 세션 I/O 과정에 부하가 적어 선택하게 되었다. (유지 보수 비용도 고려) 세션 저장소로 jdbc로 사용하려면 아래와 같이 프로퍼티 파일에 옵션을 주면된다. spring.session.store-type=jdbc 하지만 이렇게 설정을하고 실행을 하면 spring_session 테이블이 생성이 안되었다는 에러가 발생할것이다. 문제 해결 만약 프로젝트에서 사용하는 데이터베이스가 embeded 타입이라면 spring_session 테이블은 자동 생성되도록 기본 설정 되어 있다. 하지만 나는 e..

Tistory

실시간 알림 - SSE(Server Sent Event), Websoket 차이점 정리

판매자가 회원의 리뷰에 답글을 달면 위와같이 알림 메세지를 보내는 기능이 필요했다. 현재는 답글을 달 경우 "어드민 서버"에서 Kakfa로 메세지를 보내고, "회원 서버"에서는 해당 topic을 구독하는 회원들에게 전달 받은 메세지를 SSE로 프론트에 뿌려주도록 구현했다. DB에 저장하는 것 만으로 알림은 충분히 구현이 가능하다. 다만 위 처럼 실시간으로 알림을 보내줄순 없다. 실시간 알림을 구현하는 경우 대표적으로 SSE, Websoket, Polling 3가지가 있다. 이번 포스팅에서는 자주 사용되는 SSE와 Websoket에 대한 차이점에 대해 이야기하고, SSE를 사용해 해당 실시간 알림을 구현한 이유에 대해 설명하고자 한다. SSE vs Websoket SSE (Server Send Event)..

Tistory

[Kafka] 카프카란 ? 주요개념 정리 및 Pub/Sub 모델 비교

카프카(kafka) 란? Kafka는 대규모 실시간 데이터 스트리밍을 처리하는 데 사용되는 분산 이벤트 스트리밍 플랫폼이다. 먼저 "분산 이벤트 스트리밍"이라는 용어에 대해 알아보자 분산 이벤트이라는 말은 여러 대의 서버(노드)에 분산되어 저장된 이벤트(데이터) 를 말한다. 이벤트 스트리밍은 대량의 이벤트(데이터)를 실시간으로 처리하는 방식을 의미한다. 즉, 이 두 내용을 연결 시키면 분산 되어 있는 이벤트(데이터)들을 실시간으로 처리하는 플랫폼이라는 뜻이 된다. 위 그림의 왼쪽은 링크드인에서 개발한 카프카가 등장하기전의 아키텍처 모습니다. 각 데이터 저장소들이 도착지점까지 모든 시스템을 거치는 End - To - End 연결로 매우 복잡한 것을 볼 수 있다. 하지만 카프카가 적용된 오른쪽 그림을 보면 ..

Tistory

[Spring] 자체 서비스 회원과 소셜 로그인 회원 통합 관리 방법

우리 서비스는 쇼핑몰을 통한 회원 가입 및 로그인, 그리고 소셜 계정을 통한 회원 가입 및 로그인을 지원한다. (카카오, 네이버, 구글) 이 글을 포스팅하는 이유는 소셜 로그인을 뒤 늦게 적용하게 되었는데 소셜 로그인을 적용하고 난뒤에 기존 쇼핑몰 회원과 소셜 계정을 통해 가입한 회원을 관리하는데 문제가 발생하게 되어서 그 문제점을 해결한 방법에 대해 포스팅하고자 한다. 문제 발생 상황 문제점 1. 소셜 로그인 구글 이메일이 a@, 나머지 이메일은 b@일 때 쇼핑몰을 통해 회원가입한 유저의 이메일이 b@ 일 경우 이메일 중복 문제가 발생해 이메일이 같은 경우 b@이메일 유저의 세션을 사용하는 문제. 2. 소셜 로그인은 보안상 비밀번호를 받아올 수 없기 때문에 소셜 로그인한 회원은 비밀번호 찾기가 불가..

Tistory

[Spring Security] 일반 로그인 & 소셜 로그인 분리 및 Security 로그인 비동기 처리 방법

우리의 서비스는 자체 회원가입을 통해 가입한 유저 로그인, 소셜 계정을 통해 가입된 유저 로그인 2가지 로그인 방식을 지원한다. 처음에는 일반 로그인만 구현해놓고 소셜 로그인은 후반에 적용하게 되었다. 그래서 일반 로그인은 자체 로그인 로직으로, 소셜 로그인은 스프링 시큐리티로 로그인을 구현이 되었다. 그런데 여기서 문제가 발생하게 되었다. 소셜 로그인은 사용자의 권한을 잘 읽어오지만 일반 로그인을 한 회원은 사용자의 권한을 읽어오지 못해 권한 설정을 한 페이지에 접근할수가 없는 문제가 발생하는 것이다. 문제 발생이유 기존에는 소셜 로그인은 시큐리티로 처리했지만, 일반 로그인 같은 경우는 아래처럼 요청을 받아 유효성검사를 하고 결과를 반환해주는 식이였다. 하지만 이런식으로 일반 로그인을 처리할 경우에는 ..

Tistory

[Redis] Redis에 로그인 Session정보를 저장하여 사용하기 (세션 불일치 해결)

서버가 한대일 경우에는 해당 서버에 세션 정보를 저장해서 사용할 수 있겠지만, 대용량 트래픽을 고려해 Scale-out이 적용된 환경에서는 세션 불일치 문제가 발생할 수 있다. Scale-out은 여러 대의 서버로 트래픽을 분산하기 때문에 로드 밸런싱이 필수로 적용되는데, 이 로드 밸런싱으로 인한 분산 처리 과정에서 서버마다 가지고 있는 세션 저장소에 있는 세션을 공유하지 않기 때문에 세션 불일치 문제가 발생할 수 있다. 이런 세션 불일치 문제가 발생하면 새 요청을 할 때마다 로그인을 해야하는 아주 좋지 않은 사용자 경험을 발생시킬 것이다. 이 세션 불일치 문제를 해결하기 위한 방법으로 아래 3가지 방법들이 있다. Sticky Session Session Clustering Session Storage ..

Tistory

[Spring + Redis] Redis cache를 적용해 조회 성능 개선 방법

내 프로젝트에서는 사용자별로 사이드바에 찜 수, 장바구니 수들을 카운트 쿼리로 반환된 데이터 수를 view에 뿌려주는데, 이 사이드바는 여러 페이지에서 노출되어 페이지 이동마다 카운트 쿼리를 자주 호출하고 있었다. 그렇기 때문에 매번 카운트 쿼리를 호출하지 않고 해당 데이터를 캐시 처리하여 카운트 수가 변경되지 않을 경우에 Redis 캐시에서 해당 데이터 수를 반환하도록 하여 DB의 부담을 줄이도록 하였다. 레디스에 대해 알고 싶다면 아래 포스팅에서 설명한다. [Redis] 레디스란? 특징, 활용예시, 비교 정리 레디스란? Redis는 Remote Disctionary Server의 약자로 키(Key) : 값(Value) 해시 맵과 같은 구조를 가진 NoSQL 데이터베이스이다. MySQL, Oracle같..

Tistory

[Spring] 아임포트(import)로 결제 취소, 환불 기능 구현하기

결제 취소 기능에 대해 포스팅하기 앞서 iamport를 사용하기 위한 준비과정 및 결제 기능 구현하는 방법에 대해서는 아래 포스팅에 설명되어 있다. [Spring] 아임포트(import)로 결제 기능 구현하기 (클라이언트 + 서버 코드 포함) import 란? 아임포트는 쇼핑몰 서버를 대신해서 쇼핑몰에서 사용자가 상품을 구매하려 할 때 실제 결제 요청 받는 역할을 하고 이 요청을 받아서 PG(결제 대행 업체)에 요청을 해준다. 그리고 결제 hstory0208.tistory.com 결제 취소 기능 구현 상품을 결제했으면 당연히 취소도 가능해야한다. 그렇기 때문에 결제 취소 로직을 추가하였다. 아래에서 설명하는 iamport에 결제 취소 요청을 보내는 코드를 구현하면 결제 완료된 상품에 대한 상품에 대한 결..

Tistory

[Redis] 레디스란? 특징, 활용예시, 비교 정리

레디스란? Redis는 Remote Disctionary Server의 약자로 키(Key) : 값(Value) 해시 맵과 같은 구조를 가진 NoSQL 데이터베이스이다. MySQL, Oracle같은 일반 DB와 다르게 하드 디스크(SSD, HDD)에서 데이터를 처리 하는 것이 아니라, Redis는 In-Memory(인메모리) 기반의 DB로 메인 메모리(DRAM)에서 데이터를 처리하기 때문에 작업 속도가 월등히 빠르다. DRAM과 SSD, HDD의 비교 메모리 계층 구조는 다음과 같이 여러 계층이 있지만 인메모리DB와 일반 DB를 비교하기 위해 2가지에 대해서만 비교 하고 넘어 가고자 한다. 특징 DRAM (메인 메모리) SSD, HDD (하드 디스크) 가격 하드 디스크 보다 비쌈 제일 저렴 지속성 휘발성 ..

Tistory

[Spring] 아임포트(import)로 결제 기능 구현하기 (클라이언트 + 서버 코드 포함)

import 란? 아임포트는 쇼핑몰 서버를 대신해서 쇼핑몰에서 사용자가 상품을 구매하려 할 때 실제 결제 요청 받는 역할을 하고 이 요청을 받아서 PG(결제 대행 업체)에 요청을 해준다. 그리고 결제 정보 결과에 대해서 응답을 받을 수 있다. 그렇기 때문에 웹 서버의 부담을 줄일 수 있고, PG사 별로 결제를 요청하는 코드를 작성해야하는 번거로움도 사라지게 된다. iamport는 가이드를 아주 친절하게 제공해주고 무엇보다 한국어로 되어 있어서 보기 편할 것이다. iamport 가이드 iamport 개발자 가이드 ( Notion ) : https://guide.portone.io/test_integration PG 사별 코드표 : https://portone.gitbook.io/docs/tip/pg-2 결..

Tistory

application.properties의 키 값이 @Value를 선언한 필드 값에 주입되지 않는 문제

결제 시스템으로 iamport api를 사용하기 위해 IamportClient 객체를 apikey로 생성하는데 이 apikey를 application.properties에 작성하고 @Value 어노테이션으로 키 값을 받아오는데 해당 필드에 키값이 채워지지 않는 문제가 발생했다. @Controller @RequiredArgsConstructor public class OrderController { private final OrderService orderService; @Value("${imp.api.key}") private String apiKey; @Value("${imp.api.secretkey}") private String secretKey; private IamportClient iampor..

Tistory

[Spring] Cookie(쿠키)를 활용한 최근 본 상품 기능 구현 (Session과 비교)

그림과 같이 클릭했던 상품들을 "최근 본 상품"이라는 목록에 보여주는 기능을 추가하게 되었다. 이 기능을 구현하기 위해서는 Cookie와 Session을 사용해 구현할 수 있는데, 여기서 고민에 빠졌다. 고민하게 된 이유는 다음과 같다. Cookie와 Session방식을 통해 "최근 본 상품"기능을 구현했을 때의 장단점 먼저 Cookie는 기본적으로 문자열 형태로 데이터를 저장하며, 복잡한 데이터 타입인 리스트(List)와 같은 자료구조를 그대로 Cookie에 저장하는 것은 지원되지 않는다. 그렇기 때문에 복잡한 데이터 타입을 저장하려면 추가적인 로직이 필요하다. (필자는 objectMapper로 JSON 데이터로 변환하여 저장하였다.) 게다가 최근 본 상품에는 이미지URL로 해당 상품의 이미지를 보여준..

Tistory

[Spring] 로그인 어노테이션으로 세션 정보가져오기 (Argument Resolver 활용)

로그인 사용자에 대한 기능들을 구현하다보면 로그인 사용자의 Session 정보를 활용할 일이 정말 많다. 그렇다 보니 Session 정보를 가져오는 코드마다 아래의 코드가 반복될 것이다. SessionUser user = (SessionUser) httpSession.getAttribute("loginUser"); 이 같은 코드가 반복되는 것을 방지하고자 Spring의 argument resolver를 활용하여 메서드 파라미터의 SessionUser 앞에 @Login 어노테이션을 붙여 세션값을 바로 받아 올 수 있도록 구현할수 있다. 또한 사용자별 세션 정보를 갖고 있으므로, 사용자별로 서로 다른 페이지 내용을 볼 수 있다. ( ex: 마이페이지 ) SessionUser 클래스 세션에 저장할 사용자의 정..

Tistory

[MySQL] 이벤트 스케쥴러와 프로시저 (매일 특정 시간에 CRUD 작업 실행)

MySQL에 주기적으로 특정시간에 DB에 어떤 작업을 해주어야 할 상황이 생길 때가 있다. 나는 이번에 쇼핑몰 프로젝트를 진행하면서 "장바구니에 담긴 상품은 최대 15일까지 보관되며 자동으로 삭제됩니다." 라는 장바구니의 정책이 있어서 이를 MySQL의 이벤트 스케쥴러와 프로시저를 활용하여 매일 자정에 15일이 지난 상품을 장바구니 테이블에서 삭제하도록 만들었다. 프로시저(Procedure) 프로시저는 MySQL의 함수(메서드)를 만드는 것이라고 보면 된다. 실행할 쿼리문을 함수로 빼서 재사용가능하고, 이 프로시저의 쿼리에 조건문이나 반복문도 함께 사용할수가 있다. 프로시저 생성 나같은 경우에는 현재날짜와 cart 테이블에 데이터가 생성된 시점을 비교해 15일이 지났으면 삭제하는 간단한 프로시저를 만들었..

Tistory

[Spring] GET요청으로 url 쿼리 파라미터에 포함된 JSON 데이터 사용하기

적용하게 된 이유 장바구니에 있는 상품들 중에 체크박스가 활성화된 상품들만 결제 페이지로 넘기는 작업을 진행하면서 해당 상품들만 어떻게 GET 요청에 담아서 보내야할까? 라는 의문이 들었다. 처음에는 체크박스가 활성화된 상품들을 배열에 담아 해당 배열을 보내주어야 하는데 처음에는 axios를 통해 비동기로 POST 요청으로 해당 상품들의 정보들을 JSON 객체로 넘겨주려했었다. 하지만, 비동기로 요청하게 되면 컨트롤러에서 view를 반환할 때 해당 view에 체크박스가 활성화된 상품들의 데이터를 model에 담아 넘겨줘야하는데 요청에 대한 응답을 성공적으로 넘겨준후에 axios의 then 구문으로 넘어가게되면서 해당 데이터를 넘겨주기 힘들어지는 문제가 발생했다. (해당 위 방법으로 해결 할수 있을 수도 ..

Tistory

[Spring] 공통 기능을 @Aspect를 사용해 적용하기

아래와 같은 사이드바에 장바구니에 담긴 상품 개수, 찜 개수, 최근 본 상품이 표시되도록 하는 기능을 구현하게 되었다. 그런데 개수 같은 경우에는 count 쿼리로 구해 model에 담아 view넘기는데 이 사이드바가 메인, 장바구니, 결제, 상품상세 페이지 등에 적용이되어서 해당 컨트롤러들마다 count 쿼리를 날리는 건 낭비라 생각해 @Aspect로 AOP를 적용하게 되었다. AOP 적용 아래는 사이드바에 공통으로 적용할 코드들을 담은 Aspect를 적용한 클래스이다. @Aspect @Component @Slf4j @RequiredArgsConstructor public class SidebarAspect { private final LikeService likeService; private fina..

Tistory

@ModelAttribute 객체가 바인딩 되지 않는 오류

이번 프로젝트를 진행하면서, 요청으로 받은 파라미터들이 @ModelAttribute 객체에 바인딩이 되지 않는 이슈를 겪어 이에 대해 정리해보고자 한다. 지금 진행하는 프로젝트에서 JPA와 MyBatis를 함께 사용하는 것이 아닌 오로지 MyBatis만 사용하면서 기존의 방식과 다른점으로 머리속이 복잡해지면서 많은 오류를 겪었다. JPA에서는 Entity 객체에 @Entity 어노테이션을 붙여 테이블이 생성하도록 해준다. @Entity 객체에 기본 생성자가 없을 경우에는 JPA가 작동하지 않을 것이다. 그 이유는 JPA는 Reflection API라는 것을 사용하여 객체를 생성해 기본 생성자가 필요하기 때문이다. 그래서 보통 Entity 객체에는 기본 생성자와 값 생성자가 포함된다. 그리고 Setter ..

Tistory

[TinyMce] 텍스트 에디터 적용하기 (+ 에디터 이미지 업로드)

이번 프로젝트에서 어드민 페이지 상품 등록 화면의 상세설명 부분에 아래와 같이 TinyMce 에디터를 적용하게 되었다. TinyMce 에디터를 사용하면 위와 같은 텍스트 편집기를 추가할 수 있는데 이번 포스팅에서는 TinyMce를 JavaScript로 적용하는 방법에 대해 설명하고 에디터를 커스터마이징하는방법에 대해 포스팅하려한다. TinyMce 적용방법 TinyMce Api Key 발급 tinymce를 적용하기전에 먼저 아래의 공식 홈페이지에 들어가서 회원가입 후 API KEY를 발급받아야한다. The Most Advanced WYSIWYG Editor | Trusted Rich Text Editor | TinyMCE TinyMCE is the most advanced WYSIWYG HTML edito..

Tistory

데이터베이스 정규화(Normalization)란? 예시를 통해 쉽게 이해해보자

정규화란? 데이터베이스 정규화는 데이터베이스 내의 데이터 구조를 조직화하고 최적화하는 과정이다. 정규화를 하는 목적은 데이터 중복을 제거하고, 효율성을 향상시키며, 데이터 무결성을 보장하기 위함이다. 데이터 정규화에는 다음과 같이 여러 단계가 있다. 제1 정규화 (1NF) 제2 정규화 (2NF) 제3 정규화 (3NF) 이상 종류 이상 종류란 정규화를 거치지 않은 데이터에서 발생할 수 있는 현상을 말한다. 삽입 이상 (Insertion Anomaly) : 데이터 삽입 시 의도와 다른 값들도 삽입 삭제 이상 (Delete Anomaly) : 데이터 삭제 시 의도와 다른 값들도 연쇄 삭제 갱신 이상 (Update Anomaly) : 속성값 갱신 시 일부 튜플만 갱신되어 모순 발생 제1 정규화 (1NF) 데이터..

Tistory

@ModelAttribute가 객체에 바인딩하는 과정 및 방법

@ModelAttribute 이 어노테이션은 보통 컨트롤러 메서드의 파라미터 객체의 앞에 사용되며 HTTP 요청을 받으면 HTTP 요청 파라미터를 자동으로 자바 객체에 바인딩 해준다. 요청을 처리하는 스프링 어노테이션으로 주로 @ModelAttribute와 @RequestBody가 많이 헷갈리는데 @ModelAttribute는 content-type이 application/x-www-form-urlencoded인 경우 즉 태그를 통해 제출한 데이터를 받아 객체로 변환하고, @RequestBody는 message body를 통해 넘어온 JSON이나 XML 형식들을 받아 객체로 변환한다. 이 두 어노테이션에 대한 차이는 아래 포스팅을 참고하여 알아 볼 수 있다. 2023.07.05 - [JAVA/Spring..

Tistory

[비동기 통신] Ajax와 Axios의 차이점?

Ajax와 Axios는 웹 개발에서 비동기 통신으로 데이터를 주고받기 위해 사용되는 기술들이다. 이 두 기술들에 대해 혼동이와서 어떤 차이점이 있는지 정리해보려 한다. 비동기 통신에 대해 쉽게 이해하고 싶다면 아래 링크를 참고하면 도움이 된다. 동기와 비동기의 개념 및 차이에 대해 쉽게 알아보자. 동기(Synchronous) 방식 동기란, 말 그대로 동시에 일어난다는 뜻입니다. 요청을 하면 동시에 응답을 한다는 약속으로, 바로 요청을 하면 시간이 얼마가 걸리던지 요청한 자리에서 응답(결과)가 주 hstory0208.tistory.com Ajax (Asynchronous JavaScript and XML) Ajax는 약자 그대로 JavaScript, XMLHttpRequest 객체를 사용하여 웹 브라우저와..

Tistory

Spring Data JPA + QueryDSL 페이징 처리

이번 포스팅에서는 QueryDSL과 Spring Data JPA를 함께 사용해 페이징 처리하는 방법에 대해 알아보고자 한다. 다음은 이번 포스팅에서 사용할 QueryDSL 사용자 정의 레포지토리 인터페이스와 이를 구현한 구현체 이다. 이 내용에 대해 알고 싶으면 아래 링크를 참고 하면 도움이 된다. 2023.07.10 - [오픈소스] - QueryDSL Repository 생성하기 (사용자 정의 리포지토리) public interface MemberRepositoryCustom { Page searchPage(MemberSearchCondition condition, Pageable pageable); } @RequiredArgsConstructor public class MemberRepositoryI..

Tistory

QueryDSL 기본 문법 총정리

기본 문법들에 대해 설명하기 앞서 QueryDSL을 사용하기 위한 세팅 방법이나 사용방법들에 대해 알고 싶다면 아래의 포스팅들을 참고하면 된다. 2023.07.10 - [오픈소스] - QueryDSL 사용법, DTO 반환 방법 정리 2023.06.27 - [오픈소스] - [QueryDSL] 스프링부트 3.x 버전에서 QueryDSL 설정하기 QueryDSL 문법에 대해 설명하기 앞서 QueryDSL은 JPAQueryFactory를 사용하여 JPQL을 생성하고 실행한다. 작성하는 쿼리문을 보면 JPQL 문법이랑 동일하고, 뒤에 . 을 붙여 체인으로 연결하여 java 코드로 작성한다. // static import 방법으로 작성 import static study.querydsl.entity.QMember...

Tistory

QueryDSL 동적 쿼리를 작성하는 방법에 대해 알아보자.

QueryDSL을 사용하는 이유는 아마 동적 쿼리를 아주 쉽게 해결할 수 있어서가 아닐까 싶다. 이번 포스팅에서는 QueryDSL을 사용해서 동적 쿼리를 작성하는 방법에 대해 포스팅해 보려한다. QueryDSL 설정, 사용방법, 문법에 대해 알고 싶다면 아래 링크를 통해 확인할 수 있다. 2023.07.10 - [오픈소스] - QueryDSL 기본 문법 총정리 2023.06.27 - [오픈소스] - [QueryDSL] 스프링부트 3.x 버전에서 QueryDSL 설정하기 2023.07.10 - [오픈소스] - QueryDSL 사용법, DTO 반환 방법 정리 동적 쿼리 querydsl에서 동적 쿼리를 사용하는 방법 중 Where 절에서 다중 파라미터를 사용하는 방법에 대해 설명하려 한다. 이 방법은 wher..

Tistory

QueryDSL Repository 생성하기 (사용자 정의 리포지토리)

이번시간에는 QueryDSL을 사용하기위핸 QueryDSL 리포지토리를 만드는 방법에 대해 포스팅해보려고 한다. QueryDSL를 사용하기 위해서는 구현 클래스가 필요하고 Spring Data JPA는 인터페이스로 동작한다. 그래서 QueryDSL를 사용하기 위한 사용자 정의 리포지토리(Custom Repository)를 만들고 Spring Data JPA 리포지토리와 연결하는 방법을 알아보자. JPAQueryFactory 빈 등록 QueryDSL을 사용하기 위해서는 JPAQueryFactory를 다음과 같이 Bean 등록 해주어야 한다. @Configuration public class QueryDSLConfig { @Bean JPAQueryFactory jpaQueryFactory(EntityMana..

Tistory

QueryDSL 사용법, DTO 반환 방법 정리

스프링부트 3.x 버전에서 QueryDSL 설정하기 [QueryDSL] 스프링부트 3.x 버전에서 QueryDSL 설정하기 스프링 부트 2.x 버전 대를 쓰다가 이번에 스프링 부트 3.x 버전이 나오면서 많은 설정이 변경되었다. 이번 포스팅에서는 스프링부트 3.x 버전에서 QueryDSL을 설정하는 방법에 알아보고자 한다. (스 hstory0208.tistory.com 설명하기 앞서, QueryDSL을 사용하기 위해서는 JPAQueryFactory를 Bean 등록하고 의존성 주입받아야 한다. Bean 등록 @Configuration public class QueryDSLConfig { @Bean JPAQueryFactory jpaQueryFactory(EntityManager em) { return ne..

Tistory

[Python/파이썬] 백준 13305번 - 주유소

문제 설명 입출력 예제 풀이 코드 왼쪽에서 제일 오른쪽 도시로 이동하는 최소의 비용을 구하기 위해서는 가장 싼 주유소에서 기름을 넣는 것이 이득이다. 먼저 왼쪽에서 출발할 때는 기름이 없기 때문에 시작지점에서 먼저 기름을 넣고 시작하는데 가장 값이 싼 주유소를 찾기 위해 첫 번 째 주유소를 가장 값이 싼 주유소로 저장해 놓은 뒤 반복문을 통해 저장한 주유소와 현재 위치의 주유소의 기름 값을 비교해 가장 값이 싼 주유소를 갱신해서 기름을 넣으면 된다. 정답 코드 import sys input = sys.stdin.readline n = int(input()) distances = list(map(int, input().split())) oilCosts = list(map(int, input().split(..

Tistory

[Spring] @ModelAttribute와 @RequestBody의 차이점에 대해 쉽게 이해해보자. (API 동작 방식)

@ModelAttribute와 @RequestBody 모두 HTTP 요청 파라미터를 객체에 매핑하는 데 사용되는 어노테이션입니다. api 개발을 하다가 이 두 개념에 대해 헷갈려서 확실히 정리하고 넘어가고자 포스팅하려 한다. @ModelAttribute @ModelAttribute는 요청 파라미터의 이름과 일치하는 객체의 필드에 요청 파라미터를 매핑한다. 쉽게 말해 폼 데이터를 객체에 매핑할 때 주로 사용하는 것이다. 아래 컨트롤러에 있는 코드를 통해 예시들을 보고 쉽게 이해해보자. requestDto 위 ItemSearchCond 객체를 살펴보면 다음과 같다. @Getter @NoArgsConstructor public class ItemSearchCond { private String itemName..

Tistory

[Python/파이썬] 백준 1541 - 잃어버린 괄호

문제 설명 입출력 예제 풀이 코드 그리디 알고리즘 문제로 괄호를 적절히 합쳐서 최소 값이 나올 수 있게 하는 방법만 알면 쉽게 해결할 수 있다. 해당 방법는 모든 + 식들만 먼저 더하고 나중에 구한 값들을 첫 번째 값에서 부터 빼는 방식이다. 이때, 첫 번째 값은 등호가 없으므로 따로 저장하여 처리한다. 만약 10 - 20 + 30 - 60 + 20 - 40 이 주어졌다고 가정해보자. 가장 최소 값이 나올 수 있도록 덧셈 식들만 괄호를 적용하면 다음과 같다. (10) - (20 + 30) - (60 + 20) - (40) 이 식대로 계산을 하면 정답은 10 - 50 - 80 - 40 = -160이 된다. 정답 코드 import sys input = sys.stdin.readline arr = input(..

Tistory

[Python/파이썬] 백준 2638번 - 치즈

문제 설명 입력과 출력 및 예제 풀이 코드 2차원 배열의 값들을 하나씩 탐색해 해당 부분이 외부 공기와 2번 이상 접촉했는지 확인해야 하므로 BFS를 이용해 문제를 풀 수 있다. 내 코드에서 주의할점으로는 치즈가 있는 부분은 visited 방문 처리 하지 않았다는 점인데 여러 면에서 공기와 접촉이 될 수 도 있기 때문에 이 부분을 방문 처리 해버리게 되면 해당 치즈는 무조건 한 면만 접촉되는 것이 되기 때문이다. 나머지 부분은 주석을 통해 이해할 수 있을 것으로 생각되어 자세한 설명은 생략한다. 정답 코드 from collections import deque import sys input = sys.stdin.readline n, m = map(int, input().split()) cheeze = [l..

Tistory

[QueryDSL] 스프링부트 3.x 버전에서 QueryDSL 설정하기

스프링 부트 2.x 버전 대를 쓰다가 이번에 스프링 부트 3.x 버전이 나오면서 많은 설정이 변경되었다. 이번 포스팅에서는 스프링부트 3.x 버전에서 QueryDSL을 설정하는 방법에 알아보고자 한다. (스프링 부트 3.x버전은 자바 17만을 지원하므로 자바 17이 준비되어 있어야한다.) QueryDSL을 적용하고 나면 Q타입 class라는 것이 생기는데 이 Q타입 class은 Entity 클래스를 통해 생성된다. 그리고 이 Q타입 class가 있어야 QueryDSL로 쿼리문을 작성할 수 있다. 그렇기 때문에 먼저 QueryDSL을 적용하기전에 Entity 객체가 준비되어 있어야한다. 나는 간단하게 Hello라는 엔티티 클래스를 만들었다. @Entity @Getter @NoArgsConstructor p..

Tistory

Nginx란 무엇이고 왜 사용하는가? (Apache와 차이점)

Nginx의 등장 이전 최초의 웹 서버는 1995년 UNIX 기반으로 만들어진 NCSA Httpd 였다. 하지만 처음은 다 그렇듯이 NCSA Httpd에는 버그가 상당히 많아서 개발자들이 사용할 때 많은 불편함을 겪었다고 한다. 그래서 이러한 문제를 해결하기 위해 구조도 변경하고 새로운 기능을 추가해 개발된 것이 바로 Apache이다. Apache Apache는 요청이 들어오면 커넥션을 형성하기 위해 프로세스를 생성하는데 새로운 요청마다 프로세스를 생성하는 것은 시간이 소요되는 작업이다보니 프로세스를 미리 만들어 놓는 Prefork 방식을 사용했다. 새로운 요청이 들어오면 미리 만들어 놓은 프로세스를 가져다 쓰는 방식이다. 만약 만들어 놓은 프로세스가 모두 할당되었다면 추가로 프로세스를 만든다. 이러한 ..

Tistory

[Python/파이썬] 백준 16928 - 뱀과 사다리 게임

문제 설명 입출력 예제 풀이 코드 10 x 10 크기의 보드판에서 진행되는 게임이라고 했지만 상하좌우로 움직이는게 아닌, 한 방향으로만 움직일 수 있다. 그렇기 대문에 2차원 배열이 아닌 1차원 배열로 나열해 풀 수 있다. 그리고 주어진 사다리, 뱀의 위치를 dict(딕셔너리) 타입으로 받아 주사위를 던져 도착한곳이 사다리, 뱀 위치(key)면 value로 이동시킨다. 정답 코드 from collections import deque import sys input = sys.stdin.readline n, m = map(int, input().split()) # 사다리 수, 뱀 수 board = [0] * 101 visited = [False] * 101 ladder = dict() for _ in ran..

Tistory

[Spring Data JPA] 스프링 데이터 JPA에서 페이징(Paging) 사용하기

저번 포스팅에서 순수 JPA를 통해 페이징을 적용하는 방법에 대해 알아보았다. Spring Data JPA를 사용하면 정말 편리하게 PageRequest를 따로 만들필요없이 페이징 적용이 가능하다. 하지만 Spring Data JPA도 Page와 Pageable 인터페이스를 사용하기 때문에 해당 인터페이스에 대한 설명은 아래 포스팅을 참고하는 걸 추천한다. [JPA] 페이징과 정렬에 대해 알아보자. 페이징 (Pageable, Page, Slice ) 데이터베이스의 대용량 데이터를 처리할 때, 데이터를 효율적으로 로드하고 출력하기 위해 페이지 단위로 데이터를 분할하여 가져오는 기능을 페이징이라고 한다. 페 hstory0208.tistory.com 페이징 적용 파라미터로 Pageable 인터페이스를 받고 다..

Tistory

[Docker] 도커 컴포즈(Docker Compose)란? 왜 사용하는가?

도커 컴포즈란? 여러 개의 Docker 컨테이너들을 하나의 서비스로 정의하고 구성해 하나의 묶음으로 관리할 수 있는 하나의 애플리케이션을 만드는 것이다. 도커 컴포즈 설치 # 도커 컴포즈 V2 버전 설치 sudo curl -sSL "https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 실행 권한 설정 chmod +x /usr/local/bin/docker-compose # 버전 확인 docker-compose --version Docker Compose를 사용하기 위해선 다음과 같은 단계가 필요하다. Docker C..

Tistory

왜 WAS와 Web Server를 같이 사용하는걸까?

Web과 WAS란 ? 웹 서비스의 구조에 대해 알아보자 Web Server (웹 서버) 웹 서버란, HTTP 프로토콜을 기반으로 동작하는 서버로, 동작하는 방식은 클라이언트가 웹 서버에 HTTP 요청을 보내면 웹 서버는 HTTP로 응답하여 정적 리소스를 제공합니다. 대표 hstory0208.tistory.com 보통 웹 서비스는 아래의 그림처럼 Client ↔ Web Server ↔ WAS ↔ DB 이런식으로 요청 , 응답을 주고 받는다. WAS만으로도 웹 서비스를 제공할 수 있는데 왜 앞에 Web 서버를 붙여 같이 사용하는걸까? 그 이유는 다음과 같다. 1. 성능 향상 웹 서버는 정적 콘텐츠(이미지, CSS, JavaScript 등)의 처리에 최적화되어 있다. 따라서 웹 서버가 정적 콘텐츠를 처리하고 ..

Tistory

[Python/파이썬] 백준 1436 - 영화감독 숌

문제 설명 입출력 예제 풀이 코드 이 문제는 완전탐색 탐색 문제로 완전 탐색 답게 무식하게 숫자를 하나씩 더해가면서 해당 숫자가 몇번째 종말의 수인지 찾아야 한다. 그래도 반복문을 덜 타게 규칙이 있지 않을까?했지만 그런 규칙을 찾긴 힘들었다 다만 반복문을 덜타도록 탐색하는 수 num을 1부터가 아닌 종말의 수인 "666"부터 시작하도록 하였다. 정답 코드 import sys input = sys.stdin.readline n = int(input()) cnt = 0 # 몇 번째 종말의 수인지 카운팅 num = 666 while True: if "666" in str(num): # 666이 num에 포함되어 있다면 cnt = cnt + 1 if cnt == n: # 구하자고 하는 n번째 종말의 수와 같다..

Tistory

[Docker] 도커 명령어 총모음집 (image, container, compose)

Docker 실행 sudo systemctl status docker # 1 sudo /etc/init.d/docker start # 2 Docker Image 관련 명령어 이미지 빌드 Dockerfile을 이용해서 이미지 생성 (제일 많이 쓰는 이미지 생성 방법) docker build -t {이미지명:태그명} {dockerfile의 경로} 이미지 삭제 도커 단일 이미지 삭제 docker image rm {이미지 ID 또는 이름} 모든 도커 이미지 삭제 (컨테이너가 있어서 이미지 삭제가 안될 시 -f 옵션을 붙여서 강제 삭제가능하다.) docker rmi {옵션} {이미지 ID 또는 이름} 이미지 조회 도커 이미지들 보기 docker images 현재 이미지 목록 확인 docker..

Tistory

무중단 배포란? 무중단 배포 전략에 대해 알아보자.

무중단 배포란? 무중단 배포를 사용하지 않을 경우 실제 서비스를 서버 한대만을 사용해 운영한다고 가정해보자. 현재 서비스 중인 서비스는 application-V1을 배포한 서비스이다. 그런데 기능이 업데이트되어 application-V2를 새로 개발해 새로운 버전을 배포하려한다. 이 새로운 버전 V2를 배포하기 위해서는 V2 버전의 빌드 파일을 서버에 배포를 해야한다. V1과 V2는 서로 같은 포트를 사용하기 때문에 V2를 배포하기 위해서는 V1버전을 통해 실행하고 있는 서비스를 종료해야만한다. 이 경우 V1이 종료되고 V2 버전이 실행되는 사이 유저가 서비스를 이용할 수 없는 시간이 생기는데, 이를 "다운타임"이라고 한다. 무중단 배포 무중단 말 그대로 서비스가 중단되지 않은 상태로 새로운 버전을 배포..

Tistory

[Python/파이썬] 백준 11659 - 구간 합 구하기 4

문제 설명 입출력 예제 풀이 코드 이 문제는 현대오토에버 코딩문제에 나온 문제라고 한다. 사실상 실버난이도인 만큼 접근만 한다면 쉽게 풀 수 있는 문제다. 제한 사항을 보면 N, M 입력값의 제한 범위가 100,000이다. 이중 반복문으로 풀면 쉽게 풀수는 있겠지만 2중 반복문은 O(n^2) 시간 복잡도를 갖기 때문에 시간초과가 발생한다. 따라서 O(N)이나 O(logN)의 시간 복잡도로 풀어야 하는데 문제에서도 이미 정답을 말해줬다."구간합" 문제를 푸는 방법은 다음과 같다. 주어진 값들의 누적합을 갖는 리스트를 만든다. PrefixSum 여기서 PrefixSum에 0을 넣어 놓은 이유는 주어지는 구간 i가 1부터 시작하기 때문에 인덱싱에러를 방지하기 위해서이다. 각 수들의 합을 갖는 변수 total을..

Tistory

[Docker] DockerFile의 개념과 작성법에 대해 알아보자. (도커 이미지 생성 방법)

DockerFile이란? Dockerfile은 Docker Image를 생성하기 위한 스크립트(설정파일)이다. 여러가지 명령어를 토대로 Dockerfile을 작성한 후 빌드하면 Docker는 Dockerfile에 나열된 명령문을 차례대로 수행하며 DockerImage를 생성한다. Dockerfile을 읽을 줄 안다는 것은 해당 이미지가 어떻게 구성되어 있는지 알 수 있다는 의미이기도 하다. 도커 파일은 레이어 개념으로 실행 되기때문에 레이어 순서대로 작성해주는게 좋다. DockerFile 작성법 기본적으로 도커 파일의 파일명은 확장자 없이 Dockerfile 이다. FROM 베이스 이미지를 지정. 생성할 이미지의 베이스가 될 이미지를 의미한다. 로컬에 해당 이미지가 없는 경우 Docker Hub에서 가져..

Tistory

[Docker] 도커의 레이어(Layer)에 대해 알아보자.

도커 이미지는 컨테이너를 만들기 위한 "압축파일" 개념이다. 이미지는 한번 만들어지면 이미지 내의 정보는 절대 변하지 않으며(불변성), 이미지를 통해 컨테이너를 만들 수 있다. 이 이미지는 컨테이너를 만들었다고 사라지지 않고, 하나의 이미지로 여러개의 컨테이너를 만들 수 도 있다. 이 이미지를 만들기 위해서는 dokckerfile 도커파일을 작성해야 한다. 도커 파일 작성방법은 아래 링크를 통해 확인할 수 있다. [Docker] dockerfile의 개념과 작성법에 대해 알아보자. hstory0208.tistory.com 도커 이미지는 컨테이너를 생성하기 위한 모든 정보를 갖고 있기 때문에 보통 수백MB ~ 수GB가 넘는다. (VM에 비해서는 상당히 작은 용량) 그런데 기존 이미지에서 작은 변경사항이 생..

Tistory

[Spring Data JPA] @EntityGraph 엔티티 그래프란?

Spring Data JPA는 JPA가 제공하는 엔티티 그래프 기능을 편리하게 사용하게 도와주는데, 이 기능이 바로 @EntityGraph이다. JPQL로 fetch join을 직접 작성하지 않고 @EntityGraph 어노테이션을 붙임으로서 fetch join을 편리하게 사용할 수 있다. 즉, @EntityGraph는 fetch join을 적용해주기 때문에 N + 1 문제를 해결하고, 성능 최적화에 도움을 줄 수 있다. (fetch join의 간편 버전) fetch join 이란? => 2023.06.12 - [JAVA/JPA] - [JPA] JPQL의 fetch join(패치 조인)이란? 사용 방법 Member와 Team 엔티티가 있고 이 둘은 "1 : 다" 양방향 관계를 갖는다고 가정해보자. 이 때..

Tistory

Docker(도커)란? 왜 사용하는가?

Docker란? Docker는 컨테이너 기반의 오픈 소스 가상화 플랫폼으로, 애플리케이션 및 그에 따른 환경을 격리된 컨테이너에 패키징하여 개발, 배포, 실행을 쉽게 지원하는 툴이다. 먼저 Docker를 이해하기 위해서는 가상화에 대해서 이해가 필요하다. 가상화란? 하이퍼바이저를 이용해 여러개의 운영체제를 하나의 호스트에서 생성하는 방식이다. 하이퍼바이저 하이퍼바이저는 다음과 같은 역할을 수행한다. OS들에게 자원을 나누어 주며 조율 OS들의 커널을 번역해서 하드웨어에게 전달 위 그림을 보면 하나의 Host OS에서 여러 개의 서버 운영 체제(게스트 OS)가 생성되어 있는 것을 볼 수 있다. 이렇게 생성된 게스트 OS들은 가상 머신이라는 단위로 구별되고, 다른 게스트 OS와는 완전히 독립된 공간과 시스템..

Tistory

[JPA] 컬렉션 조회 시 주의할 점 (hibernate.default_batch_fetch_size)

DTO를 조회 하되, 그 안에도 엔티티가 있을 경우 DTO로 변환해서 사용해야한다. 아래 그림은 Order와 OrderItem 엔티티의 일부 코드로 "1 : 다" 양방향 관계를 갖고 있는 것을 볼 수 있다. 이 전 포스팅에서 엔티티를 직접 반환하면 안되는이유에 대해 알아봤었다. [Spirng/JPA] Dto와 Entity를 분리해서 사용하는 이유 프로젝트를 진행하거나 강의, 책을 보면 항상 엔티티를 직접 반환하지말고 DTO로 변환하여 반환하라는 말을 접하거나 보았을 것이다. 하지만 단순히 "아 ~ 그렇게 하라니까 그렇게 해야지" 보다 hstory0208.tistory.com 컬렉션도 마찬가지다. 컬렉션도 엔티티를 DTO로 변환해서 반환해야한다. Order와 OrderItem이 연관관계를 갖고 있는 것 처..

Tistory

[Spring Data JPA] 쿼리 생성 기능과 반환 타입

메소드 이름으로 쿼리 생성 Spring Data JPA는 메서드 이름을 통해 쿼리를 작성해주는 쿼리 기능을 제공한다. (공식 문서 : Spring Data JPA - Reference Documentation) List findByUsernameAndAgeGreaterThan(String username, int age); 위 메서드 이름을 통해 실행도니느 쿼리는 다음과 같다. select m from Member m where m.username = :username and m.age > :age" 이 기능은 보통 파라미터 개수가 적을 때 사용한다. ( 파라미터 수가 많아지면 메서드 이름이 너무 길어져 가독성이 떨어짐 ) 그리고 엔티티의 필드명이 변경되면 인터페이스에 정의한 메서드 이름도 꼭 함께 변경..

Tistory

[JPA] 페이징과 정렬에 대해 알아보자.

페이징 (Pageable, Page, Slice ) 데이터베이스의 대용량 데이터를 처리할 때, 데이터를 효율적으로 로드하고 출력하기 위해 페이지 단위로 데이터를 분할하여 가져오는 기능을 페이징이라고 한다. 페이징 적용 코드 다음과 같은 순서와 방식으로 페이징을 적용할 수 있다. public interface MemberRepository extends JpaRepository { Page findByAge(int age, Pageable pageable); } /** * 1. PageRequest 객체 생성 * PageRequest.of() 메소드를 사용하여 페이지 번호와 페이지 크기를 전달하며 PageRequest 객체를 생성할 수 있다. * 이때 정렬 조건이 있는 경우 추가적으로 Sort 객체도 함께..

Tistory

[Spring/JPA] OSIV 전략이란? 언제 사용해야 할까?

OSIV (Open Session In View) OSIV란 스프링 프레임워크에서 사용하는 세션 관리 전략 중 하나로 스프링 부트에서는 기본 값이 True로 설정되어 있다. spring.jpa.open-in-view: true 애플리케이션에서 HTTP 요청마다 새로운 데이터베이스 연결(Connection)이 생성되는데, 이에 따라 많은 수의 DB 커넥션이 발생하여 성능 저하가 발생할 수 있다. 하지만 OSIV 옵션을 True로 설정하여 사용하면, 트랜잭션 시작처럼 최초 데이터베이스 커넥션 시작 시점부터 API 응답이 끝날 때 까지 영속성 컨텍스트와 데이터베이스 커넥션을 유지한다. 장점 지연 로딩은 영속성 컨텍스트가 살아있어야 가능하고, 영속성 컨텍스트는 기본적으로 데이터베이스 커넥션을 유지한다. 지연 로..

Tistory

JpaRepository를 상속한 인터페이스가 구현체가 없이 동작하는 이유

public interface MemberRepository extends JpaRepository { } Spring Data JPA를 사용하면 위 처럼 JpaRepository 인터페이스를 상속받은 인터페이스만 있어도 CRUD 기능을 다 지원한다. 그렇다면 어떻게 인터페이스의 구현체가 없는데도 MemberRepository가 작동하는 걸까? How ? JpaRepository 인터페이스를 상속 받은 MemberRepository 클래스 타입을 찍어보면 다음과 같이 나온다. memberRepository.getClass() => class com.sun.proxy.$ProxyXXX Spring Data JPA가 JpaRepository 인터페이스를 상속받은 인터페이스를 보고 구현체를 만들어서 의존성 주..

Tistory

[Spring] @Controller와 @RestController의 차이 및 구분

이번 포스팅에서는 웹 애플리케이션을 API 방식으로 개발하는데, @Controller는 어디까지 구현하는데 사용하고 @RestController는 어디까지 구현하는데 사용해야 할지에 대해 확실히 정리하고자 한다. @Controller @Controller 어노테이션은 주로 웹 애플리케이션에서 View를 처리하는데 사용된다. Spring MVC에서 요청을 처리하고 뷰 템플릿과 연계하여 결과를 반환한다. 해당 뷰로 데이터를 전달하고 싶은 경우 Model 객체를 사용하여 데이터를 첨부해 반환할 수 있다. @Controller @RequiredArgsConstructor public class MemberController { private final MemberService memberService; @Get..

Tistory

[Spirng/JPA] Dto와 Entity를 분리해서 사용하는 이유

프로젝트를 진행하거나 강의, 책을 보면 항상 엔티티를 직접 반환하지말고 DTO로 변환하여 반환하라는 말을 접하거나 보았을 것이다. 하지만 단순히 "아 ~ 그렇게 하라니까 그렇게 해야지" 보다는 "왜? 엔티티를 직접 사용하지 말고 DTO를 사용해야하는가"에 대해 정리해보려고 한다. DTO와 Entity 구분 DTO(Data Transfer Object) : 클라이언트와 서버 간 데이터 전송을 위해 설계된 객체 Entity : 데이터베이스에 저장되는 데이터 객체로, 데이터베이스와 직접적으로 연결 Enttity를 직접 반환할 경우 생기는 문제점 엔티티 구조 변경 시 발생하는 문제 예를 들어 요구사항이 변경되어 엔티티의 필드 이름이 변경 될 경우, API 스펙이 변경되어 추가 작업이 요구된다. 이는 효과적인 유..

Tistory

[티스토리] 게시글을 작성하는데 실패했습니다. (초간단 해결 방법)

요즘들어 갑자기 게시글을 작성할 때마다 "게시글을 작성하는데 실패했습니다." 라는 오류가 발생했다. 아마 실패 이유는 완료 버튼을 누르고 발행을 클릭하는데, 우측의 대표 이미지 사진이 로딩이 되지 않으면 해당 오류가 발생하는 것 같다. 해결방법 로딩이 되지 않은 이미지를 " - " 버튼을 클릭해 제거하고 다시 이미지를 등록하면 된다.

Tistory

[JPA] @Modifying이란? 그리고 주의할점 (벌크 연산)

@Modifying 이란? Spring Data JPA에서 사용되는 애노테이션으로, @Query 어노테이션을 통해 작성된 변경이 일어나는 쿼리(INSERT, DELETE, UPDATE )를 실행할 때 사용된다. @Modifying을 변경이 일어나는 쿼리와 함께 사용해야 JPA에서 변경 감지와 관련된 처리를 생략하고 더 효율적인 실행이 가능하다. @Transactional @Modifying @Query("UPDATE User u SET u.name = :name WHERE u.id = :id") int updateUserName(@Param("id") Long id, @Param("name") String name); @Query, @Param 알아보기 (클릭) 벌크 연산이란? 벌크 연산은 데이터..

Tistory

[JPA] 지연 로딩(Lazy Loading)과 즉시 로딩(Eager Loading)

JPA에서는 연관된 엔티티를 가져오는 방법으로 지연 로딩과 즉시 로딩이 있다. 지연 로딩 지연 로딩은 연관된 엔티티를 사용할 때까지 로딩을 지연하는 방식이다. 지연 로딩을 사용함으로써 연관 엔티티의 데이터를 사용할 필요가 없는 경우, 쿼리 수행과 시간을 절약할 수 있다. @xxToxx(fetch = fetchType.LAZY) 언제 지연로딩을 사용할까? 연관 엔티티를 많이 사용하지 않는 경우 부모 객체를 조회할 때 자식 객체를 따로 조회하지 않고, 자식 객체가 필요한 경우만 로드하여 사용할 때 유용하다. 실제로 필요한 경우에만 연관 엔티티를 사용하는 경우 연관 엔티티가 필요한 경우에만 로딩하여 불필요한 쿼리가 수행되지 않아, 쿼리 수행 시간을 줄일 수 있다. 대용량 데이터 처리 연관된 엔티티를 무조건 로..

Tistory

[JPA] JPQL의 fetch join(패치 조인)이란?

Fetch Join JPQL에서 성능 최적화를 위해 제공하는 기능으로 연관된 엔티티나 컬렉션들을 한번의 SQL 쿼리로 함께 조회할 수 있다. 연관된 엔티티에 대해 추가적인 쿼리를 실행할 필요 없이 효율적인 로드를 할 수 있는 것이다. 즉, 패치 조인은 성능 최적화에 주로 사용되며, N+1 문제를 해결하는 데 효과적이다. 예를 들어 Order와 Product 엔티티가 있고, 이 둘이 (1 : N) 일대다 연관관계가 있다고 가정해보자. Order 엔티티를 조회하면서 관련된 상품(Product) 엔티티도 한 번의 쿼리로 함께 조회하기 위해 패치 조인을 사용할 수 있다. SELECT o FROM Order o JOIN FETCH o.products 위의 쿼리는 패치 조인을 사용하여 Order 엔티티와 관련된 P..

Tistory

[JPA] 사용자 정의 쿼리 작성과 파라미터 바인딩(@Query, @Param)

@Query Spring Data JPA를 사용할 때, 개발자가 원하는 쿼리를 직접 짜야 한다면, @Query 어노테이션을 사용하여 직접 쿼리를 작성할 수 있다. @Query 안에서 작성한 JPQL에 오타가 있다면 애플리케이션 실행 시점에 문법 오류를 발견할 수 있다. @Query는 JpaRepository를 상속하는 인터페이스에서 사용할 수 있다. public interface UserRepository extends JpaRepository { @Query("JPQL 쿼리작성") List method(); } 만약 나이가 18살 이상인 유저를 조회하는 쿼리를 작성해보면 다음과 같이 작성할 수 있다. public interface UserRepository extends JpaRepository { @..

Tistory

[Python/파이썬] 백준 2589 - 보물섬

문제 설명 입출력 예제 풀이 코드 처음에 육지중에 땅의 크기가 가장 큰 섬를 bfs로 구한다음에 가장 큰 섬에서 또 bfs로 보물 사이의 최단거리를 구해야하나? 라고 생각했다. 하지만 그럴 필요 없이 두 섬에서 보물 사이의 거리가 가장 먼 값을 구하면 된다. 정답 코드 from collections import deque import sys input = sys.stdin.readline r, c = map(int, input().split()) board = [list(input().rstrip()) for _ in range(r)] dx = [1, -1, 0, 0] dy = [0, 0, -1, 1] def bfs(x, y): q = deque() q.append((x, y)) visited = [[-..

Tistory

[JPA] JPQL이란? 사용방법, 기본 문법 총 정리

JPQL (Java Persistence Query Language)이란 ? JPQL은 엔티티 객체를 대상으로 하는 쿼리 언어이다. JPQL의 문법을 보면 다음과 같다. (나이가 18살 이상인 유저를 조회) select u from User as u where u.age > 18 JPQL은 SQL과 유사한 구문을 사용하는 것을 볼 수 있다. 하지만 살짝 다른 특징을 살펴보면 이렇다. JPQL 문법 특징 엔티티 클래스 이름, 엔티티 필드의 대소문자가 일치해야한다. ( 즉, 유저의 나이를 조회하는데 나이 필드가 age면 Age가 아닌 age로 작성 ) JPQL 키워드는 대소문자 구분하지 않는다. (SELECT, select, From, from) 엔티티 객체를 대상으로 하는 쿼리이므로 엔티티 이름을 사용한다..

Tistory

[JPA] 임베디드 타입이란? (@Embeddable)

임베디드 타입은 엔티티의 일부에 별도의 클래스를 사용하여 구현함으로써, 코드를 더 모듈화하고 재사용성을 높이는 방식이다. 임베디드 타입을 사용함으로써 복잡한 속성 그룹을 분리하고 공통 타입을 다양한 엔티티에서 재사용할 수 있다. 이해하기 쉽게 예시를 통해 알아보자. 임베디드 타입을 사용하는 예시 User 엔티티에 다음과 같은 정보가 있다고 가정해보자. @Entity public class User { @Id @GeneratedValue private Long id; private String username; private String city; private String street; private String zipcode; ... } 여기서 city, street, zipcode는 주소에 해당된다...

Tistory

구글 서치콘솔 소유권 인증 HTML 태그 확인하는 방법

이번에 티스토리 스킨을 변경하고 나서 초기화 된 Meta Tag를 새로 등록하게 되었다. 구글 서치콘솔에서 소유권 인증 HTML 태그를 찾았는데 아래처럼 HTML 태그 클릭이 안되서 알 수가 없었다. HTML 태그 찾기 서치콘솔을 아무리 뒤져보아도 HTML 태그 값을 찾을 수가 없었는데 대체 어디에 있을까? 모든 버튼들을 클릭해보며 뒤져본 결과 아래 방법으로 찾을 수 있었다. 1. "설정 -> 소유권 인증" 페이지에서 아래의 "자세히 알아보기" 클릭 2. 클릭 시 나오는 아래 페이지에서 "사용자 및 권한 관리" 클릭 3. 그 다음 나오는 페이지에서 "속성 검색"을 클릭 해 현재 연결된 블로그 링크 클릭 4. 오른쪽의 3개의 점선 버튼을 클릭하면 "소유권 인증 세부정보"가 나온다 이를 클릭 5. 그러면 다..

Tistory

[InteliJ] 라이브 템플릿을 이용해 원하는 주석을 자동완성 되도록 세팅해보자.

보통 테스트 코드를 작성할 때 아래와 같이 주석을 사용해 3단계로 분리하여 작성하곤 한다. 하지만 여러 테스트 코드에 저 주석들을 일일히 줄바꿈해가며 작성하는 건 상당히 번거로운 일이다. 우리는 이 번거로운 일을 해결해줄 인텔리제이의 "라이브 템플릿"을 이용해 특정 단축키를 입력하면 위와 같은 주석이 자동 완성 되도록 세팅해보자. 1. 인텔리제이 설정(Preferences) -> 에디터(Editor) -> 라이브 템플릿(Live Templates) 2. Java 클릭 -> 우측 파란색 + 버튼 클릭 -> 1 라이브 템플릿 클릭 3. 약어 , 템플릿 텍스트 입력 약어는 설정 한 값을 입력하면 템플릿 텍스트에 작성한 코드가 자동완성되어 나타나도록 하는 단축 명령어이다. (iter를 입력하면 for 구문이 자..

Tistory

[OOP] 디미터 법칙에 대한 오해와 디미티 법칙에 대해

객체지향 프로그래밍을 잘 하기 위한 9가지 원칙을 준수해가며 코드를 리팩토링 하는 과정에서 디미터 법칙에 대한 오해가 한 가지 생겼습니다. Enum 클래스의 경우 열거형 상수 값을 가져 올 때 GameMessage.START.getMessage() 이런 식으로 코드 한줄에 점(.)이 2번 들어가게됩니다. 바로 여기서 오해가 생기게 되었습니다. 디미터 법칙은 코드 한줄에 점(.)을 하나만 허용해야 한다고 되어 있는데, "점(.)이 2번 들어갔으니 이건 디미터 법칙 위반아니야 ?" 라는 오해가 생겼는데요. 이 오해에 대해 정리한 제 생각을 공유해보자고 합니다. 디미터 법칙이란? 디미터 법칙은 결합도가 낮은 설계를 위해 생긴 규칙이지, 점(.) 이 몇번 쓰였냐가 중요한게 아니라 객체지향 측면에서 바라봐야한다고..

Tistory

[Spring] ELK + Kafka를 활용해 실시간 로그 수집하기

ELK 도입 이유 ELK가 무엇인지에 대해 알아보고 싶다면 아래 포스팅을 참고. [ELK] ElasticSearch란? ELK란? 내부 구조, 장단점, RDB와 차이 ElasticSearch란? Elasticsearch는 Apache Lucene기반의 Java 오픈 소스 분산 검색 엔진이다. Elasticsearch를 통해 방대한 양의 데이터를 신속하게(거의 실시간) 저장, 검색, 분석을 수행할 수 있다. Elasticsearch는 hstory0208.tistory.com ELK를 적용한 이유 필자의 쇼핑몰 서비스는 아래 처럼 사용자 서버와 관리자 서버가 분리되어 있다. 이렇게 분리된 서버를 관리하기 위해서 ELK를 적용하기전에는 어디서 어느 시점에 장애가 발생했는지 확인하려면 실행되는 서비스의 로그를 ..

Tistory

JWT란? 장단점과 Session 인증 방식과의 차이점을 알아보자.

인증과 인가 JWT와 Session은 서버가 인증을 처리하는 방식으로 먼저 "인증과 인가"의 개념에 대해 알 필요가 있다. 인증 인증은 말 그대로 사용자의 신원을 확인하는 것으로, 특정 인증 요청(로그인, 이메일 인증 등)이 유효한 사용자인지를 검증하는 과정이다. 만약 인증 과정이 없다면 어떻게 될까? 인증되지 않은 사용자가 마음대로 상품 정보를 수정하고 주문하는 등 악의적인 행동을 할 수 있을 것이다. 그래서 인증 절차를 통해 서버가 인증된 사용자를 검증하는 과정이 필요하다. 인가 인가는 이미 인증된 사용자에게 특정 자원에 대한 접근 권한을 부여하는 과정이다. 예를 들어 일반 사용자 "USER"와 관리자 "ADMIN"이 있다고 가정해보자. USER는 ADMIN에 접근 할 수 없어야하고 ADMIN은 US..

Tistory

[JPA] 영속성 전이(cascade)와 고아객체(orphalRemoval)란?

영속성 전이 영속성 전이는 부모 엔티티의 생명주기에 종속적인 자식 엔티티의 상태변화를 같이 처리해주는 역할을 한다. 즉, 부모 엔티티를 저장하거나 삭제 할 때, 자식 엔티티 역시 같이 저장하거나 삭제될 수 있도록 하는 것이다. 이를 통해 자식 엔티티를 추가적으로 저장, 삭제하기 위한 코드를 작성하지 않아도 된다는 장점이 있다. ( 연관관계를 매핑하는 것과는 아무 관련이 없다. ) 사용방법 영속성 전이는 @OneToOne, @OneToMany, @, @ManyToMany 관계에서 사용할 수 있으며, 사용하는 연관관계 매핑 옵션에 cascade = CascadeType.XXX 과 같은 옵션을 설정하여 사용할 수 있다. 주로 사용하는 옵션은 다음과 같다. CascadeType.ALL - 아래의 모든 Casca..

Tistory

[Python/파이썬] 백준 2636 - 치즈

문제 설명 입력과 출력 및 예제 풀이 코드 나름 정석적인 BFS 문제 풀이 방식으로 풀수 있는 문제였다. 이 문제를 풀기 위한 핵심은 다음과 같다. bfs 탐색으로 치즈를 녹여가면서 녹인 치즈의 개수를 구하고, 모두 녹기 한시간전의 녹인 치즈의 수를 알아야 하기 때문에 list에 저장해놓는다. 녹일수 있는 치즈의 수가 없을 때 까지 while 반복문을 돌며 다음 반복문이 돌기전에 time을 + 1 증가시킨다. 정답 코드 from collections import deque import sys input = sys.stdin.readline r, c = map(int, input().split()) board = [list(map(int, input().split())) for _ in range(r)] ..

Tistory

[JPA] Entitiy에서 왜 Setter를 사용하지 말라고 할까?

어느 책에서나 어느 강의에서나 Entity에서는 Setter를 사용하는 것을 지양한다고 한다. 그렇다면 왜 setter를 지양할까 ? setter를 지양하는 이유 사용한 의도를 쉽게 파악하기 어렵다. Member member = new Member(); member.setUsername("김갑동"); member.setAge(50); 위 코드를 보면 member에 값을 설정하는 것은 알겠는데 이게 값을 생성하는 것인지, 값을 변경하는 것인이 의도를 파악하기 힘들다. 그리고 엔티티의 필드가 더 많을 수록 한눈에 파악하는 것이 힘들어진다. 일관성을 파괴한다. public Member updateMember(Long id) { Member member = findById(id); member.setUserna..

Tistory

[JPA] 연관관계 매핑 총 정리

@ManyToOne - 다대일 ( N : 1) 연관관계 매핑 시 가장 많이 사용하는 매핑 방법이다. 다대일은 외래키(FK)를 갖고 있는 "다"쪽이 연관관계의 주인이 된다. 단방향 매핑 @Entity public class Member { @Id @GeneratedValue @Column(name = "MEMBER_ID") private Long id; private String username; @ManyToOne @JoinColumn(name = "TEAM_ID") private Team team; ... } @Entity public class Team { @Id @GeneratedValue @Column(name = "TEAM_ID") private Long id; private String nam..

Tistory

[JPA] 상속관계 매핑, 매핑 정보 상속에 대해 알아보자.

상속관계 매핑 - @Inheritance 관계형 DB는 상속 관계라는 개념이 없고, 슈퍼 타입, 서브 타입 관계라는 모델링 기법이 객체 상속과 유사하다. 그래서 JPA는 객체의 상속 구조와 DB의 슈퍼타입 서브타입 관계를 매핑할 수 있는 상속 관계 매핑을 지원한다. JPA의 상속 관계 매핑은 총 3가지 방법이 존재한다. JOIN 전략 ( JOINED ) 단일 테이블 전략 ( SINGLE_TABLE ) 구현 클래스마다 테이블 전략 ( TABLE_PER_CLASS ) - 많은 단점이 존재해 추천 X 상속 관계 매핑에 사용되는 주요 어노테이션은 다음과 같다. @Inheritance(strategy=InheritanceType.??) 상속관계 매핑을 사용하는 주요 어노테이션으로 부모클래스에 해당 어노테이션을 붙..

Tistory

[Python/파이썬] 백준 5014 - 스타트링크

문제 설명 풀이 코드 각 층마다 버튼을 몇번씩 눌려 도달했는지 저장하기 위해 visited[] 배열을 선언하였다. 강호의 위치(S)부터 bfs로 탐색을 시작한다. 강호의 위치(S)가 스타트링크(G)에 도착하면 스타트링크까지 도착하는데 눌린 버튼횟수를 반환한다. visited[cur] 정답 코드 from collections import deque import sys input = sys.stdin.readline f, s, g, u, d = map(int, input().split()) # 층수, 강호, 스타트링크, 위, 아래 visited = [-1] * (f + 1) def bfs(start): q = deque() q.append(start) visited[start] = 0 while q: cur..

Tistory

[JPA] 연관관계 매핑 주인에 대해서 (mappedBy)

이번 포스팅에서 JPA의 연관관계 매핑의 주인이란 무엇인지? 또 연관관계 매핑의 주인이 왜 필요한지에 대해 알아보려한다. 연관관계 주인이 필요한 이유에 대해 먼저 말하자면, 객치 지향의 패러다임과 데이터베이스의 패러다임에 차이가 있기 때문이다. 먼저 각 패러다임의 차이를 이해할 수 있도록 양방향과 단방향 매핑에 대해 설명하고자 한다. 양방향과 단방향 매핑 양방향 : 두 객체 모두가 각각 참조용 필드를 갖고 참조 단방향 : 두 객체 사이에 하나의 객체만 참조용 필드를 갖고 참조 데이터베이스에서 양방향과 단방향 데이터베이스에는 양방향과 단방향이라는 개념이 없다. 외래키(FK) 하나면 양쪽의 연관관계를 알 수 있다. (양방향 관계의 특성을 갖는다.) 데이터 베이스 테이블은 외래키(FK) 하나로 양쪽 테이블을 ..

Tistory

[JPA] 데이터베이스 초기화 전략 (ddl auto 옵션)

spring.jpa.hibernate.ddl-auto 데이터베이스 ddl 자동 생성 옵션으로 Entity 설정을 참고하여 애플리케이션 실행시점에 Hibernate에서 자동으로 DDL을 생성하여, 필요한 Database의 Table 설정들을 자동으로 수행해주는 기능이다. application.yml spring: jpa: hibernate: ddl-auto: 옵션 ddl-auto의 옵션으로는 5가지가 있다. ddl-auto 옵션 종류 create: 기존테이블 삭제 후 다시 생성 (DROP 후에 CREATE) create-drop: create와 같으나 종료시점에 테이블 DROP (테스트 코드 실행 시 주로 사용) update: 변경분만 반영, 추가만 반영되고 삭제는 반영되지 않는다. (DB Lock을 방지..

Tistory

[JPA] 엔티티 매핑 어노테이션과 속성 값 정리

객체와 테이블 매핑 @Entity @Entity가 붙은 클래스를 엔티티라고 하고 JPA가 관리 한다. JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수이다. 속성 값 속성 설명 기본값 name JPA에서 사용할 엔티티 이름을 지정한다 클래스 이름을 그대로 사용 주의할점 기본 생성자 필수이다. (파라미터가 없는 public 또는 protected 생성자) final, enum, interface, inner 클래스에서는 사용할 수 없다. 저장할 필드의 변수에 final을 사용할 수 없다. @Table 엔티티와 매핑할 테이블 지정한다. 속성 값 속성 설명 기본값 name 매핑할 테이블 이름을 지정한다 엔티티 이름 사용 catalog catalog 기능이 있는 DB에서 catalog를 매핑한다. ..

Tistory

[JPA] 기본 키 매핑 (기본키 자동 생성 전략)

기본키(primary key) 매핑하는 방법은 총 2가지로 직접 할당과 자동 생성이 있다. 직접 할당 : @Id 어노테이션만 사용하여 Id값을 직접할당 자동 생성 : @Id와 @GeneratiedValue를 사용하여 원하는 키 생성 전략을 선택 자동 생성의 키 생성 전략은 다음과 같이 4가지로 분류 된다. 키 생성 전략 IDENTITY : 데이터베이스에 위임 (MYSQL) SEQUENCE : 데이터베이스 시퀀스 오브젝트 사용 (ORACLE) TABLE : 키 생성용 테이블 사용 (모든 DB에서 사용) AUTO : dialect(방언) 설정에 따라 자동 지정 (기본값) 이 각 키 생성 전략에 대해 자세히 알아보자. IDENTITY 전략 기본 키 생성을 데이터베이스에 위임하는 전략 (주로 MySQL, Pos..

Tistory

[Python/파이썬] 백준 1697번 - 숨바꼭질

문제 설명 풀이 코드 숨바꼭질 3번 문제와 완전 똑같은데 순간이동시 시간이 1초 소요된다는 점만 다르다. [Python/파이썬] 백준 13549 - 숨바꼭질3 문제 설명 입출력 예제 풀이 코드 동생의 위치 k에 도달할 때 까지 문제에 주어진 3가지 이동방법으로 탐색한다. 문제에 주어진 범위 0 hstory0208.tistory.com 동생의 위치 k에 도달할 때 까지 문제에 주어진 3가지 이동방법으로 탐색한다. 문제에 주어진 범위 0

Tistory

[데이터베이스] DDL, DML, DCL이란?

DDL(Data Definition Language) - 데이터 정의어 데이터베이스를 정의하는 언어이며, 데이터를 생성, 수정, 삭제하는 등의 데이터의 전체의 골격을 결정하는 역할을 한다. 쉽게 말해 데이터베이스의 테이블을 생성하고, 수정하고, 삭제하는 언어이다. create : 데이터베이스, 테이블등을 생성 alter : 테이블을 수정 drop : 데이터베이스, 테이블을 삭제 truncate : 테이블을 초기화 DML(Data Manipulation Language) - 데이터 조작어 정의된 데이터베이스에 입력된 레코드를 조회하거나 수정하거나 삭제하는 등의 역할을 한다. 쉽게 말해 DB 테이블의 컬럼과 로우를 조작하는 언어이다. 저장된 데이터를 실질적으로 처리하는데 사용된다. select : 데이터 조..

Tistory

[JPA] dialect란?

JPA의 가장 큰 장점은 객체 매핑을 통해 자동으로 SQL 쿼리를 작성해 DB에 전달해준다. 그런데 DB의 종류는 한가지가 아닌 정말 다양한 DB의 벤더들이 있고 각 DB마다 SQL 문법이 다르다. 그럼 JPA는 어떻게 이 수많은 DB들에 우리가 사용하는 DB에 맞는 SQL을 작성하여 전달해줄까? 이 때 사용되는 것이 바로 "Dialect (방언)"이다. dialect는 JPA 구현체(ex: hibernate)가 사용하는 SQL 방언을 추상화한 것으로, 각 DB마다 다른 SQL 문법을 처리해준다. DB마다 맞은 SQL 언어를 JPA가 알아서 자동으로 인지하는 것이 아니라 다음과 같이 DB에 맞는 dialect를 설정해줘야한다. application.yml spring: jpa: properties: hi..

Tistory

[JPA] 내부 동작 방식 (feat. 영속성 컨텍스트란?)

JPA를 사용하다보면 "영속성 컨텍스트"라는 단어를 많이 보게 된다. 하지만 대충 어떤방식인줄은 알지만, 정확히는 이해하지 못했다. 이번에 JPA에서 가장 중요하고 핵심 개념인 "영속성 컨텍스트"에 대해 다뤄보려한다. 영속성 컨텍스트 영속성 컨텍스트를 한국어로 번역하면 "엔티티를 영구 저장하는 환경"이라는 뜻이다. EntityManager.persist(entity) 우리가 Spring Data JPA를 사용할 때는 우리가 직접 EntityManager을 생성해서 객체를 저장하지는 않는다. 하지만 영속성 컨텍스트를 이해하기 위해서는 EntityManager에 대한 이해가 필요하다. EntityManager의 persist() 메서드는 객체를 저장하는 역할을 한다. 하지만 저장하는 곳이 DB가 아닌 바로,..

Tistory

[Python/파이썬] 백준 16953 - A -> B

문제 설명 입출력 예제 풀이 코드 이 문제는 딱 보고 BFS 문제다라고 생각하진 못했지만 너비 우선 탐색 알고리즘 카테고리를 풀고 있기 때문에 BFS로 문제를 풀어 보았다. 큐에 연산을 통해 값이 변할 a와 첫 연산 횟수 1을 튜플로 묶어 추가해준다. 큐가 빌 때 까지 a의 뒤에 숫자 1을 추가한 수와 a * 2를 한 수를 추가하여 연산 횟수를 하나씩 올린다. 만약 a의 수가 b보다 크면 다음 큐를 꺼내어 확인한다. a와 b가 같다면 연산횟수 cnt를 출력하고 종료한다. 큐가 빌때 까지 a와 b가 같지 않다면 -1을 출력한다. 아래의 사진은 a : 2 , b : 162 일 때 bfs를 통해 나온 (a, cnt) 값들이다. 처음에는 a > b 일 때 continue를 하지 않아 정답과 다른 값이 나왔는데 ..

Tistory

[Spring] 스프링으로 파일 업로드, 다운로드 구현 (MultipartFile)

File -> Settings -> plugin 클릭 -> korean 검색 설치하고 인테리제이 재시작하면 정상적으로 한글화가 되어 있다. 초간단

Tistory

[Spring] 스프링 페이징(Paging) 기능 구현 방법 (Thymeleaf, JPA)

사용 기술 스택 - 스프링 부트 2.7.12 - 타임리프 - Spring Data JPA - H2 DB - Lombok 이번에 게시판에 필수요소인 페이징 기능을 추가해보았다. 페이징 기능은 Springframework가 제공하는 @PageableDefault 어노테이션, Pageable, Page 인터페이스로 구현할 수 있다. 이 포스팅은 페이징 기능을 구현하는 설명을 다루므로 페이징과 관계 없는 코드는 과감히 뺐으며, 나머지 부분은 아래 링크로 대체한다. - 게시판 웹 서비스에 관한 코드 : https://github.com/Hyeon0208/posting-webservice - OAuth로 소셜 로그인 구현 : 2023.05.30 - [JAVA/Spring] - [Spring] Google OAu..

Tistory

[Python/파이썬] 백준 13460 - 구슬 탈출2

문제 설명 입출력 예제 풀이 코드 골드1 난이도인 만큼 이전 BFS문제보다 상당히 까다로웠다. 1. 먼저 빨강 공과 파란 공의 위치를 방문했는지 확인할 필요가 있다. 이 부분을 visited 리스트에 공들의 위치 값을 튜플로 넣어 방문 여부를 확인하였다. 2. 주어진 입력 값에서 빨강 공의 위치와 파란 공의 위치를 반환. getPos()라는 메서드를 만들어 각 공의 위치를 반환하도록 하였다. 3. 각 공이 구멍전까지 도달하는데 걸리는 기울이기 횟수를 구한다. move() 함수를 통해 이동하는 위치가 벽이아니고, 구멍에 들어가지 않을 동안 반복하여 각 공의 기울이기 횟수를 구하였다. 이 기울이기 횟수는 두 공의 위치가 겹쳤을 경우를 처리하기 위해 사용한다. 4. bfs를 통해 빨강 공이 구멍에 도달하면 r..

Tistory

[Spring] Google OAuth 로그인 API 키 발급 및 구글 소셜 로그인 구현

Google Cloud 프로젝트 생성 1. 먼저 아래의 주소로 들어간다. Google 클라우드 플랫폼 로그인 Google 클라우드 플랫폼으로 이동 accounts.google.com 빨간색 밑줄친 부분을 선택하고 -> 새 프로젝트 생성을 클릭한다. 프로젝트 이름을 적고 만들기를 클릭한다. OAuth2 동의 화면 OAuth 클라이언트 ID를 만들기 전에 먼저 동의 화면을 구성해야 한다. 자신이 생성한 프로젝트 이름이 맞는지 확인하고, API 및 서비스 -> 사용자 인증 정보를 클릭한다. 먼저 동의 화면을 구성해야한다. 우측의 동의 화면 구성을 클릭한다. 조직을 선택하지 않아 내부는 선택이 되지 않는다. 외부를 선택하고 만들기를 클릭하자. 앱 이름, 사용자 지원 이메일을 작성하고 다음으로 넘어간다. 다른 첨..

Tistory

[IntelliJ] `Cannot resolve symbol` 에러 해결 방법

예전에 만들었던 프로젝트를 열었더니 손하나 댄거 없었는데 아래처럼 모든 코드들이 시뻘게 져있다. 나는 인텔리제이 한글 플러그인을 다운로드 해서 해당 오류가 심볼 'springframework` 를 해결할 수 없습니다. 라고 나온다. ( 한글 플러그인 설치 방법 => 2023.05.31 - [JAVA] - IntelliJ 한글화 적용 방법 ) 해결 방법 프로젝트를 다시 빌드하거나 Gradle 종속성을 새로고침하는 여러 방법이 있지만 나는 이 방법보다는 "캐시 무효화"하는 방법이 가장 직빵이였다. 1. File -> Invalidate Caches를 클릭 2. Restart(무효화 및 다시 시작) 클릭 그럼 이제 캐시가 삭제되고 프로젝트가 다시 빌드 될 것이다. 빌드가 끝난다면 아래처럼 정상적으로 바뀐것을 ..

Tistory

IntelliJ 한글화 적용 방법

File -> Settings -> plugin 클릭 -> korean 검색 설치하고 인테리제이 재시작하면 정상적으로 한글화가 되어 있다. 초간단

Tistory

[Vue.js] vue create 파일 로드 오류 (Window)

vue 프로젝트를 생성하기 위해 "vue create 프로젝트명"을 입력했는데 다음과 같은 오류가 발생했다. 이 시스템에서 스크립트를 실행할 수 없으므로 C:\Users\Home\AppData\Roaming\npm\vue.ps1 파일을 로드할 수 없습니다. 자세한 내용은 about_Execution_Policies(https://go.microsoft.com/fwlink/?LinkID=135170)를 참조하십시오. 해결 방법 해당 오류는 Window의 PowerShell에서 악의적인 스크립트의 실행을 방지하기 위해 실행정책이 설정되어 있기 때문이다. 때문에 우리는 이 실행정책을 변경해주어야 vue create를 실행할 수 있다. 1. 먼저 관리자 권환으로 PowerShell을 실행한다. 2. 아래 명령어..

Tistory

[Python/파이썬] 백준 16234 - 인구 이동

문제 설명 입출력 예제 풀이 코드 더 이상 인구 이동이 일어나지 않을 동안 bfs 탐색을 통해 연합을 이루는 나라들을 구한다. 연합을 이루는 나라가 2개 이상이라면 연합인구수의 평균을 구해 인구이동을 시작한다. 인구 이동이 없다면 반복문을 종료하고 인구 이동이 발생한 횟수를 출력한다. 정답 코드 from collections import deque import sys input = sys.stdin.readline n, l, r = map(int, input().split()) country = [list(map(int, input().split())) for _ in range(n)] dx = [1, -1, 0, 0] dy = [0, 0, -1, 1] cnt = 0 def bfs(x, y): q = d..

Tistory

[Thymeleaf] 타임리프 header, footer 레이아웃 적용하기 (간단 버전)

레이아웃이란? 레아아웃을 사용하는 이유는 만약 100개의 페이지에 똑같은 header와 footer가 들어갈 경우 각각의 HTML마다 똑같은 header와 footer를 추가하는 것은 상당히 비효율적이고 유지보수면에서도 좋지 않다. 그래서 반복되는 화면이 있어 HTML 코드를 줄일 때 레이아웃을 적용하면 상당히 효과적이다. 타임리프 레이아웃 적용하기 의존성추가 레이아웃 기능을 사용하기 위해 아래의 의존성을 build.gradle에 추가하자. implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' 폴더 구조 /layout/fragments/header.html 각 페이지마다 상단 부분에 반복적으로 들어가는 내용을 추가한다. 헤더입니다. /lay..

Tistory

[Python/파이썬] 백준 1389 - 케인 베이컨의 6단계 법칙

문제 설명 입력과 출력 입출력 예제 풀이 코드 아래 표 처럼 각 노드에서 출발하여 해당 노드와 연결된 노드까지의 거리를 구한 뒤, 총합이 가장 높은 노드를 출력하는 문제이다. 케빈 베이컨의 수 0 1 2 3 4 5 1번 노드 0 0 2 1 1 2 2번 노드 0 2 0 1 2 3 3번 노드 0 1 1 0 1 2 4번 노드 0 1 2 1 0 1 5번 노드 0 2 3 2 1 0 정답 코드 from collections import deque import sys input = sys.stdin.readline n, m = map(int, input().split()) # 유저 수, 친구관계 수 relationship = [[] for _ in range(n + 1)] for i in range(m): a, b ..

Tistory

[Python/파이썬] 백준 16236 - 아기 상어

문제 설명 입출력 예제 풀이 코드 먼저 bfs()에서 탐색을 시작할 아기 상어의 자표를 먼저 구해야한다. 그렇게 하지 않고 while문 안에서 아기 상어의 좌표를 찾을 경우 n^3으로 시간초과가 발생한다. 핵심은 다음과 같다. bfs()에서 먹을 수 있는 물고기들을 반환하는데, 가장 거리가 가까운 물고리를 우선적으로 먹으므로 이를 거리순, x좌표순, y좌표순으로 반환한다. 그리고 while문을 통해 더이상 먹을 물고기가 없을 때 까지 반복문을 실행한다. 정답 코드 from collections import deque import sys input = sys.stdin.readline n = int(input()) sea = [list(map(int, input().split())) for _ in ran..

Tistory

[Grafana] 그라파나란? 대쉬보드 만들기 및 활용

그라파나란? 프로메테우스가 DB라고 하면, 이 DB에 있는 데이터를 불러서 사용자가 보기 편하게 보여주는 대시보드가 필요하다. 그라파나는 매우 유연하고, 데이터를 그래프로 보여주는 툴이다. 수 많은 그래프를 제공하고, 프로메테우스를 포함한 다양한 데이터소스를 지원한다 대쉬보드 만들기 1. 그라파나의 주소로 접속한다. http://localhost:3000/dashboards 2. 왼쪽 상단의 삼선버튼을 클릭 후 Dashboards 카테고리를 클릭한다. 3. New를 클릭하고 New Dashboard를 클릭 4. 오른쪽 상단의 저장버튼을 눌려 대쉬보드의 이름을 적어 저장한다. 5. 생성한 대쉬보드에서 상단의 Add 버튼 클릭 후 Visualization을 클릭한다. 이 부분이 바로 매트릭(지표)를 그래프로..

Tistory

[Spring] 메트릭(matric) 직접 등록하기

비즈니스 메트릭 CPU 사용량, 메모리 사용량, 톰캣 쓰레드, DB 커넥션 풀과 같이 공통으로 사용되는 기술적인 메트릭들은 이미 스프링 엑츄에이터에 등록되어 있기 때문에, 우리는 이러한 메트릭들을 가져와 대시보드를 구성하고 모니터링 하면 된다. 하지만 주문수, 취소수, 재고 수량 같은 비즈니스 메트릭 같은 비즈니스 메트릭들을 각각의 비즈니스에 특화되어 있기 때문에 각각을 직접 등록하고 확인해야 한다 비즈니스 메트릭의 예시로 취소수가 갑자기 급증하거나 재고 수량이 최대치를 넘는 부분은 기술적인 메트릭으로 확인할 수 없다. 거기에 더해 어떠한 문제가 생겨 주문 취소가 급격하게 증가한다해도 CPU, 메모리 사용량 같은 메트릭에는 아무런 문제가 발생하지 않아 문제를 인지하기 힘들다. 이 경우에 비즈니스 메트릭을..

1 2 3 4