Archive: 2025

0

[Spring Boot] - Github Package 에 Spring 프로젝트를 배포하기

참고 GitHub Packages - Gradle 레지스트리 작업 🧑‍💻 무료로 Artifact 저장소를 사용하고 싶다!회사가 아닌 개인 프로젝트를 할때, 라이브러리를 개발해서 다른 프로젝트에서 사용하고 싶은 경우, 라이브러리 저장을 위한 Nexus 저장소를 별도로 구축하기가 쉽지 않습니다. 지속적이고 무료로 패키지 저장이 가능한 서비스로 JitPack 과 Github 패키지 저장소를 찾아봤습니다. 처음에 알아본 JitPack 은 패키지를 무료로 올릴 수 있는 서비스지만, Private 저장소 대상으로는 유료입니다. 만약 내가 Private 저장소를 이용해 패키지를 만든다고 하면 적합한 대상이 아닙니다. 추가적으로 알아본게 Github 인데, Github 가 코드 저장 뿐만 아니라 Docker 이미지나 Artifact 들을 올릴 수 있는 기능 또한 제공을 하고 있었습니다. 코드와 함께 이번에는 Github 를 패키지 저장소로 사용해보려고 합니다. 🌱 Spring Boot 프로젝트를 Github 에 배포하기✅ Gradle 플러그인 추가 설정 추가build.gradle 에 maven-publish 플러그인을 추가합니다

0

[Spring Boot] - Spring Interceptor 에서 Response 조작이 가능한가?

참고 Spring interceptor에서 Response 수정하기 “HttpServletResponse is committed” mean? 📝 후처리에서 메뉴 데이터를 Response 객체에 데이터를 넣어주세요개발 요구사항 중 페이지 접근시 전처리에서 접근 권한을 확인하고 후처리로 Response 객체에 사용자가 접근할 수 있는 메뉴를 같이 내려달라는 요구를 받았습니다. 해당 요구사항을 Spring 에서 제공하는 Interceptor 로 가능한지 검토해 달라는 요청을 받았습니다. 🤔 Interceptor 에서 데이터 변경이 가능할까?스프링에서 제공하는 Interceptor 는 아래 코드와 같습니다. 요청을 처리하는 Controller 전에 preHandler 를 거치기 때문에 사용자 접근을 제어해달라는 요구사항은 어렵지 않았습니다. 마찬가지로 요청이 끝난 후에는 postHandler 를 거쳐 나가는데 그때 응답 객체를 수정할 수 있지 않을까? 마침, HttpServletRequest 객체를 매게변수로 받아서 조작이 가능할 것 같은 그런 기분이 들지만, 결론은 안됩니다. (두둥탁 🥁) HandlerInterceptorpublic interface HandlerInterceptor { default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { }} 🧐 그럼 왜 인터셉터 에서 응답 객체 조작이 불가능한 것인가?

0

[Docker] 이미지 history

목차 [Docker] 이미지 history [Docker] 이미지 레이어 [Docker] 이미지 Build 참고 Docker History 명령어 공식문서 ✅ 이미지 historyDocker 이미지를 받아서 사용하다보면 은근, 해당 이미지가 어떻게 생성 됐는지, 어떤 명령어를 사용했는지 확인해봐야 할때가 있습니다. Docker 에서는 history 명령어를 이용해 해당 이미지가 어떤 명령어를 이용해 이미지가 생성 됐는지 확인할 수 있는 기능을 제공합니다. 저 같은 경우는 제대로 작동되지 않는 빌드된 이미지에 대한 디버깅용으로 사용을 많이 했었습니다. ✅ docker history 명령어기본 명령어

0

[Docker] 이미지 레이어

목차 [Docker] 이미지 레이어 [Docker] 이미지 Build 참고 Docker 공식 문서 - 이미지 레이어 이해하기 Docker 공식 문서 - Storage drivers 🔍 이미지 레이어란?Docker 이미지의 핵심적인 특징 중 하나는 레이어 기반 구조 입니다. Docker 이미지는 빌드시 한번에 만들어 지는 것이 아닌 기존 이미지에 레이어를 하나씩 쌓는 방식으로 이미지를 만듭니다. 이미지 레이어는 Dockerfile 에 있는 명령어를 실행할때 각 명령어별로 생성됩니다.. 각 레이어들은 읽기 전용 (read-only) 속성을 가지며, 순서대로 쌓여서 하나의 완전한 이미지를 구성합니다. 최종적으로 생성되는 이미지는 여러개의 레이어들이 쌓여서 만들어진 결과물이라 생각하면 됩니다. ✅ 레이어의 특징

0

[Docker] 이미지 Build

🔍 Docker Build 란?Docker Build 는 서비스를 격리된 환경에서 실행할 수 있도록 운영체제 및 필요한 의존성과 설정, 실행 파일등을 하나의 이미지로 패키징하는 것을 의미합니다. 이미지 Build 는 Dockerfile 을 기반으로 수행되며, Dockerfile 에는 이미지 생성에 필요한 명령어들이 있으며, 순서대로 실행됩니다. ✅ Build 명령어# 현재 디렉토리 위치에 Dockerfile 가 있고 현재 위치에서 이미지를 생성할 경우docker build -t <만들 이미지 이름>:<만들 이미지 태그> .# Dockerfile 이 다른 경로에 있을 경우docker build -t <만들 이미지 이름>:<만들 이미지 태그> -f <파일 경로> <빌드 컨텍스트 경로># Dockerfile 명이 다를 경우우docker build -t <만들 이미지 이름>:<만들 이미지 태그> -f <파일 경로/파일 이름> <빌드 컨텍스트 경로> ✅ 이미지지 레이어Docker 는 Build 시 Dockerfile 의 베이스가 되는 이미지부터 시작해 각 명령어를 실행할 때마다 새로운 이미지를 생성합니다. 이것을 이미지 레이어를 생성한다고 이야기 합니다. 때문에 초기 명령어들이 같고 중간 단계 부터 달라지는 Dockerfile 의 경우 빌드시 각각 이미지 레이어를 생성하는게 아닌 기존에 만들어진 이미지 레이어를 바탕으로 새로운 이미지를 생성해 빌드시간과 저장공간을 절약할 수 있습니다. ✅ Dockerfile

0

[Docker] Volume - 컨테이너 데이터 관리

목차 [Docker] Volume - 컨테이너 데이터 관리 [Docker] Network - 컨테이너간 통신 [Docker] 🤔 Docker Volume 이 왜 필요한가? 컨테이너내 데이터는 휘발성입니다. Docker 와 컨테이너 기술이 막 떠오를때 PC 에 깔아서 개발을 하고 있는데 Docker 내에서 설정한 값들이 재실행할때 마다 초기화 되는 현상들을 겪었습니다. 당시 너무 화가나서 여러 책들을 읽어봤는데 생각해보니 컨테이너의 특성을 제대로 이해하지 못해 생기는 문제였었습니다. 컨테이너는 기본적으로 휘발성 이기 때문에 컨테이너가 종료되거나 삭제되면 내부 데이터도 함께 사라집니다. 쉽게 생각해서 격리돼 있는 컨테이너의 특성상 컨테이너가 생성한 모든 파일들은 결국 컨테이너내에서만 존재하고 컨테이너 삭제시에는 컨테이너와 함께 데이터도 삭제가 되는 것입니다. Docker 에서는 Docker Volume 을 통해 컨테이너 내에서의 데이터 휘발성 문제를 해결하고 영구적으로 저장할 수 있는 방법을 제공합니다. ✅ Docker Volume 이란?Docker Volume 은 컨테이너 외부 에 데이터를 저장할 수 있는 공간입니다. 컨테이너와는 별도로 존재하기 때문에, 컨테이너를 삭제하더라도 데이터는 유지되며 데이터 영속성이 보장됩니다.

0

[Docker] Network - 컨테이너간 통신

목차 [Docker] Volume - 컨테이너 데이터 관리 [Docker] Network - 컨테이너간 통신 [Docker] 📌 Docker Network 란?Docker Network는 컨테이너 간 통신을 가능하게 해주는 가상 네트워크입니다. 컨테이너는 독립적인 환경에서 실행되지만, 애플리케이션을 만들다 보면 서로 데이터를 주고받아야 하거나 외부 요청을 받아야 할 일이 많습니다. Docker 네트워크는 이러한 컨테이너간 통신을 가능하게 해주는 역할을 합니다. 🔍 Docker Network 의 종류Docker는 기본적으로 다음과 같은 네트워크 드라이버들을 제공합니다 드라이버 설명 bridge 기본 드라이버. 컨테이너 간 통신이 가능하며, 같은 호스트에서 작동합니다. host 컨테이너가 호스트의 네트워크를 그대로 사용합니다. 격리는 없지만 속도는 빠릅니다. none 네트워크를 사용하지 않도록 설정합니다. 완전한 격리가 필요할 때 사용합니다. overlay 여러 호스트 간 컨테이너를 연결할 수 있습니다. Docker Swarm에서 유용합니다. macvlan 컨테이너에 고유한 MAC 주소를 부여해 물리 네트워크처럼 동작시킵니다. ✅ Docker 네트워크 생성

0

[데이터 베이스] 자바에서 대용량 조회 시 애플리케이션과 데이터베이스는 어떻게 동작하는가?

목차 [데이터 베이스] 자바에서 대용량 조회 시 애플리케이션과 데이터베이스는 어떻게 동작하는가? [데이터 베이스] Cursor 란? 🤔 대용량 조회 시 애플리케이션과 데이터베이스는 어떻게 동작하는가?대용량 데이터를 조회해야 하는 상황이 생기면, 우리는 종종 “애플리케이션 메모리는 괜찮을까?”, “DB에 부하가 가지는 않을까?” 같은 고민을 하게 됩니다. 자바 JDBC 에서는 이런 상황을 제어하기 위해 cursor 와 fetch size 를 이용합니다. 🕵️‍♂️ 대용량 조회의 기본 흐름JDBC로 쿼리를 실행할 때, 결과가 수천~수만 건이라면 어떻게 처리될까요? 예를 들어, 아래 코드를 실행했다고 가정해 봅시다. PreparedStatement ps = conn.prepareStatement("SELECT * FROM large_table");ps.setFetchSize(100); // 한 번에 100건씩 가져오도록 설정ResultSet rs = ps.executeQuery(); 이 코드가 실행될 때 내부적으로 일어나는 동작은 아래와 같습니다 애플리케이션이 DB에 쿼리를 날립니다. DB는 전체 결과를 준비하고 커서를 생성합니다. JDBC 드라이버는 커서로부터 100 건씩 row 를 가져옴니다 row 를 다 소비하면 JDBC는 다음 100 건을 요청합니다. 이 과정을 반복하여 전체 데이터를 처리합니다.

0

[데이터 베이스] Cursor 란?

목차 [데이터 베이스] 자바에서 대용량 조회 시 애플리케이션과 데이터베이스는 어떻게 동작하는가? [데이터 베이스] Cursor 란? 🔎 Cursor 란?커서는 쿼리 결과셋을 탐색할 수 있는 포인터 입니다. DB 는 쿼리 결과 데이터를 반환할 때, 커서(cursor) 를 생성하여 현재 어디까지 데이터가 반환됐는지, 어디부터 읽으면 될지를 알 수 있습니다. 주로 프로그램 내에서 루프를 돌며 한 줄씩 데이터를 처리할 필요가 있을 때 사용합니다. ✅ Cursor 사용법1. DECLARE - Cursor 선언 및 생성커서를 사용하고 싶은 쿼리가 있으면 아래 SQL 을 이용해 커서를 정의 및 생성해줍니다.

0

[쿠버네티스] 인증/인가 - Role 과 ClusterRole

목차 [쿠버네티스] 인증/인가 - OIDC 를 이용한 Keycloak 연동 [쿠버네티스] 인증/인가 - ServiceAccount [쿠버네티스] 인증/인가 - X.509 인증서를 사용한 사용자 추가 및 인증 [쿠버네티스] 인증/인가 - Role 과 ClusterRole 쿠버네티스에서 Role과 ClusterRole은 RBAC(역할 기반 접근 제어)를 통해 사용자나 서비스 계정에 권한을 부여하는 중요한 리소스입니다. 아래에 각각의 특징과 차이점을 정리해 보았습니다. Role네임스페이스 범위: Role은 특정 네임스페이스 내에서만 유효합니다. 따라서 한 네임스페이스의 자원에만 접근 권한을 부여할 수 있습니다. 정책 정의: Role 안에는 API 리소스(예: Pods, Services 등)에 대한 특정 동작(예: get, list, create 등)이 정의되어 있습니다. 바인딩: Role은 RoleBinding을 통해 사용자나 서비스 계정에 연결됩니다. 이때 RoleBinding 역시 특정 네임스페이스에 속합니다.

0

[쿠버네티스] 인증/인가 - OIDC 를 이용한 Keycloak 연동

목차 [쿠버네티스] 인증/인가 - OIDC 를 이용한 Keycloak 연동 [쿠버네티스] 인증/인가 - ServiceAccount [쿠버네티스] 인증/인가 - X.509 인증서를 사용한 사용자 추가 및 인증 [쿠버네티스] 인증/인가 - Role 과 ClusterRole 참고 https://wlsdn3004.tistory.com/62 앞서 말했듯이, 쿠버네티스는 사용자 정보를 저장하지 않습니다. 사용자를 관리하고 싶으면, 쿠버네티스에서 제공하는 OIDC 를 통해 별도의 인증 서버와 연계를 하면 사용자를 관리할 수 있습니다. 인증서버로 유명한 Keycloak 을 이용해 사용자를 관리하고 쿠버네티스에서 인증을 진행할 수 있도록 설정을 진행하려고 합니다. ✅ 1. Keycloak Client 추가쿠버네티스에서 Keycloak 을 이용해 인증을 진행하기 위해서는 Client 생성(등록) 이 필요합니다. Client 단위로 Keycloak 에서는 쿠버네티스 사용자들을 관리하고 권한을 매핑해줄 수 있습니다.

0

[쿠버네티스] 인증/인가 - X.509 인증서를 사용한 사용자 추가 및 인증

목차 [쿠버네티스] 인증/인가 - OIDC 를 이용한 Keycloak 연동 [쿠버네티스] 인증/인가 - ServiceAccount [쿠버네티스] 인증/인가 - X.509 인증서를 사용한 사용자 추가 및 인증 [쿠버네티스] 인증/인가 - Role 과 ClusterRole 쿠버네티스는 사용자를 “인증”하는 방식만 알면 되고, 사용자 정보를 자체를 저장하지 않습니다. X.509 인증서 를 사용하는 방식은 사용자 인증서를 만들고 클러스터에 등록해서 인증하는 방식입니다. ✅ 1. 사용자 인증서 및 키 생성1. 개인 키 (Private Key) 생성RSA 알고리즘으로 개인 키 생성 하게 되면 dev-user.key 파일이 생성됩니다. 개인 키는 인증서 서명 요청(CSR)을 만들 때 필요하며 이후 쿠버네티스 API 서버와 통신 시 이 키로 서명된 인증서를 사용해 본인을 증명

0

[Vue 3] - Tailwind 사용하기

1. Vue3 프로젝트 생성npm init vue@latest my-vue3-appcd my-vue3-appnpm install 2. Tailwind Css 설치Tailwind CSS와 관련된 패키지를 설치합니다. npm install -D tailwindcss postcss autoprefixer 그런 다음 Tailwind CSS 초기화를 진행합니다. npx tailwindcss init 이 명령어를 실행하면 프로젝트 루트 디렉토리에 tailwind.config.js 파일이 생성됩니다. 3. Tailwind CSS 구성

0

[Vue 3] - Pinia 사용하기

Pinia 란?Pinia 는 Vue 에서 사용하는 상태 관리를 위한 라이브러리입니다. Vue2 에서는 Vuex 를 사용하다가 Pinia 의 등장으로 점차 Pinia 가 대세를 이루게 됐습니다. Vue 에서는 ref, reactive 와 같은 상태 관리를 할 수 있는 방법들이 있는데 이런 함수들을 이용해 생성된 상태를 다른 페이지로 전달하기 위해서는 props 나 event 혹은 provide 나 inject 를 이용해 전달할 수 있지만, 파일이 많아질수록 추적하기가 복잡해집니다. Pinia 를 사용하는 이유는 상태를 관리하는 로직을 분리할 수 있고 중앙 집중식 으로 관리할 수 있다는 이점 때문에 그렇습니다. 1. Pinia 설치npm install pinia 2. Pinia 모듈 추가하기main.tsimport { createApp } from 'vue';import { createPinia } from 'pinia';import App from './App.vue';const app = createApp(App);const pinia = createPinia();app.use(pinia);app.mount('#app'); 3. Pinia Store 생성

0

[Vue 3] Vue Route - 네비게이션 가드

참고 Vue Router 공식 문서 🌐 네비게이션 가드Vue 3 를 이용해 개발하다보면, 사용자의 인증 여부에 따라 페이지 접근을 제한하거나, 페이지 전환 전/후에 특정 로직을 실행하고 싶을 때가 있습니다. SSR 웹사이트의 경우 서버가 요청을 받아서 처리를 하면 되지만, CSR 인 Vue 에서는 Client 에서 페이지 이동을 확인해야 합니다. 다행히 Vue Router 에서는 Router 를 탈때 특정 로직 수행을 위해 네비게이션 가드 를 제공합니다. 네비게이션 가드 는 라우터 전환 시점에 개입할 수 있게 해주는 훅 입니다. 🛡️ 전역 가드전역 가드는 애플리케이션 전체에 적용되며, 모든 라우트 변경 시 실행됩니다. beforeEach: 모든 라우팅 전에 실행 beforeResolve: 컴포넌트 렌더링 전 비동기 작업 afterEach: 라우팅 완료 후 작업