728x90
728x90

전체 글 350

[14] 대용량 파일 전송 시스템 개발 - 다중 파일 다운로드 (multipart/mixed) 전체 소스

파일 다운로드 (multipart/mixed) 전체 소스 멀티파트인 multipart/mixed 방식으로 파일이 다운로드되게 만든 코드입니다.테스트를 위해 서버에 있는 test.png, test.mov파일을 다운로드하게 개발되어 있습니다. 소스 경로transmission +src +main +java +com +example +transmission +controller DownloadServlet3.java +webapp ..

[13] 대용량 파일 전송 시스템 개발 - 다중 파일 다운로드 (multipart/mixed)

실무에서 multipart/mixed를 활용한 파일 다운로드를 접할 기회는 드물지만, 개발자로서의 개발 스펙트럼을 넓히고 깊이 있는 기술 구조를 이해하기 위해 그 개념과 구현 방법을 살펴보고 multipart/mixed 기반의 파일 다운로드 구현법을 알아보겠습니다. multipart/mixed는 서버에서 클라이언트로 응답 본문(Body)에 독립적인 여러 종류의 파일(텍스트, 바이너리(Binary))을 동시에 담아 전송할 때 사용하는 Content-Type입니다. multipart/mixed는 multipart/form-data와 비슷하지만 다른 점이 있습니다.구분multipart/form-datamultipart/mixed사용하는 곳웹 Form 전송이메일 클라이언트, 다중 전송 클라이언트, API(JSO..

[12] 대용량 파일 전송 시스템 개발 - 파일 다운로드 (HTTP Transfer-Encoding) 전체 소스

파일 다운로드 (HTTP Transfer-Encoding) 전체 소스 HTTP 전송 인코딩(Transfer-Encoding) 방식으로 파일이 다운로드되게 만든 코드입니다.테스트를 위해 서버에 있는 test.mov파일을 다운로드하게 개발되어 있습니다. 소스 경로transmission +src +main +java +com +example +transmission +controller DownloadServlet2.java +weba..

[11] 대용량 파일 전송 시스템 개발 - 파일 다운로드 (HTTP Transfer-Encoding)

HTTP Transfer-Encoding은 서버에서 웹 브라우저에 실시간으로 데이터를 보내거나 대용령의 파일을 보낼때 사용되는 기술입니다. HTTP 전송 인코딩(Transfer-Encoding) HTTP 전송 인코딩 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Transfer-Encoding) HTTP Transfer-Encoding은 네트워크상의 노드(서버와 클라이언트) 간 메시지 전송에 사용되는 인코딩 형식을 지정합니다.Transfer-Encoding은 노드 간 메시지에 적용되는 홉간(Hop-by-hop, 노드 사이의 개별 구간(Hop)에서만 적용) 응답 헤더입니다. 대부분의 인코딩은 chunked입니다.Transfer-E..

[10] 대용량 파일 전송 시스템 개발 - 파일 다운로드 (HTTP 범위 요청) 전체 소스

파일 다운로드 (HTTP 범위 요청) 전체 소스 HTTP 범위 요청(HTTP range requests) 방식으로 파일이 다운로드되게 만든 코드입니다.테스트를 위해 서버에 있는 test.mov파일을 다운로드하게 개발되어 있습니다. 소스 경로 소스 경로 transmission +src +main +java +com +example +transmission +controller DownloadServlet.java +resources..

[9] 대용량 파일 전송 시스템 개발 - 파일 다운로드 (HTTP 범위 요청)

웹 브라우저가 서버에 있는 파일을 다운로드 받을 때 파일을 한번에 다운로드하는게 아니라 여러 번에 나누어서 다운로드 합니다. 이때 사용되는 기술이 HTTP 범위 요청(HTTP range requests)입니다. HTTP 범위 요청(HTTP range requests)은 클라이언트가 서버에 리소스의 일부(특정 범위)를 보내달라고 요청하는 겁니다. 이 기술은 미디어 플레이어, 대용량 파일 다운로드에서 사용되고 있습니다. HTTP 범위 요청(HTTP range requests) HTTP 범위 요청 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) HTTP 범위 요청(HTTP range requests)을 사용하기 위해서 서버가 HTTP 범..

[8] 대용량 파일 전송 시스템 개발 - 파일 업로드 전체 소스

파일 업로드 전체 소스 DB 테이블 생성임시 업로드 파일 테이블업로드 되는 파일에 대한 정보를 관리하는 테이블입니다. 업로드가 진행되면 데이터가 생성되고 완료되면 삭제됩니다. 업로드 파일 테이블업로드가 완료된 파일에 대한 정보를 관리하는 테이블입니다. 1. DBeaver를 사용하여 SQL문을 실행합니다.-- testdb.tb_up_tempfile definitionCREATE TABLE `tb_up_tempfile` ( `SEQ` int NOT NULL AUTO_INCREMENT COMMENT '업로드 임시 파일 시퀀스', `FILE_ID` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '업로드 파일 ID', `FILE_PATH` varchar(..

[7] 대용량 파일 전송 시스템 개발 - 파일 확장자 변조 검증, Tika

모든 청크 데이터(이진 데이터)를 다 받은 후 내부의 바이트를 읽어 파일 형식(MIME Type)과 파일 확장자가 같은지 비교할 수 있습니다. 검증을 통해 악성 스크립트나 해킹 실행 파일이 문서 파일이나 이미지 파일로 위장해 서버로 업로드되는 것을 원천적으로 차단할 수 있어 보안이 강화됩니다. 아파치 티카(Apache Tika, https://tika.apache.org/)Tika는 다양한 파일에서 메타데이터와 텍스트를 감지하고 추출하는 라이브러리콘텐츠 유형 감지(파일 시작 부분 근처에서 특수("magic") 바이트 패턴을 찾아 파일 유형을 감지) 1. Tika를 사용하기 위해 pom.xml에 추가합니다.[Maven] org.apache.tika tika-core 3.0.0[Gradle]..

[6] 대용량 파일 전송 시스템 개발 - 암호화 전송, RSA + AES

청크 데이터(이진 데이터)를 암호화하여 보내면 보안을 높여 전송할 수 있습니다. 하이브리드 암호화 구조로 청크 데이터 전송1. 서버에서 RSA를 사용하여 공개키(PublicKey)와 개인키(PrivateKey)을 생성하고 공개키(PublicKey)를 클라이언트에 전달합니다.2. 클라이언트에서는 AES Key를 랜덤으로 생성하고 청크 데이터를 암호화합니다.3. AES Key를 서버에서 생성한 RSA 공개키(PublicKey)로 암호화하여 암호화된 청크 데이터와 같이 서버로 전송합니다.4. 서버에서 RSA 개인키(PrivateKey)로 AES Key를 복호화해서 암호화된 청크 데이터를 복호화합니다. RSA 공개키, 개인키 생성 서버에서 RSA를 사용하여 공개키와 개인키를 생성합니다. 1. 서버에서 Key..

[5] 대용량 파일 전송 시스템 개발 - 압축 / 무결성 검증, gzip, pako, MessageDigest

청크 데이터(이진 데이터)를 그래도 보내도 되지만 압축하면 전송 효율이 좋아지기 때문에 압축 라이브러인 pako(파코)를 사용하여 압축하여 전송할 수 있습니다. Blob(Binary Large Object)를 압축pako (https://github.com/nodeca/pako)pako(파코)는 Zlib 라이브러리의 JavaScript 구현체입니다. 1. pako(파코) 라이브러리를 CDN으로 가져옵니다. pako.gzip()은 Blob 객체를 직접 입력받을 수 없기 때문에 Uint8Array 같은 이진 배열(TypedArray) 형태로 데이터를 변환해서 사용해야 합니다. ArrayBuffer (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer..

[4] 대용량 파일 전송 시스템 개발 - 대용량 파일 업로드, Blob

대용량 파일 업로드대용량 파일을 청크로 분리하여 업로드하는 프로세스를 시퀀스 다이어그램(Sequence Diagram)으로 표현했습니다. Sequence Diagram(시퀀스 다이어그램) 웹 브라우저에서 대용량 파일을 청크(Chunk)로 분리하기 위해서 slice() 함수를 사용하면 됩니다. slice (https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice)File API의 slice 함수를 사용하여 Blob(Binary Large Object)를 가져옵니다. 파일에서 시작 바이트(begin)부터 끝 바이트(end)까지(end 미포함) 복사하여 Blob(Binary Large Object) 객체로 반환합니다.slice(start, end);// 업로드..

[3] 대용량 파일 전송 시스템 개발 - 카테고리별 파일 업로드 설정 관리 전체 소스

카테고리별 파일 업로드 설정 관리는 게시판 기반 형태로 단순한 CRUD로 되어 있어 설명 없습니다. 소스만 보셔도 충분히 이해하실 겁니다. 카테고리별 파일 업로드 설정 관리 전체 소스 DB 테이블 생성카테고리 테이블카테고리와 업로드/다운로드의 파일 경로, 업로드 청크 크기, 전송 암호화 여부 등을 관리하는 테이블입니다. 1. DBeaver를 사용하여 SQL문을 실행합니다.-- testdb.tb_category definitionCREATE TABLE `tb_category` ( `SEQ` int NOT NULL AUTO_INCREMENT COMMENT '카테고리 시퀀스', `CATE_ID` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci ..

[2] 대용량 파일 전송 시스템 개발 - 개발 환경, 공통 부분 소스

대용량 파일 전송(업로드/다운로드) 시스템 개발을 위해 기능을 정의하고 만들어 보겠습니다. 개발환경은 다음과 같습니다.IDE : IntelliJ IDEA 2025.2.2 (Community Edition)spring-boot 3.4.0Java 17.0.14MySQL 8.4 개발할 기능들을 기능 정의서로 정리하였습니다. 이전에 설명드린 것처럼 대용량 파일을 한번에 전송하지 않고 청크로 분리하여 전송하고 전송 중 중지, 재시작, 삭제를 할 수 있게 개발하겠습니다. 또한 보안을 강화하기 위해서 무결성 검증, 파일 확장자 변조 검증, 암호화 전송, 압축 전송 등 기능을 추가하여 개발하겠습니다. 기능 정의서기능기능 설명파일 업로드 설정 관리(관리자)대용량 파일 업로드에 대한 조건과 업로드 후 조치 사항을 설정합니..

[1] 대용량 파일 전송 문제점과 해결방법

대용량 파일 전송의 문제점서버파일의 크기가 클 수록 네트워크 트래픽(데이터 전송량)이 증가하고 서버의 자원(메모리, 스레드)을 많이 사용하게 되어 서버의 응답이 지연되고 다른 서버의 서비스가 느려지거나 중지될 수 있습니다.네트워크 회선 증설, 서버 메모리 증설 또는 서버 증설 → 비용 증가JVM 옵션에서 다이렉트 메모리(-XX:MaxDirectMemorySize) 조정 → 임시적인 조치전송시간이 길어지면 서비스 서버의 섹션 타임아웃(Session Timeout)이 발생해서 섹션 정보가 삭제될 수 있습니다.웹 서버 설정에서 섹션 타임아웃(session-timeout) 조정 → 임시적인 조치 → 보안 문제 발생 예상 클라이언트파일 업로드를 중지하기가 쉽지 않습니다.파일 전송이 동기 처리일 경우 전송 완료할 ..

[19] Frontend 개발 - Capacitor, Geolocation, Google Map

앱에 위치 기반 기능을 추가해보겠습니다. @capacitor/geolocation 설치 (https://capacitorjs.com/docs/apis/geolocation) 위치 기반 기능 사용1. geolocation 설치 (터미널에서 실행합니다.)npm install @capacitor/geolocation --save 2. src\views\LunchMenu에 LunchMenuMapView.vue 파일을 생성합니다. GeoLocation 나의 위치: 위도: {{ loc.lat }} 경도: {{ loc.lng }} 현 위치 3. src\router\index.js 파일을 수정합니다. :import LunchMenuMapVie..

[18] Frontend 개발 - Capacitor, Vue + Android

Capacitor를 사용하여 쉽게 앱을 개발해 보도록 하겠습니다. Capacitor (https://capacitorjs.com) Web App에 Capacitor 추가 (https://capacitorjs.com/docs/getting-started#add-capacitor-to-your-web-app) 1. capacitor 설치 (터미널에서 실행합니다.)npm install @capacitor/core @capacitor/cli --save 2. Capacitor 초기화 (터미널에서 실행합니다.)npx cap init App Name : 앱 이름 (변경하지 않으려면 그냥 엔터 키를 누릅니다. 변경하려면 입력합니다.) Package ID : 앱의 패키지 아이디 (변경하지 않으려면 그냥 엔터 키를 누..

Android 설치 - Hello Android 실행

Android Studio 다운로드1. Android Developer (https://developer.android.com/?hl=ko) 사이트로 이동합니다. 2. [Android 스튜디오 다운로드]를 클릭합니다. 3. 약관를 아래로 스크롤한 후 동의를 체크하고 하고 [다운로드]를 누릅니다.현재는 Android Studio Quail 2 입니다. 4. Android Studio가 다운로드 됩니다. Android Studio 설치1. [Next] 버튼을 누릅니다. 2. 설치할 컴퍼넌트를 선택하고 [Next] 버튼을 누릅니다. 3. 설치 경로를 설정하고 [Next] 버튼을 누릅니다. 4. 설치 이름을 설정하고 [Next] 버튼을 누릅니다. 5. 설치가 진행됩니다. 6. 설치가 완료되면 [Finish] ..

[17] Frontend 개발 - Store State 유지, Cookies, localStorage, Pinia Plugin Persistedstate

페이지 새로고침 문제점웹 브라우저에서 새로고침을 하면 Vue가 초기화 되면서 Store가 초기화 됩니다. 페이지 새로고침 문제점 해결Store에 있는 State를 유지하기 위해서는 state의 정보를 저장하고 초기화되면 다시 읽어 들어 유지하게 하면 됩니다. State의 정보를 저장하고 유지하기 위해 다음과 같이 세 가지 방법이 있습니다.Cookie(쿠키)를 사용하는 방법Storage(스토리지)를 사용하는 방법Pinia Plugin Persistedstate를 사용하는 방법 Store State 유지 - Cookie(쿠키) 사용 웹 브라우저에서 F12키를 누르면 개발자 툴이 나타납니다.여기서 Application를 클릭하고 Cookies를 클릭합니다. Cookie 구성Name : 쿠키 이름Value : ..

[17] Frontend 개발 - Login 관리, 모듈화

모듈화Axios Instance (엑시오스 인터셉터) (https://axios-http.com/kr/docs/instance) 1. src\apis\axiosInterceptor.js 파일을 수정합니다.import axios from 'axios';import { useLoginStore } from '@/stores/useLoginStore';import { useRouter } from 'vue-router';export const createAxiosInstance = (baseURL, timeout) => { const loginStore = useLoginStore(); const router = useRouter(); const axiosInstance = axios...

[16] Frontend 개발 - Login 관리, Axios Interceptor

Axios Interceptor (엑시오스 인터셉터)를 사용하여 Access Token 재발급(갱신)Axios Interceptor (엑시오스 인터셉터) (https://axios-http.com/kr/docs/interceptors)Axios 요청 전이나 Axios 응답 후 처리는 Axios Interceptor (엑시오스 인터셉터)을 사용하여 가로챌 수 있습니다. Axios Interceptor (엑시오스 인터셉터) 기본 구조입니다.// 요청 인터셉터axios.interceptors.request.use(function (config) { // Do something before request is sent // 요청이 전달되기 전에 처리 return config; }, functi..

[15] Frontend 개발 - Login 관리, Access Token, Refresh Token

Access Token, Refresh Token (액세스 토큰, 리프레시 토큰)1. src\stores\useLoginStore.js 파일을 수정합니다.import { defineStore } from 'pinia';import { ref, computed } from 'vue';import axios from 'axios';export const useLoginStore = defineStore('login', () => { const access_token = ref(""); const refresh_token = ref(""); // 로그인 여부를 가져옵니다. const isLogin = computed(() => { return refresh_token.valu..

[14] Backend 개발 - 사용자 API 개발, 라우트 별 인증 처리, 인가 처리

라우트 별로 인증 처리1. index.js 파일 수정const express = require('express');const cookieParser = require('cookie-parser');const app = express();const port = 9000;app.get('/', (req, res) => { res.send('Hello World!');});:// Cookie 설정app.use(cookieParser());// 인증 설정//app.use('/api/v1/lunchmenus', require('./src/api/v1/authMiddleware'));// 점심 메뉴 연결app.use('/api/v1/lunchmenus', require('./src/api/v1/lunchmen..

[13] Backend 개발 - 사용자 API 개발, Access Token, Refresh Token

기존 ID Token 생성 부분을 함수로 분리 ID Token 생성1. src\api\v1\member.js 파일 수정 – ID Token 생성 함수로 분리합니다.// ID Token을 생성합니다.async function generateIDToken(memberID, memberName, memberRoles) { const result = { result: 'success', message: '', token: '' }; // 토큰 발급 시간 const issuedAt = new Date().toLocaleString(); const iat = Date.parse(issuedAt) / 1000; // ID Token - JWT ..

[11] Frontend 개발 - 상태 관리, Store – Pinia

Store를 사용해야 하는 이유Store는 애플리케이션 전반에서 접근할 수 있는 데이터를 포함해야 합니다.여러 컴포넌트에서 사용되는 데이터(사용자 정보, 네비게이션 정보, 전역 정보)와 컴포넌트에서 보존되어야 하는 데이터(Form 데이터)가 포함됩니다. Store는 state와 비즈니스 로직을 보유하는 독립체(entity)로 컴포넌트 트리에 묶여 있지 않습니다.→ 전역 state로 모든 컴포넌트가 읽고 쓸 수 있습니다. Computed (계산된 속성) 사용반응형 데이터를 계산하는 코드가 내에 있거나 반복되면 이 복잡해 보일 수 있습니다.그래서 계산하는 코드를 분리하고 반응되도록 computered() 함수로 처리합니다. 리스트가 {{ lunchMenuList.value.length > 0 ?..

[10] Frontend 개발 - 상태 관리

상태 관리여러 하위 컴포넌트들이 동일한 데이터를 사용해야 할 경우 → 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달해야 할 때 props를 사용합니다. 깊은 계층 구조를 가진 컴포넌트 트리에서 비효율적입니다. → Prop Drillin Prop Drilling (프랍(프롭) 드릴링)자식 컴포넌트는 부모 컴포넌트로부터 데이터를 전달 받기 위해 FooterComp.vue Footer에는 사용하지 않지만 자식 컴포넌트인 DeepChild가 사용하기 때문에 prop를 설정해야 합니다. DeepChildComp.vue {{ userID }}, Have a good time Provide(제공) / Inject(주입) 사용 ← Prop Drilling 해결 상위 컴포넌트는 하위 모든 컴포넌트에 대한..

[9] Backend 개발 - 사용자 API 개발, 인증 처리, ID Token

ID Token사용자가 로그인하면 서버에서 사용자를 확인하여 사용자 정보로 토큰을 생성한 후 응답 데이터로 클라이언트에게 토큰을 전달하는 방식입니다.클라이언트는 요청을 보낼 때 Authorization HTTP Header에 토큰을 포함하여 전달하면 서버는 전달 받은 토큰을 검증하여 인증된 사용자인지 확인합니다. ID 토큰은 JSON Web Token (JWT, JSON 웹 토큰)입니다.ID 토큰에는 인증된 사용자에 대한 정보(claim(클레임))가 포함되어 있습니다. 장점클라이언트에서 토큰을 관리하기 때문에 서버에 부하가 낮아집니다.접근 권한을 적용할 수 있습니다.단점토큰이 탈취 당할 수 있습니다. → 보안성이 취약함 (HTTPS로 보안할 수 있습니다. 단, 클라이언트 해킹은 차단할 수 없습니다.)모든..

[8] Backend 개발 - 사용자 API 개발, 인증 처리, Session + HTTP Cookie

인증 처리를 위한 사용자 API 개발사용자 인증 처리를 위한 테이블을 생성합니다. Table 생성테이블 생성 쿼리 실행use lunchdb;-- tb_member table이 있으면 삭제DROP TABLE IF EXISTS tb_member;-- tb_member table 생성CREATE TABLE tb_member ( seq int NOT NULL AUTO_INCREMENT COMMENT '사용자 일련번호', mbr_id varchar(50) NOT NULL COMMENT '사용자 ID', mbr_pw varchar(125) NOT NULL COMMENT '사용자 비밀번호', mbr_name varchar(50) NOT NULL COMMENT '사용자 이름', mbr_rol..

[7] Frontend 개발 - 읽기 뷰 (ReadView), 수정, 삭제 생성

읽기 뷰 (ReadView) 생성1. src\views\LunchMenu에서 LunchMenuReadView.vue 파일을 생성합니다. 점심 메뉴 보기 2. src\router\index.js에서 LunchMenuReadView.vue를 import하고 children(칠드런)에 추가합니다.:import LunchMenuReadView from '@/views/LunchMenu/LunchMenuReadView.vue'const routes = [ : { path: '/lunchmenu', component: LunchMenuView, children : [ : { path: ':seq', name: 'lunchmenuread', ..

[6] Frontend 개발 - 등록 뷰 (AddView) 생성

등록 뷰 (AddView) 생성1. src\views\LunchMenu에서 LunchMenuAddView.vue 파일을 생성합니다. 점심 메뉴 등록 2. src\router\index.js에서 LunchMenuAddView.vue를 import하고 routes에 route를 추가합니다.:import LunchMenuAddView from '@/views/LunchMenu/LunchMenuAddView.vue'const routes = [ : { path: '/lunchmenu/', name: 'lunchmenulist', component: LunchMenuListView }, { path: '/lunchmenu/add', name: 'lunchmenuadd', ..

728x90
728x90