개인적으로 메모장 보다는 이 notepad++을 자주 이용한다. 과거에는 UltraEdit와 같은 다양한 텍스트 편집 도구, 특히 유료 버전들을 많이 이용했었는데, 이 notepad++를 이용하고 난 이후에는 이것만 쓴다.

문제는 Windows 초기화(포멧)후 설정을 원래대로 복구하는데 매번 고생했다.

결론 부터 이야기하면 notepad++의 모든 설정 파일은 다음 위치에서 볼 수 있다.

%AppData%\Notepad++

윈도우 탐색기(Windows Explorer)의 경로창에 넣으면 바로 들어가진다.

해당 위치의 파일들을 모두 복사해가면 된다.

 

728x90

( 지금.... 2024/03/21 기준의 글로써, 이후 패치나 다른 고객지원등을 통해 변경될 수 있음)

인터넷 등기소에서 등기부등본을 출력하려고 사이트에 접속했다.
http://www.iros.go.kr/

 

대법원 인터넷등기소

 

www.iros.go.kr

일단 여기 접속하면 다양한 ActiveX나 관련 모듈들을 설치한다. 
애초에 Internet Explorer를 쓰라고 나오긴 하는데, Chrome이나 Firefox에도 되긴한다.
veraport-g3-x64 를 설치하면 대부분 관련된 대부분은 설치되긴 한다.

그런데, 이상하게 발급, 출력 부분에서 발급하려고 "결제", 상단에 나오는 팝업에서 "열기"를 하는 순간, 
RPRTRegisterXCtrl.exe 를 실행한다고 한다. 그래서 실행해! 라고 했는데.... 반응이 없다.
계속 기다려봤는데.. 역시 아무것도 동작하지 않는다.

처음에는 내 쪽에서 설정되거나 다른 프로그램과 오류가 있는줄 알았는데... 아니였다.

문제 원인

처음에는 단순 프로그램 충돌, 가상화시스템, 네트워크 ... 뭐 등등 다양한 부분에서 접근했다. 심지어 회사에서 놀고 있는 노트북이 있어서 거기다가도 했는데 동일했다. 단순 열람이나, 전자정부문서 지갑 전송 같은데서는 아무 문제가 없는데, 유독 이 "출력", "발급"에서는 터진다.

한 2시간 정도 삽질하다가.. Event Viewer를 보는데... 메시지가...

"C:\Program Files (x86)\markany\maepscourt\rprtregisterxctrl.xgd"에 대한 활성화 컨텍스트를 생성하지 못했습니다. 
종속 어셈블리 Microsoft.VC90.MFC,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8"을(를) 찾을 수 없습니다. 
자세한 진단을 위해서는 sxstrace.exe를 사용하십시오.

....

뒷골이 싸했다.

패키징 실패. 이 프린터용 프로그램인 RPRTRegisterXCtrl.exe 패키징할 때, 이에 연관된 라이브러리를 같이 설치하지 않은 것이다. 만일 사용자가 오랫동안 포멧하지 않고 사용하면서 다양한 프로그램을 깔았다면, 분명 설치되어 있을 라이브러리 겠지만, 나 같이 깔끔하게 포멧을 하고 새로 설치해서 사용하는 사람의 경우 저 라이브러리가 없을 가능성이 높은데... 이거 패키징 한 친구는 지 컴퓨터에서 잘 된다고 넘어간듯...

해결 방법

https://learn.microsoft.com/ko-kr/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version

 

지원되는 최신 Visual C++ 재배포 가능 패키지 다운로드

이 문서에는 최신 버전의 Visual C++ 재배포 가능 패키지에 대한 다운로드 링크가 나열되어 있습니다.

learn.microsoft.com

사이트에서 Visual Studio 2008(VC++ 9.0) SP1(더 이상 지원되지 않음) 부분에 있는 x86의 9.0.30729.5677 버전을 설치해야 한다. 파일이름은 vcredist_x86.exe   (직접 다운로드 경로는 아래와 같다.)

https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x86.exe

저걸 설치하면 된다.

 

결론

일차적으로는 패키징을 잘못한게 하나.

이차적으로는 대체 보안/패치도 지원하지 않는 저 오래된 라이브러리를 아직도 쓴다는게 하나.

삼차적으로는 저 따위 보안 솔루션을 쓰는 것 자체지 않을까? 차라리 보안 PDF 파일을 보내주는게 더 나을듯.

 

728x90

기존에 Yona 를 구축해서 버전관리를 잘해오고 있는데, 문제는 알림 메일이였다.
지금까지 계속 google의 SMTP로 잘 운영해오다가, 어느 순간 google의 로그인 방식이 보안 정책에 따라, OAuth 방식이 아니면 더 이상 예전 처럼 아이디/패스워드 기반의 로그인을 지원하지 않는 것이다.
그래서 naver.com 내에 계정을 하나 파서 그 안에 있는 POP3/IMAP 기능을 활성화 했고, 거기서 제공하는 SMTP 설정 값을 이용해 Yona의 application.conf 값을 아래와 같이 수정했다.

smtp.startssl = true
smtp.host = smtp.naver.com
smtp.port = 587
smtp.auth = true
#smtp.ssl = true
smtp.password = "xxxxxxx"
smtp.domain = naver.com
smtp.user = "xxxxxxx@naver.com"

설정을 변경한 뒤 Yona를 다시 시작했는데.. 왠걸.. 아래와 같은 에러가 떨어진다.

2024-03-06 13:26:51,466 - [WARN] - from application in play-akka.actor.default-dispatcher-974 
Failed to send a notification: org.apache.commons.mail.HtmlEmail@1720365d
org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtp.naver.com:465
	at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1410)
	at org.apache.commons.mail.Email.send(Email.java:1437)
	at info.schleichardt.play2.mailplugin.MailPlugin$$anonfun$6.apply(MailPlugin.scala:60)
	at info.schleichardt.play2.mailplugin.MailPlugin$$anonfun$6.apply(MailPlugin.scala:54)
	at info.schleichardt.play2.mailplugin.MailPlugin.send(MailPlugin.scala:68)
	at info.schleichardt.play2.mailplugin.api.Mailer$.send(Mailer.scala:8)
	at info.schleichardt.play2.mailplugin.Mailer.send(Mailer.java:15)
	at controllers.ProjectApp.sendTransferRequestMail(ProjectApp.java:775)
	at controllers.ProjectApp.transferProject(ProjectApp.java:634)
	at Routes$$anonfun$routes$1$$anonfun$applyOrElse$191$$anonfun$apply$191.apply(routes_routing.scala:3708)
	at Routes$$anonfun$routes$1$$anonfun$applyOrElse$191$$anonfun$apply$191.apply(routes_routing.scala:3708)
	at play.core.Router$HandlerInvokerFactory$$anon$4.resultCall(Router.scala:264)
	at play.core.Router$HandlerInvokerFactory$JavaActionInvokerFactory$$anon$15$$anon$1.invocation(Router.scala:255)
	at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:55)
	at Global$2.call(Global.java:274)
	at actions.AnonymousCheckAction.call(AnonymousCheckAction.java:57)
	at actions.IsAllowedAction.call(IsAllowedAction.java:68)
	at actions.AbstractProjectCheckAction.call(AbstractProjectCheckAction.java:93)
	at play.db.ebean.TransactionalAction$1.call(TransactionalAction.java:21)
	at play.db.ebean.TransactionalAction$1.call(TransactionalAction.java:18)
	at com.avaje.ebeaninternal.server.core.DefaultServer.execute(DefaultServer.java:715)
	at com.avaje.ebeaninternal.server.core.DefaultServer.execute(DefaultServer.java:709)
	at com.avaje.ebean.Ebean.execute(Ebean.java:1264)
	at play.db.ebean.TransactionalAction.call(TransactionalAction.java:18)
	at play.core.j.JavaAction$$anonfun$11.apply(JavaAction.scala:82)
	at play.core.j.JavaAction$$anonfun$11.apply(JavaAction.scala:82)
	at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
	at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
	at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:40)
	at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:46)
	at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:32)
	at scala.concurrent.impl.Future$.apply(Future.scala:31)
	at scala.concurrent.Future$.apply(Future.scala:485)
	at play.core.j.JavaAction$class.apply(JavaAction.scala:82)
	at play.core.Router$HandlerInvokerFactory$JavaActionInvokerFactory$$anon$15$$anon$1.apply(Router.scala:252)
	at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:130)
	at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:130)
	at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
	at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:129)
	at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:128)
	at scala.Option.map(Option.scala:145)
	at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:128)
	at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:121)
	at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:483)
	at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:483)
	at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:519)
	at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:519)
	at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:496)
	at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:496)
	at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
	at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
	at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
	at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
	at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
	at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
	at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
	at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: javax.mail.MessagingException: Could not connect to SMTP host: smtp.naver.com, port: 465;
  nested exception is:
	javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1972)
	at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:642)
	at javax.mail.Service.connect(Service.java:317)
	at javax.mail.Service.connect(Service.java:176)
	at javax.mail.Service.connect(Service.java:125)
	at javax.mail.Transport.send0(Transport.java:194)
	at javax.mail.Transport.send(Transport.java:124)
	at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1400)
	... 56 more
Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:171)
	at sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:103)
	at sun.security.ssl.TransportContext.kickstart(TransportContext.java:227)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:433)
	at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:548)
	at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:352)
	at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:207)
	at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1938)
	... 63 more

그런데 에러를 찬찬히 살펴보니 아래와 같은 문장이 눈에 딱 띄었다.

Caused by: javax.mail.MessagingException: Could not connect to SMTP host: smtp.naver.com, port: 465;
  nested exception is:
	javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1972)
	at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:642)

이상해서, 과거 Yona의 Issue 창을 뒤져보니, 답글 중에 아래와 같은 답변을 발견했다.

https://github.com/yona-projects/yona/issues/746

 

이메일 발송관련 · Issue #746 · yona-projects/yona

안녕하세요, 프로젝트 이관 중에 확인 메일이 안와서 이상하다 싶어서 확인하니까, 현재 메일에서 계속 오류가 발생합니다. 먼저 제쪽 환경은 아래와 같습니다. [OS] Ubuntu - 16.04.7 LTS (Xenial Xerus) [J

github.com

저 내용에서 중요한 건 Stackoverflow 링크 안의 답글인데, 답글 중에,

JRE_HOME/lib/security/java.security:

파일 안에 있는

jdk.tls.disabledAlgorithms

값을 수정하면 된다는 것이다.

해결 방법

일단, 지금 운영 중인 서버의 Java 파일 중에 java.security를 찾는다.
리눅스를 기준으로 이야기하면 다음과 같이 넣으면 찾을 수 있다.

find | grep java.security

root 권한이 있어야 수정되므로 sudo 로 해당 파일을 열어준다.

그리고 jdk.tls 를 검색하면 아래와 같은 내용을 볼 수 있다.

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves

저 항목 중에 SSLv3, TLSv1, TLSv1.1 을 삭제하고 저장하도록 한다.

그러면 해결된다.

728x90

다른 곳에서 전체 백업된 SQL을 받아 데이터베이스를 생성했는데, 생성했더니, 데이터베이스의 Data Collate가 "Latin1_General_CI_AS"로 설정되어 있었다. 그래서 간신히 데이터베이스의 설정 값을 바꾸어 "Korean_Wansung_CI_AS"으로 바꾸긴 했다. 그런데 Query를 실행하니까, 웬걸...컬럼들은 여전히 "Latin1_General_CI_AS" 로 되어 있었고, 새로 만든 테이블 내의 값들과 비교하려는데 자꾸 다음과 같은 에러메시지를 뱉어됐다.

Cannot resolve the collation conflict between "Korean_Wansung_CI_AS" and "Latin1_General_CI_AS" in the equal to operation.

데이블 디자이너, 그러니까, 테이블 수정에 들어가 varchar 컬럼마다 데이터 정렬(Data Collate) 값을 바꾸면 되긴 하는데, 이 많은 테이블의 또, 그 컬럼들에 들어가 수정하려니 깝깝했다.

그래서 구글을 통해서 이런 저런 검색한 결과, stackOverflow에서 찾았다.

https://stackoverflow.com/questions/18122773/change-collations-of-all-columns-of-all-tables-in-sql-server

 

Change collations of all columns of all tables in SQL Server

I imported a database with some data to compare with another database. The target database has collation Latin1_General_CI_AS and the source database has SQL_Latin1_General_CP1_CI_AS. I did change ...

stackoverflow.com

아래의 코드 값에서 @collate값만 Korean_Wansung_CI_AS로 변경하고, 수정할 데이터베이스의 쿼리창을 열고 실행했다.

DECLARE @collate nvarchar(100);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);

SET @collate = 'Korean_Wansung_CI_AS';

DECLARE local_table_cursor CURSOR FOR

SELECT [name]
FROM sysobjects
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1

OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE local_change_cursor CURSOR FOR

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
        , c.name column_name
        , t.Name data_type
        , c.max_length
        , c.column_id
    FROM sys.columns c
    JOIN sys.types t ON c.system_type_id = t.system_type_id
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id = OBJECT_ID(@table)
    ORDER BY c.column_id

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id

    WHILE @@FETCH_STATUS = 0
    BEGIN

        IF (@max_length = -1) OR (@max_length > 4000) SET @max_length = 4000;

        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' + @table + ' ALTER COLUMN ' + @column_name + ' ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) + ') COLLATE ' + @collate
            PRINT @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR: Some index or constraint rely on the column' + @column_name + '. No conversion possible.'
          PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @row_id, @column_name, @data_type, @max_length, @column_id

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor

    FETCH NEXT FROM local_table_cursor
    INTO @table

END

CLOSE local_table_cursor
DEALLOCATE local_table_cursor

GO

지금 모든 데이터베이스의 모든 테이블의 컬럼들을 한번에 수정할 수 있었다.

다행다행...

728x90

현재 개인 개발 도구를 이용해서 작업 중인데, 네트워크 IP가 미묘하게 겹쳐 업무를 할 때마다 Lan 선을 뽑았다 꼈다를 반복해왔다.

개발 PC에 랜카드를 두개 붙여서 한 쪽은 192.168.30.200 으로 설정해서, 인터넷이나 버전관리 서버에 접속해서 Commit을 했고, 다른 한쪽에는 192.168.0.105 으로 설정한 뒤, Lab 실에 있는 장비와 연결을 했다.

인터넷 하면서 Lab 실 장비를 건드릴 때는 문제가 없는데, 딱! 버전관리 서버를 손대자 문제가 터져나갔다.
그 이유가 192.168.0.x 대역을 버전관리 서버와 Lab실이 동시에 이용해서 이다.
만일 버전관리 서버와 연결하고 싶으면 Lab 실과 연결된 네트워크 랜선을 떼어야 하고,
다시 Lab 장비를 손대려면 다시 붙여야 한다. 만일 Lab 실 장비 손 보다가, 소스 수정할 내용을 Commit을 하고 싶으면 다시 뗀것을 붙여야 했다.

한 두번은 하겠는데, Commit 되는 횟수가 늘어나면 늘어날 수록 점점 귀차니즘이 돌발했다.

그래서 방법을 바꿨다. 그래서 route 라는 명령을 찾게 되었다.

route는 현재 네트워크를 호출할 때 어디로 연결해서 처리할지를 나타내고 수정하는 도구다.
먼저 관리자 권한으로 터미널(관리자)를 연다.

그리고 다음과 같이 명령을 입력하면 현재 설정된 라우팅 정보가 보인다.

저 라우팅 테이블의 내용만 보면, 0.0.0.0 즉 모든 연결은 192.168.30.200 인터페이스에 있는 192.168.30.1 게이트웨이로 보낸다는 의미다. 그리고 192.168.0.0 즉 192.168.0.x 로 된 모든 연결은 192.168.0.105 인터페이스로 보낸다는 의미다.

이걸 보고 해석을 하면, 192.168.30.63  하면, 192.168.30.200 인터페이스를 통해 패킷을 보내고, 192.168.0.3 하면, 192.168.0.105 인터페이스를 통해 패킷을 보낸다.

문제는 192.168.0.2 를 했을 때도, 192.168.0.105를 통해 내보낸다.
내 버전관리 서버는 192.168.30.200을 통해서 VPN을 거쳐 접속을 해야 하는데도 말이다.

그래서 방법을 찾은게 route 명령을 통해 아래와 같이 입력하는 것이다.

route add 192.168.0.2 mask 255.255.255.255 192.168.30.200 -p

192.168.0.2 의 연결에서 Subnet mask를 255.255.255.255를 하면, 딱 저 IP를 입력할 때, 192.168.30.200 인터페이스로 패킷을 보내라는 명령이다. 일단 Subnet mask 부분에서 이해의 폭을 너무 많이 요구하긴 하지만, 최소한 맨 앞의 값과 255.255.255.255 가 붙으면 1개의 IP 라고 읽자.
192.168.0.3 이나 192.168.0.100 같은 경우에는 라우팅 테이블 상에 있는 192.168.0.0 / 255.255.255.0 에 걸려 192.168.0.105 인터페이스로 패킷을 보내지만,
192.168.0.2 는 192.168.0.2 / 255.255.255.255 에 걸려서 192.168.30.200 인터페이스로 패킷을 보낸다고 이해하면 된다.
여기서 인터페이스 라는게 랜카드를 의미하고, 그 랜카드에 설정된 IP 주소라고 읽으면 된다.

맨 마지막의 -p는 영구 연결이라고 해서 네트워크가 리셋되도 일단 살아 있게 만들어 준거다. 없으면 나중에 네트워크 리셋되는 순간 위의 명령만 다시 넣어주면 된다.

나중에 vpn을 통해 이용해야 할 서버의 IP 192.168.0.88 라는게 생기고, 지금과 같이 하고 싶다면,  위의 명령을 이용해서 만들어 줄 수 있다.

route add 192.168.0.88 mask 255.255.255.255 192.168.30.200 -p

 

 

728x90

2022년이니까 햇수로는 2년, 만으로는 1년 반정도 전에 구매.

당시에는 나름 뭐 내적 갈등과 합리화를 통해서 받아드리긴 했는데,
가격이 참 살벌하네;;;;;

딱 10,000 Km 찍어보고 다시 정리해보자

728x90

이게 지금 내가 가진 제품인지 더 확인을 해봐야 겠지만...

도면이 Raddit에 있어서 한번 퍼왔다.
https://www.reddit.com/r/overclocking/comments/r2um0w/default_thermal_pad_thickness_for_sapphire_radeon/

메모리 쪽이 0.75 mm 이고,
파워 쪽이 1.0 mm 인 것 같다.

0.15 쪽은 써멀 구리스로 하면 되니까..

내일 써멀구리스와 써멀패드를 모두 모아와서 분해해 봐야겠다.

728x90

1인 개발자나 스스로 후원자 하면서 세월아 내월아 해도 상관없는 경우를 제외하고, 일감을 받아 업무를 수행하고 돈을 받아가는 형태로 업무를 진행하고 있다면 좀 고려해주었으면 하는 게 있다.


바로 신뢰도다. 
조금은 많이 뭉그뜨려서 표현한 부분이긴 한데, 자기 자신의 속도에 대한 이해도와 현재 업무에 대한 전체적인 파악 및 장악력 같은 내용을 의미한다.
예를 들면, 현재 프로젝트에서 특정 모듈을 개발하는 업무를 받았다고 치자. 여기서 PM 혹은 PL은 얼마나의 시간이 걸릴지를 묻곤 한다. 여기서 그 답을 줄 수 있느냐 없느냐는 부분이다. 물론 성격에 따라 정확한 수치가 아니면 제시할 수 없다고 하는 완벽주의(?)를 가진 분도 있긴 하지만, 그런 부분을 차치하고, 대략적인 수치를 떠올릴 수 있냐 없느냐다. 
이런 대략적인 수치를 뽑으려면 2가지가 요구된다. 


그 하나가 자신의 개발 속도다. 
특정 과제를 해결하는 데 걸리는데 보통 며칠이 걸리는지, 그 과제의 난이도는 어떤지 등에 대해서 기준점을 확실히 하는 것이다. 그래서 특정 과제, 유사 과제 등이 제시되었을 때 어느 정도의 기간 내에 개발할 수 있는지를 곱셈이든, 덧셈이든 해서 값을 도출할 수 있게 된다.

그리고 다른 하나가 주어진 과제에 대한 장악력이다. 
왜 내가 이 부분을 만들어야 하고 -오해하지 말아야 할 부분이 할지 말지를 알기 위한 게 아니다. 반드시 해야 한다. 다만 이렇게 만들어지는 게 어떻게 이용되고 활용되어야 하는지를 의미한다. - , 전체 프로젝트에 어느 부분에 해당하고 어느 정도의 영향력이 있는지 등을 이해하는 능력이다. 하지만 이런 능력은 해당 업무 도메인에 대한 경험치와 비례하기 때문에, 초보 개발자에게 요구하기엔 무리가 있긴 하다. 하지만 이 부분에 대한 대응 가능 여부에서  자신이 초급인지 중급인지 고급인지를 나누게 된다. 

이 업계에서 20여 년간 지내보면서 다양한 동료와 일을 해보면서 느낀 점은 저 부분에 대해서 고민하는지 안하고 피동적으로만 일하는지에 따라 다른 길로 나아간다. 때로는 상급자로, 때로는 금전적 보상으로, 때로는 인정으로 보상을 받으며 일하는지, 아니면 그저 잠깐 인력 지원 레벨에서 끝나 이곳 저곳을 전전하다 결국 적응 실패로 다른 직업으로 전환하거나, 마지못해 일하는 모습만으로 무시 혹은 평가절하 신세를 면치 못하는 모습에 실망하는 모습을 여럿 본 것 같다.

시킨 것만 하고, 미련하게 앞서 생각하다 깨지고 나댄다고 혼날 바엔 조용히 할 일만 하고 따박 따박 월급 받으면서 사는게 제일이야.. 라고 자신있게 말하는 분도 보지만, 결국 활동시기가 저무는 40대 즈음 자신이 해온 일을 쭉 돌아보고 나면 대개는 후회한다고 생각한다.

만일 아직 20대고 30대라면 저 부분에 대해서 고민해보자.
상급자가 겁나게 까칠하거나, 되먹지 않다면 굳이 나대가며 할 필요까지는 없지만, 스스로 계산해보고, 정말 그런지 안그런지를 조용하게 검증해보면서 기준을 잘 세워본다면 상급자로 올라가거나 다른 곳으로 이직하면서 새롭게 적용할 때, 준비된 개발자로 거듭나지 않을까 생각한다.

728x90

+ Recent posts

728x90