서버환경 이슈 분석을위한 간단한 Java 실행파일

웹 백엔드 개발 업무를 하다보면 이런일이 종종 있습니다.
예를 들면,
1) 고갱님 서버에서 어떤 기능을 사용하면 오류가 납니다.

2) 그런데 개발자 PC에서는 오류가 안납니다.

3) 우리 고갱님은 서버에 방화벽 정책 같은것도 없고
   OS계정 정보도 다 공유해 주시면서 어떻게든
   문제만 빨리 해결해주기를 원하십니다.

4) 이런경우 보통 설정이나 환경 문제이기 때문에
   코드 분석을 통해 고갱님 서버에서만 발생할 수 있는 문제를
   개발자가 유추해서 예외처리를 합니다.

5) 코드수정 후 수정한 내용이 잘 동작하는지 확인해보고 싶은데
   고갱님 Live 서버에 반영하자니 서버를 내렸다 올려야 하고
   추측을 통해 수정 작업을 했으니 혹시라도 추측이 틀렸다면
   잘못된 부분을 다시 찾아 위에 했던짓을 반복해야 하기 때문에
   부담이 될 수밖에 없습니다.

 

이런경우 저는 부담없이 이슈 트래킹을 하기 위해

빠르게 실행해볼 수 있는 JAVA App를 미리 만들어놓고

문제로 예상되는 부분의 코드를 넣어서 빌드한후

고갱님 서버에 파일을 올려 로그를 찍어가며 이슈를 분석 합니다.

 

다음은 제가 활용하는 JAVA App를 만드는 과정을 설명 합니다.

 

아래와 같은 조건으로 간편하게 실행할 수 있는 JAR 파일을 만드는 것이 목적 입니다.

java -jar {파일명} 명령어로 실행
main class 입력은 생략할 수 있도록 처리
jar파일 하나에 참조되는 오픈소스들을 모두 포함

 

Maven 프로젝트 생성

거부감 없이 친숙한 Maven quickstart 프로젝트를 하나 생성 합니다.

 

적당한 정보를 입력하고

 

pom.xml 작성

pom.xml을 정당히 수정해줍니다.

편하게 로그를 찍기위해 logback을 참조 하였습니다.

이 프로젝트에서 참조하는 모든 라이브러리를 재패키지하여 하나의 JAR 파일에 모이도록

maven-shade-plugin을 사용하였고, 프로젝트 생성시 자동생성된 App 클래스를 메인클래스로 지정하였습니다.

이렇게하면 java -jar 실행시 메인클래스 입력이 필요 없습니다.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.study</groupId>
	<artifactId>issuetracker</artifactId>
	<version>1.0.0.0</version>
	<packaging>jar</packaging>

	<name>issuetracker</name>
	<url>http://maven.apache.org</url>

	<properties>
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.plugin.version>3.8.0</maven.compiler.plugin.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.2.3</version>
			<exclusions>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>slf4j-api</artifactId>
				</exclusion>
			</exclusions>
			<scope>compile</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-core</artifactId>
			<version>1.2.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.25</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>${maven.compiler.plugin.version}</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
					<encoding>${project.build.sourceEncoding}</encoding>
					<compilerArgument>-Xlint:all</compilerArgument>
					<showWarnings>true</showWarnings>
					<showDeprecation>true</showDeprecation>
				</configuration>
			</plugin>			
			<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-shade-plugin</artifactId>
			<version>3.0.0</version>
			<executions>
				<execution>
					<phase>package</phase>
					<goals>
						<goal>shade</goal>
					</goals>
					<configuration>
						<transformers>
							<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
								<mainClass>${project.groupId}.${project.artifactId}.App</mainClass>
							</transformer>
						</transformers>
					</configuration>
				</execution>
			</executions>
		</plugin>
		</plugins>
	</build>
</project>

 

logback.xml 생성

로그설정을 위한 logback.xml이 들어갈 소스폴더를 생성합니다.

 

logback.xml 에 적당히 설정 내용을 입력 합니다.

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true" scanPeriod="30 seconds">

	<timestamp key="date" datePattern="yyyyMMdd" />
	<timestamp key="year" datePattern="YYYY" />
	<timestamp key="month" datePattern="MM" />
	<timestamp key="day" datePattern="dd" />

	<!-- 콘솔로 로그를 남기는 설정 -->
	<appender name="console"
		class="ch.qos.logback.core.ConsoleAppender">
		<encoder
			class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<charset>UTF-8</charset>
			<Pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%p] [%t] [%c]%m%n</Pattern>
		</encoder>
	</appender>

	<!-- 파일로 로그를 남기는 설정 -->
	<appender name="file"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 저장경로/파일명 -->
		<file>log/${year}-${month}-${date}.log</file>
		<encoder
			class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<Pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%p] [%t] [%c] %m%n</Pattern>
		</encoder>

		<rollingPolicy
			class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
			<!-- 파일명을 .zip .tz로 하는경우 자동으로 압축된다 -->
			<fileNamePattern>log/${year}-${month}-${date}_%i.log.zip
			</fileNamePattern>
			<minIndex>1</minIndex>
			<maxIndex>10</maxIndex>
		</rollingPolicy>

		<triggeringPolicy
			class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
			<maxFileSize>30MB</maxFileSize>
		</triggeringPolicy>
	</appender>

	<root level="debug">
		<appender-ref ref="file" />
		<appender-ref ref="console" />
	</root>

</configuration>

 

프로젝트 패키징

준비가 다 됐습니다.

Maven install을 통해 jar파일을 생성해 봅니다.

영어영어 블라블라를 통해 플러그인도 잘 동작했고 jar파일도 잘 만들어졌다

라고 이클립스가 말해줍니다.

 

JAR파일 까보기

생성된 jar파일을 압축 프로그램을 통해 열어보면 (다들 아시겠지만 jar 파일은 압축파일입니다.)

이 프로젝트에서 코딩된 com.study.issuetracker 패키지 외에도

참조된 모든 패키지가 같이 들어있는것을 볼 수 있습니다.

이렇게 패키징하면 참조한 오픈소스 lib들을 같이 배포할 필요가 없습니다.

 

테스트 코드 작성

여기에서는 slf4j를 이용하여 로그를 찍어보는것으로 테스트코드를 대체하겠습니다.

이슈 발생시 앞으로는 이 클래스를 시작점으로 상황에 맞게 로직을 전개해 나가면 됩니다.

package com.study.issuetracker;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Hello world!
 *
 */
public class App 
{	
	static Logger log = LoggerFactory.getLogger(App.class);
	
    public static void main( String[] args )
    {
    	App app = new App();
    	
    	app.testFunction("첫번째");
    }
    
	private void testFunction(String message) {
		log.info("이것은 {} 테스트 입니다.", message);
	}
}

실행결과

[2023-05-09 16:24:06] [INFO] [main] [com.study.issuetracker.App]이것은 첫번째 테스트 입니다.

 

서버 테스트

App를 제작한 환경과 상관없는 서버에 파일을 올려서

잘 동작하는지 확인 해 봅니다.

정상적으로 실행되고 log도 생성하는 것을 볼 수 있습니다.

 

'프로그래밍' 카테고리의 다른 글

ShellScript하나로 터미널, FTP 둘다 연결하기 + PowerShell  (0) 2023.04.11
SSL 인증서 변환  (0) 2023.04.04

맥북 M1 Pro 영입

업무용으로 쓰던 MacBook의 밧데리, 전원부, 디스플레이가 전체적으로 상태가 좋지 못하여
Macbook M1 Pro 32Gb 모델로 교체를 하였습니다.
이때까진 몰랐죠 새 노트북 득템에 신나있던 저에게 무서운 시련이 기다리고 있었다는 것을..
 

비어있는 서버리스트

저는 평소에 서버관리용 Client로 터미널 작업은 Termius, 파일전송은 FileZilla를 사용하고 있었습니다.
관리하는 서버가 수십개인데 접속정보를 하나하나 새로 입력해야하는 사태에 직면하게 됩니다.

비어버린 서버리스트

SSH 명령어를 통해 접속

임시방편으로 기본 터미널에서 ssh 명령어를 통해서 그때그때 접속하여 업무를 하던 중

❯ ssh root@10.105.1.191 -p 1022
root@10.105.1.191's password: qwer1234
Last login: Tue Apr  4 15:51:29 2023 from 10.105.1.190
[root@release ~]#

'이제 Termius와는 결별하고 iTerm 터미널로 접속해서 작업하자'
'ShellScript를 짜서 자동 접속 환경을 만들자'' 라는 생각에 미치게 됩니다.
 

SSHPASS 설치

ssh 명령어를 통해 원격접속을 하려면 password 입력 프롬프트와 마주하게 되기 때문에

결국 비밀번호를 기억하고 있어야 한다는 문제가 있습니다.

따라서, 저장된 패스워드를 파라메터로 넘겨 실행할 수 있는 방법이 필요합니다. 
다행히 sshpass라는 딱 원하는 프로그램이 있습니다.
보안상의 이유로 homebrew를 통해 기본적으로 설치할 수 없는 프로그램이라서
저는 아래와 같은 명령어로 설치 하였습니다.

brew install hudochenkov/sshpass/sshpass

 
기본적인 사용방법은 아래와 같습니다.
비밀번호를 파라메터로 넘겨서 접속이 되는것을 볼 수 있습니다.

❯ sshpass -p qwer1234 ssh -o StrictHostKeyChecking=no -p 1022 root@10.105.1.191
Last login: Tue Apr 11 16:59:25 2023 from 10.105.1.190
[root@release ~]#

 

Shell Script 코딩

접속정보를 관리할 파일명은 hosts.properties 라고 정했고 포맷은 아래와같습니다.
[서버이름]:[IP]:[PORT]:[계정]:[패스워드]
 

hosts.properties

191-TEST:10.105.1.191:1022:root:qwer1234
192-TEST:10.105.1.192:2022:root:qwer1234
193-TEST:10.105.1.193:1022:root:qwer1234
194-TEST:10.105.1.194:2022:root:qwer1234

 
 
이어서 바로 스크립트 코드 입니다.
기본구조는 아래와 같습니다.

  1.  hosts.properties 파일을 읽어와 5개의 배열에 순서대로 담기
  2.  무한 while문 안에서 한페이지에 20개씩 서버목록을 보여주고 사용자 입력대기
  3.  방향키가 입력되면 page 이동
  4.  'q'가 입력되면 종료
  5.  숫자가 입력되면 해당 접속정보를 선택
  6. ssh로 연결할지 FileZilla로 연결할지 여부를 선택

ssh.sh

#/bin/sh

validNum()
{
    validchars="$(echo $1 | sed -e 's/[^[:digit:]]//g')"

    if [ -z $1 ] ; then
        return 1
    fi
    if [ "$validchars" = "$1" ] ; then
        return 0
    else
        return 1
    fi
}

viewPage()
{
    clear
    echo "[ $(($1+1)) Page ]"
    echo "-----------------------------------------------------"
    for((i=0;i<$2;i++))
    do
        echo "$((i+1)): ${names[$(($1*$2+i))]} - (${ips[$(($1*$2+i))]})"
    done
    echo "-----------------------------------------------------"
    echo "← → ↑ ↓           : move page"
    echo "input number ⏎    : connect"
    echo "q                 : exit"
    echo "-----------------------------------------------------"
    /bin/echo -n "Enter Input: "
}

fileZilla="/Applications/FileZilla.app/Contents/MacOS/filezilla"
fileName="hosts.properties"
workDir="$(cd "$(dirname "$0")" && pwd)"
file=$workDir/$fileName

declare -a names
declare -a ips
declare -a ports
declare -a ids
declare -a passwords

current_page=0
count_per_page=20

if [ -f "$file" ]
then
    i=0
    while IFS=':' read -r name ip port id password
    do
        names[$i]=$name
        ips[$i]=$ip
        ports[$i]=$port
        ids[$i]=$id
        passwords[$i]=$password
        i=$((i+1))
    done < "$file"
else
    echo "$file not found."
fi

viewPage $current_page $count_per_page

while true; do
    read -r -sn1 t
    case $t in
        A) 
            
            current_page=$((current_page+1))
            viewPage $current_page $count_per_page
        ;;
        B) 
            if [ $current_page -gt 0 ] ; then
                current_page=$((current_page-1))
                viewPage $current_page $count_per_page
            fi
        ;;
        C)
            current_page=$((current_page+1))
            viewPage $current_page $count_per_page
        ;;
        D) 
            if [ $current_page -gt 0 ] ; then
                current_page=$((current_page-1))
                viewPage $current_page $count_per_page
            fi
        ;;
        "q")
        break
        ;;
    esac
    if  validNum "$t"  ; then
        /bin/echo -n $t
        key="$t"
        connected=0
        while read -r -sn1 t
        do
            if  validNum "$t"  ; then
                /bin/echo -n $t
                key=$key"$t"
            fi
            if [ -z $t ] ; then
                index=$((current_page*count_per_page+key-1))
                if (( key > count_per_page || key < 1 )); then
                    echo ""
                    echo  "Wrong number !!"
                    /bin/echo -n "Enter Input: "
                    break;
                fi
                if  validNum "$index"  ; then
                    connected=1
                    echo ""
                    echo "Connect to ${names[$index]} - (${ips[$index]})"
                    echo "1 : SSH, 2 : FileZilla"
                    /bin/echo -n "Enter Input: "
                    read -r -sn1 t

                    if (( $t==2 )) ; then
                        $fileZilla "sftp://${ids[$index]}:${passwords[$index]}@${ips[$index]}:${ports[$index]}" & exit
                    else
                        sshpass -p ${passwords[$index]} ssh -o StrictHostKeyChecking=no -p ${ports[$index]} ${ids[$index]}@${ips[$index]}
                    fi
                    break
                fi
            fi
        done
        if [ $connected -eq 1 ] ; then
            break;
        fi
        
    fi
done

/bin/echo ""
/bin/echo -n "아무키나 누르세요."
read -r -sn1

 
 

결과물 화면

ssh 접속화면

 

FileZilla 접속화면

이제 도구가 준비 되었으니 hosts.properties에 관리서버들 정보만 다 입력하면
PC가 바뀌더라도 다시 입력해야되는 상황은 없어졌습니다.
그리고 서버정보를 꼭 제가 다 입력할 필요는 없죠 스크립트는 제가 짰으니 서버정보는
밑에있는 친구들에게 입력하라고 시키면 됩니다 ㅎㅎ
 

그리고 ssh.sh의 확장자를 .command로 바꿔주면 MacOS UI에서 더블클릭으로 스크립트를 실행할 수 있습니다.

 

난 윈도우PC도 사용하는데?

저는 업무용으로 맥북말고 윈도우PC도 사용을 하고 있습니다.
그래서 윈도우PC에서 사용할 스크립트도 따로 작성하였습니다.
PowerShell 스크립트로 작성하였고 윈도우에선 sshpass와 비슷한것을 찾을수가 없어
Solar-PuTTY라는 별도의 프로그램을 사용 하였습니다.
 

ssh.ps1

function Is-Numeric ($Value) {
    return $Value -match "^[\d\.]+$"
}

function View-Page() {
    [System.Console]::Clear()
    
    Write-Output "[ $($current_page + 1) Page ]"
    Write-Output "-----------------------------------------------------"
    
    for ($i = 0; $i -lt $count_per_page; $i++) {
        Write-Output "$($i + 1): $($names[$($current_page*$count_per_page+$i)]) - $($ips[$($current_page*$count_per_page+$i)])"
        
    }
    
    Write-Output "-----------------------------------------------------"
    Write-Output "←→↑↓             : move page"
    Write-Output "input number     : connect"
    Write-Output "q                : exit"
    Write-Output "-----------------------------------------------------"
    Write-Output "Enter Input: "

}

$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$sshClientPath = $scriptPath+ "\Solar-PuTTY.exe"
$fileZillaPath = "C:\Program Files\FileZilla FTP Client\filezilla.exe"
$fileName = $scriptPath + "\hosts.properties"
Write-Output "Read File : $fileName"

$names = New-Object -TypeName "System.Collections.ArrayList"
$ips = New-Object -TypeName "System.Collections.ArrayList"
$ports = New-Object -TypeName "System.Collections.ArrayList"
$ids = New-Object -TypeName "System.Collections.ArrayList"
$passwords = New-Object -TypeName "System.Collections.ArrayList"

$current_page = 0
$count_per_page = 20


foreach($line in [System.IO.File]::ReadLines($fileName))
{
    $tmp = $line.Split(":")

    $names.Add($tmp[0])
    $ips.Add($tmp[1])
    $ports.Add($tmp[2])
    $ids.Add($tmp[3])
    $passwords.Add($tmp[4])
}

View-Page

while ($true) {
    $key = [System.Console]::ReadKey($false)

    if($key.Key.ToString() -eq "UpArrow") {
        if ( $current_page -gt 0 ) {
            $current_page = $($current_page - 1)
            View-Page
        }        
    } elseif($key.Key.ToString() -eq "LeftArrow") {
        if ( $current_page -gt 0 ) {
            $current_page = $($current_page - 1)
            View-Page
        }
    } elseif($key.Key.ToString() -eq "DownArrow") {
        $current_page = $($current_page + 1)
        View-Page
    } elseif($key.Key.ToString() -eq "RightArrow") {
        $current_page = $($current_page + 1)
        View-Page
    } elseif($key.Key.ToString() -eq 'Q') {
        break
    }
    else {
        $connected = 0
        if(Is-Numeric $key.KeyChar) {
            $numKey = $key.KeyChar

            while ($true) {
                $key = [System.Console]::ReadKey($false)
                if(Is-Numeric $key.KeyChar) {
                    $numKey += $key.KeyChar
                } elseif ($key.Key.ToString() -eq "Enter") {
                    $connected = 1
                    $index = "$numKey" -as [int]
                    $index = $($current_page*$count_per_page+$index-1)
                    Write-Output "index : $index"
                    Write-Output "Connect to $($names[$index]) - $($ips[$index])"

                    Write-Output "1 : SSH, 2 : FileZilla"
                    Write-Output "Enter Input: "
                    $key = [System.Console]::ReadKey($false)
                    
                    if($key.KeyChar -eq "2") {
                       & $fileZillaPath "sftp://$($ids[$index]):$($passwords[$index])@$($ips[$index]):$($ports[$index])"
                    } else {                        
                       & $sshClientPath -h $($ips[$index]) -o $($ports[$index]) -u $($ids[$index]) -p $($passwords[$index])
                    }
                    
                    break;
                }
            }            
        }
        if($connected -eq 1) {
            break;
        }
    }
}

'프로그래밍' 카테고리의 다른 글

Java를 활용한 Issue Tracker 제작  (0) 2023.05.09
SSL 인증서 변환  (0) 2023.04.04

SSL 인증서가 적용된 사이트 관리자는 1년마다 인증서 갱신 작업을 해야 합니다.
자주 하는 일이 아니기 때문에 OpenSSL 명령어를 항상 기억하고 있진 않아
그때그때 검색을 통해 작업을 합니다.
 
그래서 제가 자주 사용하는 명령어를 모아봤습니다.
 

인증서 파일 구성

CSR 자동생성 및 NginX용으로 구매를 했기 때문에 파일 구성은 다음과 같고
NginX 서버에 적용할 때는 네모박스의 두 파일만 교체해주면 간단하게 작업이 끝납니다.
함께 동봉된 star_renaissance-code_com.zip이 인증서 원본입니다.

인증서 업체로부터 받은 전체 파일

 
인증서 원본의 압축을 풀어보면 아래와 같습니다.

인증서 원본

  • Root 인증서 1개
  • Chain 인증서 2개
  • Root와 Chain들을 합쳐놓은 Bundle 인증서 1개
  • 신청한 도메인 인증서 1개

로 구성되어 있는것을 볼 수 있습니다.
 
 

이제 이 인증서를 가지고 IIS용 PFX인증서, Tomcat용 JKS인증서를 만들어 보겠습니다.

 
 

인증서 합치기

사전 작업으로  도메인 인증서Bundle 인증서를 하나로 합쳐줍니다.
star_renaissance-code_com_cert.pem + Chain_RootCA_Bundle.crt

Linux
> cat star_renaissance-code_com_cert.pem Chain_RootCA_Bundle.crt > star_renaissance-code_com.crt

PowerShell
> cat star_renaissance-code_com_cert.pem, Chain_RootCA_Bundle.crt | Out-File -Encoding ascii -FilePath star_renaissance-code_com.crt

 

PFX 만들기

조금전에 합친 crt 파일과 밖의 폴더에 있던 key 파일을 이용하여 PKCS#12(.pfx)로 변환 합니다.

> openssl pkcs12 -export -in star_renaissance-code_com.crt -inkey renaissance-code_com_NginX_nopass_key.pem -out star_renaissance-code_com.pfx

Loading 'screen' into random state - done
Enter Export Password:
Verifying - Enter Export Password:
unable to write 'random state'

 
만들어진 PFX파일에 대하여 인증서 가져오기를 한 결과 아래와 같이
정상적으로 만들어진 것을 확인할 수 있습니다.

인증서 정보

 

PFX 인증서 확인

> openssl pkcs12 -info -in star_renaissance-code_com.pfx

Enter Import Password:
MAC Iteration 2048
MAC verified OK
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048
Certificate bag
Bag Attributes
    localKeyID: 3C 13 F9 C4 22 FC 16 11 9C C0 F2 5E FE EC 03 CF AF E4 70 4C
subject=/CN=*.?????.?????.???
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA

 

PFX -> JavaKeyStore(.jks) 변환

> keytool -importkeystore -srckeystore star_renaissance-code_com.pfx -srcstoretype pkcs12 -destkeystore star_renaissance-code_com.jks -deststoretype jks

키 저장소 star_renaissance-code_com.pfx을(를) star_renaissance-code_com.jks(으)로 임포트하는 중...
대상 키 저장소 비밀번호 입력:
새 비밀번호 다시 입력:
소스 키 저장소 비밀번호 입력:
1 별칭에 대한 항목이 성공적으로 임포트되었습니다.
임포트 명령 완료: 성공적으로 임포트된 항목은 1개, 실패하거나 취소된 항목은 0개입니다.

 

JavaKeyStore(.jks) -> PFX 변환

> keytool -importkeystore -srckeystore star_renaissance-code_com.jks -srcstoretype JKS -srcstorepass "qwer1234" -destkeystore star_renaissance-code_com2.pfx -deststoretype PKCS12 -deststorepass "pw1234"

키 저장소 star_renaissance-code_com.jks을(를) star_renaissance-code_com2.pfx(으)로 임포트하는 중...
<1>에 대한 키 비밀번호를 입력하십시오.
1 별칭에 대한 항목이 성공적으로 임포트되었습니다.
임포트 명령 완료: 성공적으로 임포트된 항목은 1개, 실패하거나 취소된 항목은 0개입니다.

 

서버 내에서 SSL 인증서 확인하기

> curl https://127.0.0.1 -kIv

* About to connect() to 127.0.0.1 port 443 (#0)
*   Trying 127.0.0.1... connected
* Connected to 127.0.0.1 (127.0.0.1) port 443 (#0)
* Initializing NSS with certpath: /etc/pki/nssdb
* warning: ignoring unsupported value (1) of ssl.verifyhost
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* Peer's certificate issuer is not recognized: 'CN=Sectigo RSA Organization Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB'
* SSL certificate verify ok.

기존에 사용하던

테일러메이드 M6 드라이버와,

타이틀리스트 915 5번우드

 

작년 8월 와이프님께서

테일러메이드 스텔스 드라이버,

테일러메이드 스텔스 3번우드

교체 해주셨습니다.

 

드라이버 샤프트는 전부터 쭈욱

TourAD IZ6S를 사용하고 있었기 때문에

스텔스 드라이버에도 기존 샤프트를 꽂아서 사용하고

(M6와 스텔스는 슬리브 호환)

우드는 스탁샤프트를 사용하고 있었습니다.

 

3번우드 스탁샤프트가 57그램 S라서

드라이버보다도 스펙이 약하지만

어려운채니까 그냥 편안하게 치자는 생각으로

샤프트교환은 안 하고 있었는데

내가 생각한 거리보다 너무 많이 나가는 경우가 종종 나오고

좌우 편차도 심하게 느껴져서

'아, 이건 내 몸이 아니라 샤프트스펙이 문제구나' 라는

자기합리화를 하기 시작했습니다.

 

샤프트 정하기

자기합리화를 끝냈으면 당연한 수순으로 샤프트 교체 프로젝트에 돌입 합니다.

교체 대상으로 점찍어둔 샤프트는 드라이버와 같은 TourAD IZ 샤프트이고

'그래도 드라이버 보다는 스펙이 높아야지' 하면서 60그램대 X 플렉스로 정했습니다.

(7S도 살짝 고민을 하긴 했는데 원인모를 거부감이 들어 대상에서 탈락)

 

 

필요물품 구매하기

샤프트 구매는 일단 와이프에게 아양떨어 허락을 받고나서

중고로 Ping슬리브가 꼽혀있는 TourAD IZ6X 드라이버 샤프트를 구입 하였습니다.

구입한 샤프트가 드라이버용 이다보니 길이가 45.25인치라서

커팅이 필요한데, 팁(헤드쪽)을 커팅하면 샤프트의 강도에 영향을 주기 때문에

버트(그립쪽)커팅을 해야겠다 라고 마음 먹었습니다.

버트 커팅을 하려면 기존 그립을 제거하고 새로 껴야하니

그립도 주문해야 하는데 그립은 또 몇그램짜리를 구매해야하나 라는 생각에

테일러메이드 홈페이지를 들어가서 제 클럽의 스펙표를 유심히 보았습니다.

테일러메이드 홈페이지 발췌

테일러메이드 스텔스 페어웨이우드 스펙표 입니다.

초록색 박스로 표시해놓은것이 제가 갖고있는 스펙입니다.

스탁샤프트인 TENSEI RED TM50의 길이가 43.25인치 이고 스윙웨이트가 D2.5로 되어 있습니다

그리고 그립은 램킨 42.5그램 짜리가 꼽혀 있네요.

위 데이터를 잘 보면 TourAD UB6S를 장착한 스펙도 있습니다. (43인치, D1.5, 47.5g)

 

그래서 그립은 아래놈으로 2개 구입 하였습니다. (나중에 드라이버 그립도 교체할 생각으로)

램킨코리아 발췌

 

작업의뢰하기

제가 원하는 스펙입니다.

길이 : 43인치 ~ 43.25 유동적이어도 됨

스윙웨이트 : D2

 

이제 모든것이 준비 되었으니 피팅을 할 차례 입니다.

당연하겠지만 골프클럽 피팅은 전문가에게 맞기는것이 좋습니다.

 

저의 경우는 개인사업자를 내고 소소하게 피팅작업을 하시는 형님이 있습니다.

연락했더니 작업실 비밀번호 알려주고 놓고가라고 하셔서

준비물들과 스펙표및 요구사항이 적힌 종이를 살포시 놓고 나왔습니다.

 

다음날..

작업을 끝낸 형님에게 연락이 와 가서보니

기존스펙, 교환스펙을 둘다 측정해서 적어두셨더라구요

이렇게 수치로 다 나와있으니 뭔가 더 믿음이 갑니다.

여기서 CPM은 샤프트 강도와 관련이 있습니다.

기존 50그람대 S flex 에서 60그람대 X flex로 교체를 하였으니

같은 무게대에서의 증가폭보다는 더 많이 올라가는것이 당연하겠죠.

 

아무튼.. 무게, 스윙웨이트, 강도, 길이 모든게 원하는대로 나왔으니

이제부터는 잘 안맞으면 채탓은 못하고 몸탓을 해야할 것 같습니다 ㅎㅎ

(제가 골프연습할때 동기부여하는 방법 입니다)

 

감사하게도 교체비용은 2만원만 받으시네요.. 더 받으셔도 될것을..

제거한 핑 슬리브는 나중에 사용하시라고 작업실에 남겨놓고

퇴장하였습니다.

 

어서 쳐보고 싶네요.

+ Recent posts