Development/Spring
[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에 내용이 부족해..
[Spring] Spring 메일 발송 - 회원가입 인증 메일/ID 찾고 메일로 전송/비밀번호 변경 및 임시 비밀번호 메일로 전송
https://offbyone.tistory.com/167 https://velog.io/@ehdrms2034/Spring-Security-JWT-Redis%EB%A5%BC-%ED%86%B5%ED%95%9C-%ED%9A%8C%EC%9B%90%EC%9D%B8%EC%A6%9D%ED%97%88%EA%B0%80-%EA%B5%AC%ED%98%84-4-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%9D%B8%EC%A6%9D-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%95%84%EC%9D%B4%EB%94%94-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%B0%BE%EA%B8%B0 https://m.blog.naver.com/jny9708/22177..
[Spring] Spring image 업로드 / 다운로드(리턴) / 인코딩
spring에서 서버로 image를 업로드 해야 하는 경우가 있다. 일반적으로 database에 이미지를 넣지는 않는데, 생각하기에는 - front - back - db로 총 2번 이미지를 넣어야 함 - db로 넣으면 binary 형식으로 이미지가 저장되는데 낭비임 - file system에서 굳이 binary로 바꿀 이유가 없다. 이 2가지 정도 이유가 있는 것 같다. 그래서 일반적으로 A에 대한 이미지는 A entity에 A 이미지가 있는 path를 db에 넣고, 조회/수정/삽입/삭제 할 때 해당 path를 이용해서 저장하는 것 같다. 먼저 항상 그렇듯 의존성 추가 해 준다. build.gradle implementation 'commons-io:commons-io:2.6' 다음으로 applicati..
[Spring] Spring exception handler 추가 - ambiguous handler
기존에는 아래와 같이 ResponseEntityExceptionHandler를 상속받아서 handling 했었다. @Slf4j @RestControllerAdvice public class GlobalExceptionHander extends ResponseEntityExceptionHandler { // 입력 정보가 다를 때 // sql에 중복되어 있을 때 @ExceptionHandler(value = {DataIntegrityViolationException.class}) protected ResponseEntity handleIntegrityViolateException(){ log.error("handleDataException throws Exceptions : {}", ErrorCode.PAR..
[Spring] slf4j를 이용한 spring logging
로그의 목적은 아래 2가지 정도가 있다. - 서비스 동작 상태 파악 - 장애 파악 및 알림 logging은 slf4j 등 로그 라이브러리를 사용할 것이다. 로그 레벨 - fatal : 어플리케이션 종료까지 만드는 error. - error : 의도하지 않은 오류 발생, 종료는 안 됨. - warn - info : 서비스 동작 상태 - debug : 개발자가 보기 위한 것 - trace 인데, '의도하지 않은 에러'를 나타내는(ex. database connection error) error, 기록을 남기기 위한 info 2개를 사용하면 될 것 같다. 또 로그는 파일로 작성할 거고, 너무 많이 쌓이면 다른 것으로 빼 주어야 한다. https://victorydntmd.tistory.com/173?categ..
[Spring + Swagger] Swagger 사용
swagger는 controller에 @RestController annotation을 붙인 것들에 대해, api 명세 목록을 제공해주는 명세 자동화 툴이다. build.gradle implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' 이것들 추가한다. 다음으로 config를 만들자. SwaggerConfig.java @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket a..
[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..
[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 ..
[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) ..
[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..
[JPA] JPA MySQL 몇 가지 이슈에 대해서,,, GenericJDBCException
1. JPA는 맞게 짠 것 같은데 JPA가 안돌아 가는 경우. could not execute statement; nested exception is org.hibernate.exception. org.springframework.orm.jpa.JpaSystemException: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute 이런 에러가 뜨는 경우 - JPA, 즉 Spring에서 설정한 언어(UTF-8)과 mysql의 언어 셋, charset이 달라서 그렇다. 나는 docker로 mysql을 설치했다. 그런데 여기서 MySQL에서 아래 명령어를 쳐보자..
[JPA] JPA 단방향 vs 양방향
JPA를 이용해서 구성하고 있는데... 다대일 단방향과 양방향에 대한 고찰이다. 일반적으로 다대일을 쓰는 거라고 한다. 그러면 member - team 관계가 있다고 가정하자.. (member:team=n:1 관계) 여러 자료들을 찾아보니 다대일 관계를 가질 때, '다' 쪽에서 외래키를 가지고 다대일 단방향 관계를 구성한다고 배웠ㄷ다. 필요할 때 양방향 관계를 구성한다고 하고. 그런데 이 '필요할 때'를 잘 모르겠다. 정말 양방향 연결이 필요한가? JPA는 '다'쪽에서 '1'쪽에 대한 정보를 가지고 있고, '1'쪽에서 '다'쪽에 대한 정보는 가지고 있지 않다. member-team의 관계에서 member는 어떤 team인지 알 수 있지만, team에 어떤 member가 있는지는 알 수 없기 때문이다. 그..
[Spring] 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 정리, 인프런 김영한 스프링
스프링 토이프로젝트를 하나 만들긴 했지만 내가 한 것은 기술을 어떻게 사용하느냐지, 어떻게 만들어졌는가는 생각하지 않았다. 모든 분야가 그렇듯 동작 원리에 대해 이해해야 더 좋은 코드를 작성할 수 있기 때문에 스프링 그 자체에 대해 공부를 조금 해 볼 예정이다. 인프런의 김영한님의 강의를 몇 개 들을 예정이다. https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/dashboard 이 글은 위 링크에 있는 강의를 정리한 글이다. 이후에 유료강의들은 비공개로 정리할 예정이고. 1. 프로젝트 환경설정 1) 프로젝트 생성 나는 VS Code ..
[Lombok] Lombok의 Getter, Setter with VS Code
@Getter @Setter annotation attribute에 붙이면 해당 attribute에 getter, setter method가 생기고 class에 붙이면 class의 모든 attribute에 생김. 변수 이름이 asdf면 getAsdf() setAsdf() 이 함수들이 생성이 됨. VS Code에서 작동하지 않는 경우 1) extension에서 Lombok Annotations Support for VS Code 설치 2) build.gradle dependency에 아래 코드 추가 compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok'
[Docker + Spring] Docker gradle Spring Boot with VS Code JPA MySQL 게시판 생성 - 5. 자잘한 수정사항
1. local에서 F5나 build해서 실행하면 잘 되었는데, docker 환경/서버에 올리니까 안됨! 아래 게시글을 참고했다. return "~.html"을 할 때 습관적으로 제일 앞에 /를 붙여 절대경로로 만들어서 문제가 생겼던 것 같다. 빼니까 잘 된다. https://devkingdom.tistory.com/149
[Docker + Spring] Docker gradle Spring Boot with VS Code JPA MySQL 게시판 생성 - 4. EC2 배포
1. EC2에 인스턴스 생성 IAM 계정으로 시작하는 것을 추천한다고 한다. (IAM 계정은 해킹당하더라도 다른 container에 권한이 부족하기 때문에 접속 불가) 1) instance 시작 2) AMI 선택 3) instance type 선택 4) instance detail 선택 5) storage 추가 6) 태그 추가 7) 보안 그룹 설정 서버 접속을 위한 SSH 접근은 포트 22번, 웹 서버 활용을 위한 포트는 443으로 적용되었다. 8) 키 페어 선택 ssh 접속을 위해 필요한 파일이라 한다. 이것이 있어야 인스턴스에 접속할 수 있다는 것 같다. 9) instance 확인 뭔가 돌아가고 있다. 상태 검사가 검사 통과 상태면 인스턴스 실행 중이라는 것이다. 2. EC2에 인스턴스에 접속 1) ..
[Docker + Spring] Docker gradle Spring Boot with VS Code JPA MySQL 게시판 생성 - 3. 검색기능Search
1. 검색기능 - SELECT resources/templates/list.html의 검색하기 버튼을 누르면 /board/search로 GET method가 요청된다. 요청이 가면 controller에서는 boardService.searchPost(keyword) method를 이용해 해당하는 DTO만 SELECT하게 하고, 받아온 DTO list를 model에 addAttribute한 후 return하자. 1) Controller /src/main/java/com/example/testcompose/controller/BoardController.java package com.example.testcompose.controller; import com.example.testcompose.dto.Boar..
[Docker + Spring] Docker gradle Spring Boot with VS Code JPA MySQL 게시판 생성 - 2. 게시글 CRUD
1. 게시글 작성, Create 앞 게시글에서 spring의 구조에 대해 다루었다. Controller, Service, Repository, DTO, Entity를 복습하자면 아래와 같다. 해당 프로젝트에서 service는 JPA interface인 repository를 불러올 것이다. - controller controller는 client의 요청을 받아서 처리해준다. controller는 service를 호출해서 요청을 처리한다. - service service는 business logic을 수행한다. - Repository spring data JPA는 repository라는 interface를 제공한다. JPA를 추상화 한 것으로, interface에 맞는 규칙대로 입력하면 spring이 알아서..
[Docker + Spring] Docker gradle Spring Boot with VS Code JPA MySQL 게시판 생성 - 1. 전체 구조 잡기
https://victorydntmd.tistory.com/325 https://velog.io/@max9106/Spring-Boot-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1 위 두 글을 바탕으로 구성하고, 진행했다. 1. 수정사항, 의존성 설정, 전체적 구조 잡기 개발환경 IDEA : VS Code Java : openjdk 11 Gradle : 7.0.2 Spring Boot : 2.5.2 Docker : 20.10.7 라이브러리 MySQL : DB JPA : DB와 연동을 위해 필요함 Thymeleaf : resource/templates에 있는 html 파일을 읽어오기 위해 필요함 Lombok : NoArgsConstructor라는 Con..
[Spring] Spring Boot MVC 개념 이해
SWM 프로젝트로 spring을 이용해 BE 구성을 하지 싶다. 그래서 배워보고자 spring을 이용해 게시판 CRUD를 해 보자. 개인적으로, Node.js에 비해 Spring이 진입장벽이 더 높은 것 같긴 하다. 나는 C++을 메인으로 학교에서 배웠기 때문에 API 코드를 짜면 그 url로 접속하면 해당 함수 내에 있는 것들만 수행된다는 것이 상당히 직관적이었기 때문이다. 그런데 Spring은 MVC 2 형태라고 해서, controller, service, DAO, servlet, DB와 연동을 위해서는 mybatis, JPA, hibernate, mapper 등, 또 그걸 쓰려면 entity, DTO, repository까지... 알아야 할 것이 너무 많다. 처음에는 "springboot 시작하기"..