localhost에 SSL 적용하기

localhost는 SSL이 적용되지 않는 http일지라도 SSL이 적용된 것으로 간주됩니다. 그럼에도 불구하고 localhost에 SSL을 적용해야할 상황이 생깁니다.

먼저 다음 패키지를 설치합니다.

npm install @vitejs/plugin-basic-ssl

vite.config.js에서 다음 코드를 추가합니다.

import basicSsl from '@vitejs/plugin-basic-ssl' // ADDED

export default {
  ...

  plugins: [
    ...

    basicSsl(), // ADDED
  ]

  ...
}

이제 http://localhost가 아닌 https://localhost로 결과를 확인할 수 있습니다. 하지만 SSL 인증서가 적합하지 않으므로 웹브라우저에서 사용자가 추가적인 허용을 해줘야 합니다.

Java 11, HTTP Client API

Java 11부터는 별도의 외부 라이브러리 없이도 Java에서 기본적으로 제공하는 HTTP Client API를 통해 거의 대부분의 네트워크 통신(클라이언트에서 서버로의 요청) 기능을 처리할 수 있습니다.

이 API는 HttpURLConnection을 대체하기 위해 설계되었으며, HTTP/1.1과 HTTP/2, 동기/비동기 통신, WebSocket, Proxy, Authentication, TLS/SSL, HTTP/2 Server Push 등을 지원합니다.

예를들어서 GET 방식의 동기적 요청은 다음 코드와 같습니다.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class App {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://example.com"))
                .GET()
                .build();

        HttpResponse<String> response = client.send(
                request,
                HttpResponse.BodyHandlers.ofString()
        );

        System.out.println("Status: " + response.statusCode());
        System.out.println("Headers: " + response.headers());
        System.out.println("Body:" + response.body());
    }
}

17번 코드의 send 매서드에 지정한 2번째 인자는 body를 문자열로 받겠다는 의도입니다.

POST 방식의 동기적 요청에 대한 코드 예시는 다음과 같습니다.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class App {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();

        String json = """
                {
                    "name": "Tom",
                    "age": 20
                }
                """;

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://example.com/users"))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .build();

        HttpResponse<String> response = client.send(
                request,
                HttpResponse.BodyHandlers.ofString());

        System.out.println(response.statusCode());
        System.out.println(response.body());
    }
}

위의 코드는 동기적 요청인데, 비동기적 요청 방식으로 변경하면 다음과 같습니다.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class App {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();

        String json = """
                {
                    "name": "Tom",
                    "age": 20
                }
                """;

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://example.com/users"))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .build();

        client.sendAsync(
                request,
                HttpResponse.BodyHandlers.ofString())
                .thenAccept(response -> {
                    System.out.println(response.statusCode());
                    System.out.println(response.body());
                })
                .join();
    }
}

TypeScript로 개발한 라이브러리를 npm에 배포하기

node 설치가 필요합니다. 그리고 라이브러리를 위한 개발 폴더를 위해 다음과 같은 명령 수행이 필요합니다.

mkdir -p ~/dev/my-libary
cd ~/dev/my-libary
npm init -y
npm install -D typescript tsup
mkdir src

src/index.ts에 다음 코드를 입력합니다.

export function add(left: number, right: number): number {
  return left + right;
}

index.ts는 진입점이 되므로 사용자에게 공개할 것들을 export하는 것이 주목적입니다. 실제 API에 대한 코드는 별도의 코드 파일을 통해 제공하는 것이 일반적입니다.

tsconfig.json 파일을 생성해 다음처럼 입력합니다.

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "noEmit": true,
    "verbatimModuleSyntax": true
  },
  "include": ["src"]
}

package.json 파일의 내용을 아래처럼 구성합니다.

{
  "name": "@YOUR_NPM_ID/my-libary",
  "version": "1.0.1",
  "description": "타입스크립트로 만든 테스트 라이브러리",
  "type": "module",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js",
      "require": "./dist/index.cjs",
      "default": "./dist/index.js"
    }
  },
  "files": [
    "dist"
  ],
  "scripts": {
    "build:js": "tsup src/index.ts --format esm,cjs --clean",
    "build:types": "tsc -p tsconfig.build.json",
    "build": "npm run build:js && npm run build:types",
    "check": "tsc --noEmit",
    "prepack": "npm run check && npm run build"
  },
  "keywords": [
    "typescript",
    "library"
  ],
  "license": "MIT",
  "devDependencies": {
    "tsup": "^8.5.1",
    "typescript": "^7.0.2"
  }
}

타입스크립트 코드의 타입 오류를 검사하고 빌드 하기 위해 다음 명령을 수행합니다.

npm run check
npm run build

dist 폴더가 생성되고 이 폴더 안에 index.js, index.cjs, index.d.ts 가 생성되어야 합니다.

실제 npm에 배포하기 위한 파일 생성을 시험해 보기 위해 다음 명령을 수행합니다.

npm pack --dry-run

출력되는 내용에서 dist/index.js, dist/index.cjs, dist/index.d.ts, package.json이 tar로 묶이는지 확인하면 됩니다. 만약 README.MD와 LICENSE 파일을 package.json 파일이 위치한 같은 폴더에 생성해 놨다면 이 2개의 파일들도 tar로 묶여야 합니다. tar로 묶인 결과를 tarball이라고 합니다.

실제 tarbal를 생성하기 위해 다음 명령을 수행합니다.

npm pack

그럼 your-npm-id-my-libary-1.0.0.tgz 파일이 생성됩니다.

your-npm-id-my-libary-1.0.0.tgz 파일을 npm에 배포하기에 앞서 이 파일로 라이브러리가 제대로 설치 되는지 확인하기 위해 새로운 프로젝트 풀더를 다음 절차를 참고하여 생성합니다.

mkdir -p ~/dev/my-libary-consumer
cd ~/dev/my-libary-consumer
npm init -y
npm install ../your-npm-id-my-libary-1.0.0.tgz

index.js 파일을 생성하고 다음 코드를 입력합니다.

const { add } = require("@YOUR_NPM_ID/my-libary");

console.log(add(10, 20));

다음 명령으로 코드가 정상적으로 실행되는지 확인합니다.

node index.js

이제 npm 사이트에 배포하기 위해 npm에 로그인합니다. 라이브러리 프로젝트에서 다음 명령을 실행합니다.

cd ~/dev/my-libary
npm login
npm whoami

자신의 npm ID가 출력되어야 합니다. 배포하기에 앞서 my-libary가 등록된적이 있는지 확인하기 위해 다음 명령을 실행합니다.

npm view @YOUR_NPM_ID/my-libary version

등록한 적이 없으므로 404 오류가 나와야 합니다.

실제 배포하기에 앞서 다시 한번 더 검증하고 배포합니다.

npm run check
npm pack --dry-run
npm publish --access public

이제 라이브러리를 테스트하기 위한 폴더에서 다음처럼 npm 사이트로부터 라이브러리를 설치해 테스트해 봅니다.

cd ~/dev/my-math-kit-consumer
npm uninstall @YOUR_NPM_ID/my-libary
npm install @YOUR_NPM_ID/my-libary
node index.js

라이브러리가 변경되면 버전업을 하고 다시 npm에 재배포해야 합니다. 다음 절차를 따릅니다.

cd ~/dev/my-math-kit
npm version patch
npm publish

위의 경우 버전업 레벨이 patch입니다. 다음을 참고하여 버전업 합니다.

  • patch: 버그 수정 (1.0.0 → 1.0.1)
  • minor: 하위 호환되는 기능 추가 (1.0.0 → 1.1.0)
  • major: 호환성을 깨는 변경 (1.0.0 → 2.0.0)

이제 라이브러리를 테스트하기 위한 폴더에서 다음처럼 npm 사이트로부터 라이브러리를 업데이트해 테스트해 봅니다.

cd ~/dev/my-libary-consumer
npm update @YOUR_NPM_ID/my-libary
npm list @YOUR_NPM_ID/my-libary

라이브러리가 변경되면 이를 tarball로 묶고 테스트하는 프로젝트에서 tarball을 설치(npm을 통해서든, 파일을 통해서든)하는 것은 매우 번거롭습니다. 이 경우 npm link를 통해 쉽게 해결할 수 있습니다.

라이브러리 폴더에서 다음 명령을 수행합니다.

cd ~/dev/my-libary
npm run build
npm link

그리고 테스트 폴더에서는 다음 명령을 입력합니다.

cd ~/dev/my-libary-consumer
npm link @YOUR_NPM_ID/my-libary

라이브러리를 link 방식이 아닌 tarball로 설치하고 싶다면 링크를 해제해야 합니다. 방법은 아래와 같습니다.

cd ~/dev/my-libary-consumer
npm unlink @YOUR_NPM_ID/my-libary

jar 정리

  • sqljdbc4.jar : 마이크로소프트 SQL 서버(Microsoft SQL Server) 데이터베이스에 연결하기 위해 사용하는 JDBC(Java Database Connectivity) 드라이버
  • commons-io-2.4.jar : 파일과 디렉터리 조작, 입출력(I/O) 작업을 쉽게 하도록 돕는 Apache Commons IO 라이브러리
  • ellip2ellipsoid.jar : 타원체 간 변환 라이브러리
  • EPSG.jar : EPSG 좌표계 라이브러리
  • icu4j_3_2.jar : IBM이 개발하고 Unicode 협회가 관리하는 ICU4J(International Components for Unicode for Java) 라이브러리 (ArcSDE 에서 사용되는 것으로 판단됨)
  • javaproj-1.0.6-noawt.jar : 좌표계 변환 및 지도 투영 라이브러리
  • jpe_sdk.jar : ESRI 사의 ArcSDE 시스템에서 제공하는 자바 프로젝션 엔진(Projection Engine) API 클래스 파일들을 담고 있는 라이브러리
  • jsde_sdk.jar : ESRI 사의 ArcSDE 데이터베이스와 통신하기 위한 자바 클라이언트 및 지오메트리(Geometry) API 라이브러리
  • jsde_sdkres.jar : ESRI사의 ArcSDE Java SDK에서 사용하는 리소스(Resource) 라이브러리
  • jts-1.12.jar : 2차원 공간 기하학 정보를 다루는 라이브러리인 (JTS Topology Suite(Java Topology Suite)
  • postgis-1.5.0.jar : PostGIS 데이터베이스의 공간 정보(GIS) 데이터를 다루기 위해 사용하는 JDBC 드라이버 및 지오메트리(Geometry) 라이브러리
  • postgresql-42.2.2.jar : PostgreSQL 데이터베이스에 연결할 수 있도록 돕는 JDBC(Java Database Connectivity) 드라이버
  • jetty-all-9.4.57.v20241219-uber.jar : 이클립스 젯티(Eclipse Jetty) 9.4 버전대의 마지막 공개 릴리스 중 하나인 통합(Aggregate) 라이브러리
  • trove-2.1.0.jar : 고성능 컬렉션 라이브러리인 GNU Trove의 2.1.0 버전 라이브러리
  • shpwriter.jar : 자바(Java) 환경에서 GIS 데이터 포맷인 Shapefile(*.shp)을 생성하고 내보내기(Export) 위해 사용하는 라이브러리
  • kmlwriter.jar 자바(Java) 환경에서 KML을 생성하고 내보내기(Export) 위해 사용하는 라이브러리
  • json-simple-1.1.1.jar : 자바(Java)에서 JSON 데이터를 쉽게 읽고, 쓰고, 다룰 수 있게 해주는 경량 JSON.simple 라이브러리
  • ojdbc6.jar : 오라클 데이터베이스(Oracle Database)를 연결해 주는 오라클 JDBC 드라이버
  • sdoutil.jar : 오라클 데이터베이스(Oracle Database)의 공간 데이터(Spatial Data) 처리를 지원하는 자바 라이브러리
  • sdoapi.jar : 오라클 데이터베이스(Oracle Database)에서 공간 데이터(Spatial Data 및 기하학적 데이터)를 자바(Java) 애플리케이션과 연동하여 처리할 때 사용하는 라이브러리
  • mybatis-3.5.1.jar : 데이터베이스와 쉽게 연결하고 SQL을 다룰 수 있게 해주는 MyBatis 프레임워크 라이브러리
  • tibero6-jdbc.jar : 티베로 6(Tibero 6) 데이터베이스에 접속하여 쿼리를 실행할 수 있게 해주는 JDBC 드라이버
  • quartz-2.3.0-SNAPSHOT.jar : 주기적인 작업(Job) 스케줄링을 구현할 수 있게 해주는 오픈소스 라이브러리인 Quartz Scheduler의 2.3.0 개발 중(Snapshot) 버전 라이브러리
  • slf4j-api-1.7.7.jar : 다양한 로깅 프레임워크를 연결해 주는 추상화(Facade) 라이브러리인 SLF4J(Simple Logging Facade for Java) 라이브러리
  • javax.activation-1.2.0.jar : MIME 데이터(이메일 첨부파일, 이미지 등)를 관리하고 처리할 수 있게 돕는 JavaBeans Activation Framework(JAF) 라이브러리
  • javax.mail.jar : 이메일을 송수신할 수 있도록 지원하는 JavaMail API 라이브러리
  • http-client-4.5.13-all.jar : HTTP 통신을 수행하기 위해 사용하는 Apache HttpComponents HttpClient 라이브러리
  • string-similarity.jar : 두 문자열이 얼마나 비슷한지(유사도)를 계산할 수 있도록 도와주는 라이브러리

GeoService-Xr 설정값 정리

  • SqlFile : 서버 단에서 사용되는 SQL 문에 대한 함수화가 저장된 파일(json)
  • EncryptionFile : 웹앱 단위로 사용되는 암호화 키값이 저장된 파일(json)
  • WebHomeDir : 웹서버를 통해 제공되는 정적 파일이 저장된 디렉토리
  • SessionCheckingFlags : 세션 여부에 따라 서비스 호출을 허용할 것인지를 결정하는 파일(json)
  • GeoDataFile : DB 연결정보 및 공간 데이터 설정 파일(xml)
  • Port : 서버가 사용하는 포트
  • MainMemoryBuffersCount : 주 메모리 풀에 저장된 단위 메모리 개수
  • MainMemoryBufferSize : 주 메모리에 저장된 단위 메모리 크기(단위: 바이트)
  • SubMemoryBuffersCount : 보조 메모리 풀에 저장된 단위 메모리 개수
  • SubMemoryBufferSize : 보조 메모리 풀에 저장된 단위 메모리 크기(단위 : 바이트)
  • MyBatisConfig : MyBatis(SQL 매핑 프레임워크) 설정 파일(xml)
  • ValidationCheck : DB 커넥션 객체의 유효성 검증 여부
  • ValidationCheckTime : DB 커넥션 객체의 유효성 검증 여부가 true일 경우 검증을 수행할 시간 (크론 표현식)
  • LogLevel : 서비스 이용 로그 레벨 수준(0: 로그 안남김 / 1: 성공/실패 여부만 남김 / 2 : 매우 자세히 남김)
  • PlugIn : 서버가 제공하는 기본 서비스 이외의 특화된 서비스 모듈 설정 파일(json)
  • DBRepositoryForGeocoding : 지오코딩 서비스를 제공할 때 서비스 최적화를 위한 DB 구성 여부
  • AllowCORS : 서버가 CORS를 허용할지 여부
  • SSL_p12 : SSL을 위한 .p12 파일 경로
  • SSL_pw : SSL을 위한 .pw 파일 경로
  • PG_SecretKey : PG에 대한 비밀키 문자열
  • AdminEmail : 메일 전송 서비스에서 사용하는 발신자 메일 주소(현재 구글 메일만 가능)
  • AdminEmailPW : 메일 전송 서비스에서 사용하는 발신자 메일의 암호