Development
[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에 내용이 부족해..
[Troubleshooting] 쿼리 최적화 : Subquery -> JOIN
문제상황 개발 환경은 eGovFramework에서 ibatis XML을 사용해 query를 날리고, DB는 CUBRID이다. 기존 쿼리는 아래와 같고, 시간은 약 200초로 응답이 너무 오래 걸려 기능 개선 요청이 들어온 상황이다. table명, column명은 맥락과 비슷하게 조금 수정했지만 전체 query의 구조는 동일하게 작성했다. 분석 일단 코드를 보면 개판이다. 학과 종류에 따라 subject에서 무슨 값을 가져올지가 다른데, 이 로직 하나 때문에 나머지 subquery 전체가 복사+붙여넣기이다. 따라서, 이 부분을 해결할 수 있는 방법을 고민하는 것이 첫 번째 문제이다. 두 번째로, 실행계획이다. 이 query를 아주 간단하게 표현하면 아래와 같으며, WHERE EXISTS문 subquery가..
[개발서적] Clean Architecture 정리
Clean Code, The Pragmatic Programmer에 이어 Clean Architecture를 읽었다. Clean Architecture는 처음부터 끝까지 의존관계를 줄이는 방법을 소개하며 이를 통해 Open Closed Principle을 만족하는 유연한 프로그램을 작성하는 방법을 알려준다. 아직까지 느낀 점은 결국 중복을 없애고 DIP를 통해 추상화에 의존하게 작성하면 그것이 좋은 구조다는 것이다. 처음부터 끝까지 dependency에 관해 일관성 있게 이야기하기 때문에 하나 이상의 개발 프로젝트를 진행했던 개발자라면 자신이 진행했던 프로젝트의 구조와 dependency를 생각해 보는 계기가 될 것이다. 앞선 포스팅과 마찬가지로 감명깊게 읽은 부분, 필요하다고 생각하는 부분, 중요하다고..
[개발서적] The Pragmatic Programmer 정리
Clean Code에 이어 The Pragmatic Programmer를 읽었다. 이 책은 개발자로써 어떠한 마음가짐을 가져야 하는지, 어떠한 방법을 사용해야 하는지에 대해 매우 개략적으로만 다룬다. 주변에서 이제 막 프로젝트를 하나 끝낸 개발자 지망생들에게 한 번씩 읽어보라고 추천하고 싶은 책이다. 현대 개발론에서 사용하는 agile, prototype, CICD, TDD, DDD 등에 대한 내용을 한 단락으로 정리하기 때문에 개발하면서 불편했던 점을 이렇게 해결할 수 있구나, 하는 큰 방향성을 제시해 주기 때문이다. Clean Code 포스팅과 마찬가지로 감명깊게 읽은 부분, 내게 필요하다고 생각하는 부분만 간단하게 정리했다. 그 중에서도 중요하다고 느낀 문장은 *를 쳐서 표기했다. 서문 개발자는, ..
[개발서적] 다시 쓰는 Clean Code 정리
개발에 대해 아무것도 모를 때 읽었던 Clean Code와 어느 정도 경험을 쌓고 나서 다시 보는 Clean Code는 느낌이 달랐다. 직접 프로그램을 유지보수하지 않고 개발만 했던 시절에는 모든 내용이 내 머리속에 있었기 때문에 "대체 왜 interface를 사용하는 거지? 굳이? 그냥 수정하면 되는 거 아닌가?"라고 생각했다. 지나고 보니 우매한 생각이었다. 여러 프로그램을 유지보수하다보니 요구사항을 반영할 때 기존 코드를 최소한으로 만져야 하고, dependency가 꼬여있지 않아 추가하고 싶은 기능만 추가하는 것의 중요성을 깨달았다. 기존 코드가 난잡하면 유지보수 하는데는 훨씬 많은 cost가 든다는 걸 개발병을 하면서 너무 많이 겪었다. 나는 소스 코드는 하나의 글이라 생각한다. 잘 쓴 글은 서..
[Java] Collection
이 글에서는 java의 collection에 대해 알아볼 것이다. Collection Collection은 object group을 나타내는 object이다. 편하게 data sturcture 집합이라고 이해하면 된다. Java collection에는 위와 같은 많은 interface와 class가 있는데, 이들에 대해 알아볼 것이다. List 순서가 있으며, 데이터 중복이 허용된다. ArrayList index를 가지고 있어 조회 시 성능이 빠르다. O(1)이다. erase나 insert 시 해당 위치 앞/뒤에 있는 모든 element 위치를 조정해야 하므로 O(n)이다. 따라서 삽입/삭제 성능이 느리다. thread-safe하지 않다. object array로 구현되어 있다. LinkedList 조회..
[Java] Multi Thread
이 글에서는 java에서 사용하는 thread와 multi-thread의 개념만 간략히 짚고 넘어 간다. Thread Thread는 process 내에서 작업의 흐름 단위이다. 하나의 thread는 하나의 작업만 처리하지만, 여러 개의 thread는 병렬로 여러 개의 작업을 처리하기 때문에 더 빠르다. Concurrency & Parallelism 모든 작업은 컴퓨터의 CPU가 작업하며, CPU의 core가 thread를 실행한다. 하나의 core가 여러 개의 thread를 수행할 수도 있고(concurrency), 여러 개의 core에서 여러 개의 thread를 수행할 수도 있다.(parallelism) 하나의 core가 여러 개의 thread를 작업할 때는 각 thread를 조금씩 실행하고 다른 th..
[Java] String vs StringBuffer vs StringBuilder
Java에서는 문자열을 사용할 때 String, StringBuffer, StringBuilder 이렇게 3개의 class를 사용한다. 이 글에서는 이 세가지 class의 차이를 알아볼 것이다. String 앞선 포스팅에 언급했듯 String은 reference type이자 immutable이며 다음 과정을 거쳐 address를 받아온다. literal로 할당 시 intern() method를 호출한다. string constant pool에 해당하는 값이 있으면 그 address를 받아온다. string constant pool에 해당하는 값이 없으면 그 값을 string constant pool에 할당하고 address를 받아온다. new String()과 같이 constructor로 할당 시 hea..
[Java] Primitive Wrapper Class
이 글에서는 java의 primitive wrapper class에 대해 알아본다. Primitive Wrapper Class Primitive Wrapper Class는 primitive type을 object로 다뤄야 할 때 사용한다. 대표적으로 collection이나 generic에 들어가야 하는 값은 모두 object여야 하는데 primitive type의 collection이 필요할 수도 있는데 이 때 primitive wrapper class를 사용한다. 참고로 primitive type는 byte, char, short, int, long, float, double, boolean 이렇게 8종류밖에 없으며 다음과 같이 wrapping한다. byte - Byte char - Character ..
[Java] Generic
이 글에서는 java의 generic에 대해 다룬다. Generic Generic이란 java에서 class, interface 또는 method를 정의할 때 type을 pameter화하는 것이다.(type을 parameter로 사용해 일반화하는 것이다.) Generic은 compile time에 object type을 확인하기 때문에 casting을 줄여주고 type 안정성을 보장받을 수 있다, type별로 작성해야 하는 코드의 양을 크게 줄여준다. 사용 방법 : class, interface 아래와 같이 class나 interface를 선언 시 이름 뒤에 keyword를 이용한다. 1개 이상의 type을 넣을 수 있다. method의 parameter type이나 return type으로 해당 gen..
[Java] Java Virtual Machine
이 글에서는 java가 실행되는 환경인 Java Virtual Machine에 대해 알아볼 것이다. Java 8 이후에 변경된 점을 포함하기 때문에 기존 PermGen 영역에 위치하던 Method Area를 Metaspace라고 표기했으며, static과 constant pool이 heap으로 옮겨졌다는 것을 반영한다. JDK, JRE, JVM Java의 구동에는 여러가지가 필요하다. Java Development Kit - Java 개발 도구 Java Runtime Environment - Java용 실행 환경 Java Virtual Machine - Java 실행 프로그램 Java는 여러가지 OS에서 사용 시 java platform indepence를 보장받기 위해 virtual machine을 사..
[Java] Exception Handling
이 글에서는 Java에서 사용하는 예외 처리 방법을 알아볼 것이다. Error vs Exception Java에서 Error는 치명적인 오류이며 프로그램 내에서 수습이 불가능하다. Stack overflow나 Out of memory같이 JVM의 실행에 문제가 생겼다는 것이므로 대처할 수 없다. 반면 Exception은 Error보다는 경미한 오류이며 프로그램 내에서 수습할 수 있다. Java의 exception은 runtime-error과 compile error로 나뉘며 runtime error는 unchecked exception, compile error는 checked exception으로 부른다. (이 문장에서의 error는 Java에서 사용하는 Error와는 다르다! runtime error..
[Java] abstract class vs interface
이 글에서는 java에서 사용하는 abstract class와 interace, 그리고 둘의 차이를 알아볼 것이다. Abstraction 이전 글에서 abstract를 다음과 같이 설명했다. 일반적으로 컴퓨터 과학에서 추상화라 함은 불필요한 정보(세부 구현 등)는 숨기고 중요한 정보만을 보여주는 것이다. 객체지향에서 추상화는 객체를 만들 때 사용하는 개념으로, 일반화를 통해 공통된 속성과 행위를 추출하는 것이다. 불필요한 정보(객체마다 다른 특이한 정보)는 숨기고 중요한 정보(공통된 속성과 행위)를 상위 class로 추출하는 것이다. 추상 클래스 Abstract Class abstract class는 abstract로 선언된 class이거나 abstract method가 1개 이상 포함된 class를 말..
[Java] Polymorphism - static polymorphism, dynamic polymorphism, casting
이 글에서는 Java의 inheritance와 연관된 것들에 대해 알아볼 것이다. 다형성 Polymorphism 앞선 포스팅에서 상속을 다음과 같이 정의했다. 하나의 component(variable, method, class, ...)가 casting, overloading, 또는 overriding을 통해 상황에 따라 다르게 사용되는 것을 말한다. Overloading은 이름은 같지만 parameter를 다르게 해, 이름만 같은 함수로 사용하는 것이며, static binding이다. Overriding은 parent class의 method를 child class에서 재정의하는 것이며, dynamic binding이다. polymorphism을 이용하면 code reuse, 유지보수성, 유연성이 증..
[Java] Inheritance - access modifier, super, overriding
이 글에서는 Java의 inheritance와 연관된 것들에 대해 알아볼 것이다. 상속 Inheritance 앞선 포스팅에서 상속을 다음과 같이 정의했다. parent class로부터 새로운 child class를 만드는 것이다. 또한 상속받는 child class는 새로운 attribute나 method를 추가해 확장해 나갈 수 있다. 상속을 통해 class hierarchy를 만들 수 있다. access modifier에 따른 상속 parent class member의 access modifier에 따라 child class에서 사용여부가 달라진다. [public 또는 protected access modifier로 선언된 member]들만이 child class에서 바로 접근할 수 있으며, [pri..
[Java] static, final
이 글에서는 Java에서 사용하는 static과 final에 대해 알아볼 것이다. static class 내에서 static으로 선언된 member는 class로 정의된 모든 instance에서 같은 값을 가진다. (class와는 별도로 생성되기 때문에 class를 정의하지 않고도 사용할 수 있다) 해당 member는 class가 메모리에 로드될 때 heap에 올라가기 때문에 instance가 생성되기 전에도 사용할 수 있으며, object와는 별도로 만들어지기 때문에 class 크기에 영향을 주지 않는다. static member는 GC가 관리하긴 하지만, 해당 class가 static member를 참조하지 않는 경우가 거의 없기 때문에 계속 남아 있게 되므로 남발하는 경우 메모리 효율이 나빠진다는 ..
[Java] Class - constructor, access modifier, identity & equality & hashCode
객체지향 프로그래밍 포스팅에서 객체지향의 특징을 몇 가지 살폈었다. Java는 객체지향 언어인만큼 class를 사용하고 있으며 객체지향의 특징 중 encapsulation, inheritance, polymorphism 등이 적용되어 있다. 이 글에서는 Java에서 사용하는 class에 대한 기본적인 몇 가지를 알아볼 것이다. Java에서 class 앞선 포스팅에서 다음와 같은 내용을 작성했다. 객체란 어떤 개념을 추상화하고 모델링한 요소이다. 객체는 상태(state)와 행위(behavior)를 가지고 있으며 행위를 통해 상호작용한다. class는 instance를 만들기 위한 설계도이며, instance는 class라는 설계도를 이용해 만들어진 메모리에 할당된 실체이다. class는 객체를 만들기 위한..
[Java] Data types, 예외적인 String, 그리고 call by value
이 글은 Java의 data type와 call by value를 정리한 글이다. data type에 따라 function parameter로 넘기고 값을 조작했을 때 어떻게 바뀌는지, 그리고 특히 예외적으로 작동하는 string의 동작 방식에 대해 정리했다. C++의 reference C++에서는 reference라는 변수형을 지정할 수 있다. C++에서 reference는 pointer처럼 동작하지만 변수처럼 사용할 수 있는, 변수의 주소값을 저장하는 변수이다. #include using namespace std; int main(){ int number = 10; int &reference = number; cout
[Socket.io] Socket.io를 이용한 실시간 채팅
읽기 전에 Socket.io와 room에 대해 알고 있어야 합니다. Socket.io 공식 문서를 참고해 주세요. 채팅 로직 실시간 채팅을 위해서는 다양한 경우를 고려해야 합니다. 단순하게 모든 사용자가 socket 접속이 되어 있을 경우만 생각한다면 socket 이벤트만 전송하면 되겠지만 실제로는 그렇지 않습니다. 누군가는 인터넷 연결 환경 문제로 인해 오프라인이었다가 온라인이 되는 경우도 있을 수 있고, 누군가는 나중에 채팅을 확인하기 위해 앱을 껐을 수도 있습니다. 지금부터 미어캣이 이 경우의 수들을 어떻게 처리했는지 알아보겠습니다. 여기서는 실시간 채팅을 위해 socket.io를 사용합니다. 클라이언트에 2개의 socket 연결을 이용하는데, 하나는 실시간 메시징을 위해서이고 나머지 하나는 메시지..
[Utils] 쓸만한 VS Code extension들
Color Highlight #000000처럼 작성한 색깔 코드를 색으로 보여줍니다. Git Lens 코드가 언제 적혔는지, 누구에 의해 적혔는지 등등 코드 작성자에 대한 내용을 보여줍니다. Markdown Preview Mermaid Support & Markdown Editor 마크다운 에디터. mermaid와 md 파일을 미리보기로 보여줍니다. Prettier 코드 정렬해주는 기능입니다. TODO Tree & TODO Highlight 작성한 'TODO' 등의 태그를 하이라이트해서 보여주고, 그 태그들을 tree로 보여줍니다. 태그는 추가할 수 있습니다. ngrok 개발 중, 포트 우회가 필요할 때 사용하면 좋습니다.
[Utils] 마크다운 API 명세 템플릿
가능하다면 gitbook이나 swagger같은 공유 가능한 API 명세서를 쓰는 것이 제일 좋겠지만, 그렇지 못할 때는 markdown이라도 써서 API를 명세해야 합니다. 개인적으로 gitbook의 명세가 상당히 마음에 들어서 비슷하게 템플릿을 만들어 봤습니다. 적용한 모습은 다음 페이지에서 참고하면 됩니다. https://github.com/osamhack2022/APP_Meerkat_IQDan/wiki/API-Specification 코드는 아래와 같습니다. # 일반 API 명세 ![](https://img.shields.io/static/v1?label=&message=GET&color=blue) ![](https://img.shields.io/static/v1?label=&message=POST..
[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 + 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] 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] 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을 사용하는 이유를 깨달은 것 같은데. 처..