분류 전체보기 43

[IntelliJ] docker compose로 실행한 애플리케이션 인텔리제이로 디버깅 하기

MSA 프로젝트를 개발하면서 discovery, gateway, config를 포함하여 7개의 마이크로서비스를 docker compose로 하나의 컨테이너로 실행을 하고있다. IntelliJ와 Docker Compose를 활용하여 실행 중인 애플리케이션의 디버깅 환경을 설정하는 방법을 단계별로 정리했다. 1. 디버그 포트 노출각 마이크로서비스에 대해 JVM 디버깅 포트를 노출한다. ( docker-compose.yml 수정) 2. environment 에 JVM의 디버그 모드를 활성화 하는 옵션 설정JAVA_TOOL_OPTIONS : JVM의 디버그 모드를 활성화 하는 옵션모든 서비스는 고유한 디버깅 포트를 사용해야 한다.transport=dt_socket : 디버거와의 통신에 소켓을 사용 3. Inte..

유비쿼터스 언어(보편 언어)의 중요성을 느끼며

유비쿼터스 언어(Ubiquitous Language, 보편 언어)는 도메인 주도 설계에서 중요한 개념으로,  프로젝트의 모든 이해관계자들이 공통으로 사용하는 언어를 의미한다. 도메인에서 사용하는 용어를 코드에 반영하지 않으면 코드의 의미를 해석해야하는 부담을 준다. 개발 도메인이 명확한 직장에서 근무하며 여러 프로젝트를 진행하다 보니, 유비쿼터스 언어의 중요성을 점점 더 깊이 체감하게 되었다. 디자이너, 분석가, PM 등 다양한 분야의 동료들과 소통하고 협업하는 과정에서, 이 보편 언어의 필요성이 더욱 두드러졌다. 프로젝트를 진행하면서 유비쿼터스 원어의 중요성을 깨닫게 된 주요 이유들은 다음과 같다. 1. 의사소통의 오해와 실수'혼잡도' 와 '밀집도' 처럼 비슷하지만 다른 의미를 가진 용어들로 인해 오해..

[Git] Git Submodule 로 다른 저장소 코드 가져오기

git 서브모듈은 git 저장소를 다른 git 저장소의 하위 디렉토리로 유지하는 기능이다. 다른 저장소를 프로젝트에 복제하고 커밋을 별도로 유지할 수 있다. 사내에서 공용으로 쓰는 간단한 JavaScrpit 파일을 서브모듈로 등록해 보았다 1. 서브모듈 add git submodule add {서브모듈 repository url} {로컬에 저장할 경로, 입력안하면 root에 저장됨} 인텔리제이를 사용하기때문에 터미널을 열어서 바로 입력했다.  2. 서브모듈 추가 확인 위 명령어로 서브모듈을 추가하면, 서브모듈 폴더가 생기고 .gitmoudules 라는 파일에 서브모듈의 정보가 생성된다. 생성된 폴더에 있는 파일을 그냥 사용하면 된다.  3. 협업 (업데이트) 이 서브모듈을 추가한 프로젝트를 다른 사람이 ..

프로그래밍/Git 2024.10.21

[JavaScript] 팝업 오늘 하루 보지 않기 (LocalStorage)

LocalStorage를 사용하여 페이지가 다시 로드될 때 팝업을 다시 표시할지 결정하는 방식으로 구현 1. 페이지 로드 시localStorage.getItem('doNotShow') 를 통해 오늘 하루 보지 않기를 설정했는지 확인한다.window.onload = function() { const doNotShow = localStorage.getItem('doNotShow'); if (!doNotShow) { popup.style.display = 'block'; }}; 2. "오늘 하루 보지 않기" 버튼 클릭 시현재 날짜를 localStorage 'doNotShow'에 저장.팝업 사라지게 함doNotShowButton.addEventListener('click', func..

[자동매매, SpringBoot] 3. 매도, 매수

2024.05.11 - [프로젝트/SpringBoot 업비트 자동매매 프로젝트] - [자동매매, SpringBoot] 2. 계좌 조회 이전 글에서 계좌 조회 기능을 만들었고, 매도 매수 기능을 추가 할 것이다. 업비트 개발자센터에서 API Reference를 보면  https://api.upbit.com/v1/orders 로 POST 요청을 보내 매도, 매수요청을 할 수 있고 Request Parameter 중 side 파라미터로 매수/매도 를 구분 한다. 나는 직관적으로 매수 / 매도 함수를 나눠서 만들것이다. 1. Util Class매수 / 매도 요청을 보낼 때 필요한 Jwt Token에는 클레임에 query_hash, query_hash_alg 를 포함해야 한다. 기존에 만든 Util Class에 ..

[자동매매, SpringBoot] 2. 계좌 조회

2024.05.11 - [프로젝트/SpringBoot 업비트 자동매매 프로젝트] - [자동매매, SpringBoot] 1. 프로젝트 생성 및 계획 이전 글에서 프로젝트 생성 및 계획을 마쳤고, 계좌 조회 기능을 추가할 것 이다. 업비트 개발자센터에서 API Reference를 보면 https://api.upbit.com/v1/accounts 로 GET 요청을 보내면 내가 보유한 자산 리스트를 Response 받을 수 있다고 한다. 화폐, 수량, 묶여있는 수량, 매수평균가, 매수평균가 수정 여부, 평단가 기준 화폐 정보를 받을 수 있는데 화폐, 수량 정보만 있으면 될 것 같다.  1. Util ClassAPI 요청을 보내려면 Header로 Authorization token을 보내야 하는데 업비트에서 지급..

[자동매매, SpringBoot] 1. 프로젝트 생성 및 계획

이전에 업비트 자동매매 프로그램을 Python으로 개발 후 GCP 환경에서 돌렸었는데 웹에서 매매 상황을 직관적으로 확인하기 위해 SpringBoot로 다시 개발하려고 한다. SpringBoot 3.2.5GradleJava 17IntellijDB 안씀Scheduling 함수로 자동매매가 계속 이루어지게 할 계획이다. 1. start.spring.io 에서 프로젝트를 생성 (Spring Web, Lombok 정도만 Dependency 추가해서 생성했다)  2. Config Class Upbit API를 사용하기 위해 발급받은 AccessKey와 SecretKey를 application.properties에 입력 하고 (key는 타인에게 절대 노출하지 마세요) AccessKey, SecretKey, Url ..

[Spring] Spring Security 5.7.0 이상 Config, desprecated

Spring Boot 3.0 이상 부터는 Spring Security 6.0 이상 버전이 적용된다. 이 전 버전들고 동일하게 SecurityConfig를 작성하고 나니 desprecated 된 (더 이상 사용하지 않는)함수들이 많아서 기록 하고자 함 extends WebSecurtyConfigurerAdapter -> SecurityFilterChain @Bean 등록 람다식 사용 EnableGlobalMethodSecurity -> EnableMethodSecurity authorizeRequests -> authorizeHttpRequests access("hasAnyRole('ROLE_ADMIN', 'ROLE_MANAGER')") -> .hasAnyRole("ADMIN", "MANAGER") any..

[JPA] 순환 참조, API 호출 시 순환 참조가 발생하는 이유

JPA의 순환 참조란 객체 간의 상호 참조가 무한 반복되는 경우를 말한다. 객체 그래프에서 한 객체가 다른 객체를 참조하고, 그 다른 객체가 다시 처음 객체를 참조하는 상황이고 스택 오버 플로우가 발생할 수 있다. 사이드 프로젝트 진행 하던 도중 Service 단 개발을 끝내고 API를 만들다가 스택 오버 플로우가 발생 하였다. 순환 참조를 미쳐 신경쓰지 못하고 있었음.. 순환 참조를 잘 예방해야겠다고 다시 한 번 생각함 Service를 테스트 할 때 까지만 해도 발생하지 않았던 문제인데 REST API를 구현하면서 문제가 발생한 이유는 ResponseBody를 구현할 시 Object 형태의 값을 직렬화를 이용해 JSON 형태로 변환하는데 이 때 순환 참조가 발생하기 때문이다. public class O..

프로그래밍/JPA 2024.03.01

[MyBatis] 우연히 알게된 마이바티스의 캐시 Cache

MyBatis를 사용하여 만든 프로젝트를 Jdbc Template으로 변경하고 있는 와중에 잘 성공하던 테스트 하나가 실패했다. 대충 시나리오를 설명하자면 MemberService.findById 는 1. MemberRepository.findById 를 호출하여 Member를 찾고 2. ReserveRepository.findByMemberId 를 호출 하여 List를 찾고 3. Member의 List를 채워서 반환해준다. 그런데 테스트에서 MemberService.findById 를 호출 후, 다른 함수에서 MemberRepository.findById 를 호출하고 Member.getReserve로 List를 조회하고 있었다. 당연히 MemberRepository.findById는 Member에 Li..