Category: Network

0

[Java] - 가비지 컬렉션 히스토리

목차 [JAVA] - 가비지 컬렉션 튜닝 [JAVA] - Garbage Collection(가비지 컬렉션) [JAVA] - JVM (자바 가상 머신) 초기 GC들 (JDK 1.0~1.4)Serial GC 가장 오래된 GC 단일 스레드로 동작 작은 애플리케이션이나 클라이언트 환경에 적합 Stop-the-World 시간이 길어서 현재는 제한적으로 사용 Parallel GC (Throughput Collector) JDK 1.4에서 도입 멀티코어 환경에서 여러 스레드를 사용해 처리량을 개선 JDK 6~8에서 기본 GC 여전히 긴 정지 시간이 단점 저지연 목표 GC들 (JDK 1.4~)Concurrent Mark Sweep (CMS) GC

0

[Javascript] Axios 파일 업로드 및 다운로드

파일 업로드 및 다운로드📁 파일 업로드// 단일 파일 업로드async function uploadFile(file, onProgress) { const formData = new FormData(); formData.append('file', file); formData.append('category', 'documents'); formData.append('description', [file.name](http://file.name)); try { const response = await [axios.post](http://axios.post)('/api/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' }, onUploadProgress: (progressEvent) => { const percentCompleted = Math.round( (progressEvent.loaded * 100) / [progressEvent.total](http://progressEvent.total) ); console.log(`업로드 진행률: ${percentCompleted}%`); onProgress?.(percentCompleted); } }); return [response.data](http://response.data); } catch (error) { console.error('파일 업로드 실패:', error); throw error; }}// 다중 파일 업로드async function uploadMultipleFiles(files) { const formData = new FormData(); files.forEach((file, index) => { formData.append(`files`, file); }); const response = await [axios.post](http://axios.post)('/api/upload/multiple', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); return [response.data](http://response.data);}// 사용 예시const fileInput = document.getElementById('fileInput');fileInput.addEventListener('change', async (event) => { const file = [event.target](http://event.target).files[0]; if (file) { try { const result = await uploadFile(file, (progress) => { console.log(`업로드 진행률: ${progress}%`); }); console.log('업로드 완료:', result); } catch (error) { console.error('업로드 에러:', error); } }}); 📥 파일 다운로드// 파일 다운로드async function downloadFile(fileId, filename) { try { const response = await axios.get(`/api/files/${fileId}/download`, { responseType: 'blob' }); // Blob을 사용하여 파일 다운로드 트리거 const url = window.URL.createObjectURL(new Blob([[response.data](http://response.data)])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', filename); document.body.appendChild(link); [link.click](http://link.click)(); document.body.removeChild(link); // 메모리 정리 window.URL.revokeObjectURL(url); } catch (error) { console.error('파일 다운로드 실패:', error); }} 에러 처리 베스트 프랙티스🛡️ 포괄적인 에러 처리// 에러 타입별 처리 함수function handleApiError(error) { if (error.response) { // 서버가 응답했지만 상태 코드가 2xx 범위를 벗어남 const { status, data } = error.response; switch (status) { case 400: console.error('잘못된 요청:', data.message); break; case 401: console.error('인증 실패 - 로그인이 필요합니다'); // 로그인 페이지로 리다이렉트 window.location.href = '/login'; break; case 403: console.error('접근 권한이 없습니다'); break; case 404: console.error('요청한 리소스를 찾을 수 없습니다'); break; case 429: console.error('요청 한도를 초과했습니다. 잠시 후 다시 시도해주세요'); break; case 500: console.error('서버 내부 오류가 발생했습니다'); break; default: console.error(`서버 오류 (${status}):`, data.message); } return { type: 'response', status, message: data.message }; } else if (error.request) { // 요청은 전송되었지만 응답을 받지 못함 (네트워크 오류) console.error('네트워크 오류: 서버에 연결할 수 없습니다'); return { type: 'network', message: '네트워크 연결을 확인해주세요' }; } else { // 요청 설정 중에 오류 발생 console.error('요청 설정 오류:', error.message); return { type: 'config', message: error.message }; }}// 재시도 로직이 포함된 API 호출async function apiCallWithRetry(requestFn, maxRetries = 3, delay = 1000) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await requestFn(); } catch (error) { const errorInfo = handleApiError(error); if (attempt === maxRetries || errorInfo.type === 'response') { throw error; // 최대 재시도 횟수 도달 또는 서버 응답 오류 } console.log(`재시도 ${attempt}/${maxRetries} - ${delay}ms 후 다시 시도...`); await new Promise(resolve => setTimeout(resolve, delay * attempt)); } }}// 사용 예시async function fetchUserData(userId) { return apiCallWithRetry( () => axios.get(`/api/users/${userId}`), 3, // 최대 3번 재시도 1000 // 1초 간격 );}

0

[Javascript] Axios 인터셉터

인터셉터로 요청/응답 제어하기📤 요청 인터셉터// 모든 요청에 공통 로직 적용axios.interceptors.request.use( (config) => { // 요청 시작 로그 console.log(`🚀 API 요청: ${config.method?.toUpperCase()} ${config.url}`); // 인증 토큰 자동 추가 const token = localStorage.getItem('accessToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } // 요청 시간 기록 (성능 측정용) config.metadata = { startTime: new Date() }; return config; }, (error) => { console.error('❌ 요청 설정 오류:', error); return Promise.reject(error); }); 📥 응답 인터셉터// 모든 응답에 공통 로직 적용axios.interceptors.response.use( (response) => { // 응답 시간 계산 const endTime = new Date(); const duration = endTime - response.config.metadata.startTime; console.log(`✅ API 응답: ${response.config.url} (${duration}ms)`); return response; }, async (error) => { const originalRequest = error.config; // 401 에러: 토큰 갱신 처리 if (error.response?.status === 401 && !originalRequest._retry) { originalRequest._retry = true; try { const refreshToken = localStorage.getItem('refreshToken'); const response = await [axios.post](http://axios.post)('/auth/refresh', { refreshToken }); const newToken = [response.data](http://response.data).accessToken; localStorage.setItem('accessToken', newToken); // 원래 요청에 새 토큰 적용 후 재시도 originalRequest.headers.Authorization = `Bearer ${newToken}`; return axios(originalRequest); } catch (refreshError) { // 토큰 갱신 실패 시 로그인 페이지로 리다이렉트 localStorage.clear(); window.location.href = '/login'; } } // 에러 로깅 console.error('❌ API 에러:', { url: error.config?.url, status: error.response?.status, message: error.message }); return Promise.reject(error); }); 실전 예제: API 클래스 구현🏢 사용자 관리 API 클래스class UserService { constructor() { this.client = axios.create({ baseURL: process.env.REACT_APP_API_URL || 'https://api.example.com', timeout: 10000 }); this.setupInterceptors(); } setupInterceptors() { // 요청 인터셉터: 인증 토큰 자동 추가 this.client.interceptors.request.use(config => { const token = this.getAuthToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // 응답 인터셉터: 에러 처리 this.client.interceptors.response.use( response => response, error => this.handleError(error) ); } getAuthToken() { return localStorage.getItem('authToken'); } handleError(error) { const message = error.response?.data?.message || error.message; throw new Error(`API 요청 실패: ${message}`); } // 사용자 목록 조회 async getUsers(options = {}) { const { page = 1, limit = 10, search = '' } = options; const response = await this.client.get('/users', { params: { page, limit, search } }); return { users: [response.data.data](http://response.data.data), totalCount: [response.data.total](http://response.data.total), currentPage: page }; } // 사용자 상세 조회 async getUserById(userId) { const response = await this.client.get(`/users/${userId}`); return [response.data](http://response.data); } // 사용자 생성 async createUser(userData) { const response = await [this.client.post](http://this.client.post)('/users', userData); return [response.data](http://response.data); } // 사용자 정보 수정 async updateUser(userId, userData) { const response = await this.client.put(`/users/${userId}`, userData); return [response.data](http://response.data); } // 사용자 삭제 async deleteUser(userId) { await this.client.delete(`/users/${userId}`); return { success: true, userId }; } // 사용자 검색 async searchUsers(query) { const response = await this.client.get('/users/search', { params: { q: query } }); return [response.data](http://response.data); }}// 싱글톤 패턴으로 사용export const userService = new UserService();// 사용 예시async function handleUserOperations() { try { // 사용자 목록 조회 const userList = await userService.getUsers({ page: 1, limit: 20, search: 'john' }); console.log('사용자 목록:', userList); // 새 사용자 생성 const newUser = await userService.createUser({ name: '김개발', email: '[kim.dev@example.com](mailto:kim.dev@example.com)', role: 'developer' }); console.log('생성된 사용자:', newUser); // 사용자 정보 수정 const updatedUser = await userService.updateUser([newUser.id](http://newUser.id), { name: '김시니어', role: 'senior-developer' }); console.log('수정된 사용자:', updatedUser); } catch (error) { console.error('사용자 작업 중 오류:', error.message); }}

0

[Javascript] Axios 사용하기 (고급편)

고급 설정 및 인스턴스⚙️ 상세한 요청 설정const requestConfig = { method: 'get', url: '/api/users', baseURL: 'https://api.example.com', // 헤더 설정 headers: { 'Authorization': 'Bearer token123', 'Content-Type': 'application/json', 'Accept': 'application/json' }, // URL 파라미터 params: { page: 1, size: 20 }, // 타임아웃 (밀리초) timeout: 10000, // 응답 타입 responseType: 'json', // 'json', 'text', 'blob', 'stream' 등 // 요청 바디 (POST, PUT, PATCH) data: { name: '홍길동', email: '[hong@example.com](mailto:hong@example.com)' }};const response = await axios(requestConfig); 🏗️ Axios 인스턴스 생성// API별 인스턴스 생성const apiClient = axios.create({ baseURL: 'https://api.myservice.com/v1', timeout: 15000, headers: { 'Content-Type': 'application/json' }});// 인증이 필요한 API용 인스턴스const authApiClient = axios.create({ baseURL: 'https://api.myservice.com/v1', timeout: 10000, headers: { 'Authorization': `Bearer ${getAuthToken()}` }});// 인스턴스 사용const users = await apiClient.get('/users');const profile = await authApiClient.get('/profile'); 인터셉터로 요청/응답 제어하기웹 개발을 하다 보면 서버와 통신할 때 반복적으로 처리해야 하는 공통 로직들이 생깁니다.예를 들어 JWT 토큰을 모든 요청 헤더에 붙인다거나, 에러 응답을 일관되게 처리한다거나, 응답 데이터 구조를 통일한다거나 하는 일들이죠. 이때 유용하게 사용할 수 있는 기능이 바로 Axios Interceptor입니다. 📤 요청 인터셉터

0

[Javascript] Axios 사용하기

웹 개발에서 API 통신은 필수불가결한 요소입니다. 그 중에서도 Axios는 가장 인기 있고 강력한 JavaScript HTTP 클라이언트 라이브러리로 자리잡고 있습니다. 이 글에서는 Axios의 기본 사용법부터 고급 기능까지 실무에서 바로 활용할 수 있는 예제와 함께 상세히 알아보겠습니다. Axios란 무엇인가?Axios는 Promise 기반의 HTTP 클라이언트 라이브러리로, 브라우저와 Node.js 환경에서 모두 사용할 수 있습니다. ✨ 주요 특징 Promise 기반: async/await와 완벽 호환 요청/응답 인터셉터: 공통 로직 처리 가능 자동 JSON 변환: 별도 변환 과정 불필요 요청/응답 변환: 데이터를 원하는 형태로 가공 요청 취소: 불필요한 요청 중단 가능 광범위한 브라우저 지원: IE11까지 지원 설치 및 기본 설정📦 설치# npm 사용시npm install axios# yarn 사용시 yarn add axios# pnpm 사용시pnpm add axios

0

네트워크 트래픽의 3가지 패턴 - Ingress, Egress, East-West Traffic

현대 IT 인프라를 이해하려면 데이터가 어떻게 흐르는지 파악하는 것이 필수입니다. 특히 클라우드 환경과 마이크로서비스 아키텍처가 보편화되고 트래픽의 움직임이 클라우드 서비스의 과금 요소중에 하나가 됨으로써 네트워크 트래픽 패턴을 정확히 이해하는 것은 더욱 중요해졌습니다. 오늘은 인프라를 운영하면서 알아두면 좋을 3가지 트래픽 패턴에 대해 알아보겠습니다. 📌 1. Ingress: 외부에서 내부로 들어오는 트래픽 Ingress는 클러스터 외부 → 내부로 들어오는 요청입니다. Ingress Traffic은 외부에서 우리 네트워크나 시스템으로 들어오는 모든 트래픽을 의미합니다. 대표적인 예시는 인터넷 사용자가 웹 애플리케이션에 접속하는 경우입니다. 실무 예시🌐 사용자 브라우저 → 웹 서버 (HTTP/HTTPS 요청)📱 모바일 앱 → API 게이트웨이 (REST API 호출)🔗 외부 시스템 → 내부 서비스 (Webhook, 데이터 동기화) 📌 2. Egress: 내부에서 외부로 나가는 트래픽 Egress는 클러스터 내부 → 외부로 나가는 요청 Egress Traffic은 우리 시스템에서 외부로 나가는 모든 트래픽입니다. 예를 들어 응답 데이터, 외부 API 호출, 백업 데이터 전송등을 할때 발생합니다.

0

Service Discovery 패턴

참고 https://www.nginx.com/blog/service-discovery-in-a-microservices-architecture/ https://velog.io/@hoonki/마이크로서비스-패턴-서비스-디스커버리 🕵️‍♂️ Service Discovery 패턴이 등장하게 된 배경기존 서비스 인스턴스의 개수와 IP 가 고정적이였던 온 프레미스 환경과 달리 MSA 환경에서는 Application 들이 AutoScaling 을 하면서 동적으로 줄었다가 늘어나면서 IP 자체도 고정이 아닌 동적으로 바뀌게 됐습니다. Client 나 Gateway 입장에서 서비스 인스턴스들이 동적으로 늘었는지 줄었는지에 대한 파악을 하기가 어려운 문제가 있었고 그에 따른 LoadBalancing 하는데 어려움이 있었습니다. 변경 및 추가된 서비스들의 위치와 주소를 쉽게 파악하기 위해 Service Discovery 가 등장하게 됐습니다. 출처: https://www.nginx.com/blog/service-discovery-in-a-microservices-architecture/ ✅ 서비스 등록 - Service RegistryService Discovery 패턴에서는 Service EndPoint 를 조회 및 관리하기 위한 저장소가 필요한데, 이를 Service Registry 라 합니다. MSA 에서 각 서비스들이 실행하게 되면 Service Registry 에 자신의 EndPoint 들을 등록합니다. 그리고 주기적으로 Service Registry 에 등록된 서비스 중이 정상적인지 Health Check 를 진행하고, 정상적인 응답이 안올 경우 목록에서 삭제하는 방식으로 진행합니다.

0

네트워크 - STOMP

STOMP (Simple Text Oriented Messaging Protocol)WebSocket 프로토콜은 두 가지 유형의 메세지를 정의하고 있지만 그 메세지의 내용까지는 정의하고 있지 않는다. STOMP (Simple Text Oriented Messaging Protocol) 은 메세징 전송을 효율적으로 하기 위해 탄생한 프로토콜 기본적으로 pub/sub 구조로 되어있어 메세지를 전송하고 메세지를 받아 처리하는 부분이 확실히 정해져 있기 때문에 개발자 입장에서 명확하게 인지하고 개발할 수 있는 이점이 있다. 한 줄로 정의하자면, STOMP 프로토콜은 WebSocket 위에서 동작하는 프로토콜로써 클라이언트와 서버가 전송할 메세지의 유형, 형식, 내용들을 정의하는 매커니즘 이다. 또한 STOMP를 이용하면 메세지의 헤더에 값을 줄 수 있어 헤더 값을 기반으로 통신 시 인증 처리를 구현하는 것도 가능하며 STOMP 스펙에 정의한 규칙만 잘 지키면 여러 언어 및 플랫폼 간 메세지를 상호 운영할 수 있다.

0

네트워크 - Web Socket

웹 소켓 Web Socket 웹 소켓이란 두 프로그램 간의 메시지를 교환하기 위한 통신 방법 중 하나, 현재 HTML5 에서 많이 사용하는 방식이다. WebSocket 프로토콜은 Text, Binary 두 가지 유형의 메세지를 정의하고 있지만 그 메세지의 내용까지는 정의하고 있지 않는다. 특징 양방향 통신 (Full-Duplex) 데이터 송수신을 동시에 처리할 수 있는 통신 방법 클라이언트와 서버가 서로에게 원할 때 데이터를 주고 받을 수 있다. Http 통신은 Client 가 요청을 보내고 Server 가 요청에 대해 응답을 보내주는 단방향 통신 실시간 네트워킹 웹 환경에서 연속된 데이터를 빠르게 노출할 수 있다. Web Socket 이전 기술 위 기술들은 HTTP 위에서 동작하므로 Request, Response 둘다 Header 가 불필요하게 크다. Polling 서버로 일정 주기로 요청을 송신하는 방식이다. Real-time 통신에서는 언제 통신이 발생할지 예측이 불가능 하므로 주기적으로 Request 와 Connection을 생성한다. 불필요한 Request 와 Connection 을 위한 자원 Loss 가 발생 Long Polling 서버에서 요청을 보내고 이벤트가 생겨 응답 받을 때 까지 연결을 종료하지 않는다. 응답을 받으면 귾고 다시 재요청을 한다. 많은 양의 메시지가 쏟아질 경우 Polling 과 같다. Streaming 서버에 요청을 보내고 끊기지 않는 연결 상태에서 끊임 없이 데이터를 수신한다. 클라이언트에서 서버로의 데이터 송신이 어렵다.

0

SQL injection

SQL injection 이란 보안상의 허점을 이용해 사용자가 정의한 SQL 문외 조작된 SQL 을 주입하고 실행시켜 데이터베이스에 저장된 중요한 정보를 가져오는 공격 기법을 의미한다. Error Based SQL injection 논리적 에러를 이용한 SQL injection 잘못된 SQL 을 이용해 고의로 에러를 발생시는 공격 기법이다. 예외로 던저진 Message 를 통해 테이블 명과 컬럼과 같은 테이블 정보 를 얻어낼 수 있다. SQL 구문 정보를 변경해 사용자 인증을 우회해 접속할 수 있다. Union Based SQL injection Union 명령을 이용한 SQL injection 정상적으로 실행하는 쿼리와 정보를 탈취하기 위한 쿼리문을 Union 연산자를 통해 실행시킨다. 데이터 형식과 컬럼 수가 일치하면 Union 연산자를 이용해 데이터를 가져올 수 있다. SELECT uid FROM user_table WHERE uid='' UNION SELECT upw FROM user_table WHERE uid='admin' -- and...

0

네트워크 - CSRF (Corss Site Request For Forgery)

CSRF (Corss Site Request Forgery) CSRF 란 사이트 간 요청 위조의 의미로, 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 해 특정 웹페이지를 보안에 취약하게 하거나 수정, 삭제 들의 작업을 하게 만드는 공격 방법공격자가 특정 사용자의 권한을 탈취해 특정 행위 (수정, 삭제, 등록 등) 를 사이트에 요청하게 만드는 공격 CSRF 를 위한 조건 권한이 있는 사용자가 사이트(서비스) 에 접속해야 한다. 사용자가 공격자가 만든 피싱 사이트에 접속하게 되면 CSRF 공격이 성립된다. 2008년에 발생했던 옥션의 개인정보 유출 사건에서도 관리자 계정을 탈취하는데 이 CSRF 방법을 이용 옥션 관리자가 메일을 조회하면서 CSRF 공격할 수 있는 테그가 들어간 이메일을 열어 해커가 관리자 권한을 취득하게 됨 <img src="http://auction.com/changeUserAcoount?id=admin&password=admin" width="0" height="0"> 방어 방법1. Referrer 검증

0

네트워크 - CORS (Corss Site Resource Sharing)

SOP (Same Origin Policy)다른 출처의 리소스를 사용 못하도록 제한하는 보안 방식 CORS (Cross Origin Resource Sharing) 하나의 Origin 에서 실행 중인 웹 애플리케이션이 다른 Origin 내 리소스를 사용하는 것을 의미한다. 추가 HTTP 헤더를 이용해 한 출처에서 실행중인 웹 어플리케이션이 다른 출처의 선택된 자원에 접근할 수 있는 권한을 부여하도록 브라우저에게 알려주는 체제 Request 내 Origin 헤더와 Response 내 Access-Control-Allow-Origin 헤더가 같으면 브라우저는 같은 출처로 인식한다. 해결 방법서버에서 Access-Control-Allow-Origin 헤더를 포함한 응답을 브라우저에 보내는 방식으로 CORS 에러를 해결할 수 있습니다. 프론트엔드 개발자가 CORS 에러를 확인했다면, 서버에 Access-Control-Allow-Origin 등 CORS를 해결하기 위한 몇 가지 응답 헤더를 포함해 달라고 요청해야 합니다. 출처 URL의 Protocol, Host, Port 를 합친 것을 의미한다.

0

네트워크 - XSS (Cross-Site Scripting)

![]/images/computer-science/network/http/xss.png) XSS (Cross-Site Scripting) 공격자가 보안이 취약한 웹 사이트에 악성 스크립트를 삽입하는 공격 기법 XSS 를 통해 C&C (좀비 PC에 명령을 내리거나 악성 코드를 제어하는 서버) 로 리다이렉하거나 사용자의 쿠키를 탈취해 Session 하이재킹 공격을 할 수 있다. Persistent XSS 공격자가 심어놓은 특정 스크립트가 서버에 저장돼 지속적으로 서비스를 제공하는 정상 페이지에서 공격자에게 스크립트가 노출되는 기법 Relected XSS 웹 어플리케이션의 파라미터를 사용할 때 발생하는 취약점을 이용한 공격 기법 쿼리 파라미터로 특정 스크립트를 보냈을 때 서버가 필터링을 거치지 않고 파라미터로 포함된 스크립트를 응답 페이지에 담아 전송할 때 문제가 발생

0

네트워크 - HTTP 메시지 구조

네트워크 - OSI 7 계층과 TCP/IP 5계층 네트워크 - HTTP 네트워크 - HTTP Version 네트워크 - HTTP 메시지 구조 네트워크 - HTTPS Post not found: computer-science/network/tcp HTTP 메시지 구조 HyperText Transfer Protocol 의 약자로 HTML 문서를 전송하기 위해 만들어진 규약조건이다.HTTP는 TCP/IP 기반으로 되어있다. HTTP 통신 방식HTTP는 기본적으로 요청/응답 구조 Client 요청 MessageJson 데이터 curl –http1.1 http://localhost:8888/greeting -v -H “Content-Type: application/json” -d ‘{“hello”:”json”}’ POST /greeting HTTP/1.1Host: localhost:8888Accept: */*Content-Length: 16Content-Type: application/jsonUser-Agent: curl/7.71.1{"hello":"json"}

0

네트워크 - HTTP Version

HTTP Version 네트워크 - OSI 7 계층과 TCP/IP 5계층 네트워크 - HTTP 네트워크 - HTTP Version 네트워크 - HTTP 메시지 구조 네트워크 - HTTPS Post not found: computer-science/network/tcp HTTP/0.9 간단하게 HTML 객체 를 받아오기 위해 만들어진 프로토콜이다. 때문에 GET메서드 만을 지원한다. 멀티미디어 콘텐츠에 대한 MIME 타입이나, HTTP 해더, 버전 번호는 지원하지 않는다. HTTP/1.0 버전 번호, HTTP 헤더, 추가 메서드, 멀티미디어 객체 처리를 추가했다. 웹페이지와 상호작용하는 폼을 실현 하나의 커넥션에 하나의 요청과 하나의 응답만 가능 요청GET /greeting HTTP/1.0Host: localhost:18888Connection: closeAccept: */*User-Agent: curl/7.71.1 응답