MacOS 하이시에라 root 로그인 겸 취약점

어느 OS던 보안에 자유로울 수 없다. 이건 당연하다.
그래서 각자 나름의 보안 정책으로 OS의 보안을 책임진다.

윈도우를 예를 들면,
Administrator 계정은 윈도우 설치 시 비활성화한다. (기본값 User, 튜닝으로 자동 활성화는 가능, 서버 제품군은 제외)
윈도우는 “비번 없음” 과 “비활성화” 속성이 다름에 유의하라.
그리고 어떤 계정이던 간에 비밀번호를 설정하지 않으면 원격 데스크톱 접속을 막는다.
그리고 UAC.

리눅스와 맥이야 UAC 비슷하게 시스템을 건드리는 작업이 발견되면 인증을 요구한다.
요즘 리눅스는 root 비밀번호가 없다. 비밀번호가 없다면 그 계정은 비활성화나 다름없는 것이다.
대신에 sudo를 통해 root 행세를 할 수 있고, 필요시 sudo passwd -u root 명령어로 비번을 바꿈으로 인해 root 계정 활성화는 가능하다.

대충 이런 식이다.

근데… 맥. 그것도 최신 버전인 하이 시에라에서는…
root 비번이 없는데도 불구하고 활성화가 가능한 어이 상실하는 취약점이 발견됐다.

방법은 이렇다.

설정(Preferences)에 들어간 뒤, 아무 설정이나 간다. 계정 관련 설정이면 접근이 더 쉬울 것이다.
그리고, 우측 하단 자물쇠가 있는데 그 아이콘을 누른다.

설정

그리고 사용자엔 root 입력한 뒤, 비번은 입력하지 않고 승인(Unlock) 버튼을 누르면 된다.
물론 한번에 안된다. 여러번 하면 된다. 여러번.

그러면 로그인 성공한 것처럼 인증 창이 닫히면서 자물쇠가 풀린다.

자. 이제 당신의 맥은 좆됐다는 마음가짐으로 임해야 한다.

이제 이로 인해 당신의 맥의 잠재적인 위험성이 뭐가 있을까?

  • 만약 당신의 맥을 원격으로 ssh 명령어를 통해 접근할 경우 비번 없이 root에 접근할 수 있다.
  • ssh 뿐만이겠나? VNC 등 원격으로 접근 가능한 모든 수단이 털릴텐데.

뭐 대충 설명해도 위험성은 충분히 인지했으리라 믿는다. 공중 WiFi 들어가는 순간 니 맥은 공공재가 되는 것이다.

그렇다고 그걸 막는 방법이 없는 건 아니다.
가장 간단한 방법은 우분투에 root 비번 바꿨던 것처럼 명령어를 이용해 바꾸는 것이다.
터미널 열고,
sudo passwd -u root
그리고 원하는 강력한 비번을 입력하면 조치는 끗. 제발 특문까지 들어간 강력한 비번 써라. 제발이다.

아래는 간단한 root 인증여부를 확인하는 스크립트이다. 대충 UI 자동화 스크립트라고 보면 되겠다.
osascript -e 'do shell script "id" with administrator privileges user name "root" password ""'

이 문제는 하이 시에라에서만 발생한 문제이고 수정 사항이며, 하위 버전은 신경 안 써도 된다.
당연히 발견자는 애플에게 보고했고, 이제 애플의 응답만 남았다. 왜냐면 이건 한국시각으로 글을 최초로 쓴 날 새벽에 발견한 취약점이기 때문이다.

끗.

composite / 2017년 11월 29일 / Piss Development / 0 Comments

Windows 10/Server 2016 이상에서 원격 액세스 및 라우터 없이 NAT 사용하기

보통 윈도우 환경에서 공유기 같은 환경을 구성하기 위해서 NAT 소프트웨어나, 또는 서버의 경우 원격 액세스 및 라우터 기능을 설치한다.
윈도우 10부터, 또는 서버 2016 부터, 이제 원격 엑세스 기능이 없어도 NAT 기능을 제공하는 powershell cmdlet 을 제공한다.
바로 NetNat 모듈이다.

https://docs.microsoft.com/en-us/powershell/module/netnat/?view=win10-ps

모듈 이름 그대로 NAT 환경을 제공한다. 이로 인한 이점은 아래와 같다.

  • 윈도우 10에서 사용 가능. 특히 원격 액세스 및 라우터 없어도 환경설정 가능
  • 위 기능으로 바로 Hyper-V 내부 네트워크 구성에다가 인터넷 연결이 가능
  • 심지어 여러 NAT 구성 가능

기능상 이점으로 주로 Hyper-V 환경을 구축할 때 많이 이용한다.
사용 방법을 알아보자.

인터페이스 구축

실제 랜카드

공유로 사용할 랜카드에 원하는 게이트웨이 IP를 설정하면 된다. 예를 들면 IP는 192.168.0.1 넷마스크 255.255.255.0 끝.
DNS는 원하면 구축하고 싫으면 안하면 된다. 비워도 어자피 ISP에서 제공하는 DNS 물려받게 되어 있다.
그냥 파워쉘로도 당연히 IP 부여가 가능하다. 자세한 설명은 아래 섹션 참고하자.

New-NetIPAddress –IPAddress 192.168.0.1 -PrefixLength 24 -InterfaceAlias "공유로 쓸 네트워크 이름"

Hyper-V

주로 Hyper-V 환경을 예시로 들도록 하겠다. 준비물은 Powershell 관리자 권한이 부여된 콘솔 창을 띄우기만 하면 준비 끝.
Hyper-V 관리자에서 가상 스위치 관리자를 통해 내부 네트워크에 원하는 이름으로 생성한 뒤, 네트워크 및 공유 센터 > 어댑터 변경에서 실제 랜카드처럼 생성한 Hyper-V 내부 내트워크의 IP를 원하는 게이트웨이 IP로 설정해도 되고, powershell 로 가상 내부 내트워크를 생성한 뒤 바로 IP 부여가 가능하다.

먼저, Hyper-V 가상 스위치 중 내부 네트워크 드라이버를 하나 생성한다.

New-VMSwitch –SwitchName "원하는이름" –SwitchType Internal

실행 후 vEthernet (원하는이름) 이런 식으로 명명된 가상 네트워크가 인터페이스가 생성될 것이다.
그다음 생성한 인터페이스의 IP를 부여한다. IP는 예시를 든 것이므로 원하는 IP 대역으로 수정하도록 한다.
PrefixLength 는 CIDR 마스킹 넘버로 24는 255.255.255.0을 가리킨다. 이것도 상황에 따라 원할 경우 변경할 수 있다.

New-NetIPAddress –IPAddress 192.168.0.1 -PrefixLength 24 -InterfaceAlias "vEthernet (원하는이름)"

사실 UI에서 네트워크 및 공유 센터 > 어댑터 변경 을 통해 변경해도 지장 하나도 없다.

NAT 환경 구성

이제 본격적으로 NAT를 구성하도록 하겠다.
라고 하지만 사실 별거 없다. 이제 파워쉘을 준비했으면 한줄 추가하면 끝.
마지막 InternalIPInterfaceAddressPrefix 인자에서 마스킹 IP를 입력하면 되는데,
예를 들어 192.168.0.1 넷마스크 255.255.255.0 설정했으면 192.168.0.0/24 이렇게 입력하면 된다.
원하는공유명칭 에 원하는 공유 식별자를 입력하면 되는데, 삭제 시 적어두었던 식별자를 통해 삭제할 수 있다.

New-NetNat –Name 원하는공유명칭 –InternalIPInterfaceAddressPrefix 192.168.0.0/24

끝이다. 허무할 정도로 간단하게 NAT 설정은 끝났고 공유기처럼 환경 구성하는 방법은 준비가 완료된 것이다.

참고로 삭제는 아래와 같다.

Remove-NetNat –Name 원하는공유명칭

포트 포워딩

만약 가상 컴퓨터의 특정 포트를 외부에서 접속하거나, 지금 윈도우 컴퓨터로 연결된 하위 네트워크에 있는 서비스 포트에 외부로 접속하고 싶다면,
물론 안전하게 VPN 구축해서 서비스하는 것을 추천하지만, 필요할 경우 포트포워딩도 추가 및 관리가 가능하다.
내부 공유 컴퓨터에서 80번 포트를 통해 웹 서비스하고 있는 걸 외부에서 82번 포트를 통해 접속하고자 할 경우를 예를 들어 작성하도록 하겠다.

Add-NetNatStaticMapping -NatName "원하는포트포워드명" -Protocol TCP -ExternalIPAddress 0.0.0.0 -InternalIPAddress 192.168.0.2 -InternalPort 80 -ExternalPort 82

그렇다. InternalPort 인자에 내부 공유 컴퓨터가 서비스하는 포트, ExternalPort 인자에 외부에서 접속할 포트를 입력하면 된다.
그리고, Protocol 이야 TCP, UDP 등 일반적인 인터페이스일 테고,
ExternalIPAddress 인자에 외부에서 허용할 IP 대역을 입력하는데, 0.0.0.0 이면 모든 외부 접속이 허용된다고 보면 된다.
그리고 InternalIPAddress 인자에다가 내부 컴퓨터나 가상컴 IP를 입력하면 된다.

반대로 삭제하고자 할 경우 아래처럼 하면 된다.

Remove-NetNatStaticMapping -NatName "원하는포트포워드명"

DHCP는?

만약 윈도우 10이면, 기능 없다. 외부 프로그램 아니면 포기하는게 편하다.
그리고 윈도우 서버다? 그러면 할 수 없이 DHCP 서버를 깔아야 한다.
윈도우 서버의 DHCP 서버 사용 방법은 직접 검색하거나 도움말 보거나 하면 되고,
윈도우 10이면, 몇가지 도구와 방법이 제공되는데, 링크 가서 알아보면 되겠다.

  1. DHCP Server for Windows
  2. TFTP32 – 주로 네트워크 부팅 서버 구축에 많이 사용되는데 DHCP도 제공한다.
  3. isc-dhcp-server DHCP 서버 설치
    윈도우 우분투 서브시스템 이용, 완전한 서버를 유지하도록 사용하기 위해서는 내 글 참고.

이상 끗.

참고

NetNat – cmdlet – MSDN
SET UP A HYPER-V VIRTUAL SWITCH USING A NAT NETWORK

composite / 2017년 11월 23일 / Piss Development / 0 Comments

오라클 12C의 유용한 배열 처리기능

현재 내가 있는 프로젝트는 오라클 12c를 쓰고 있다.
하지만 치매걸린 DBA는 오라클 8i 시절의 기술을 요구한다.
예를 들면, ANSI JOIN 쓰지 말고 오라클 전용 JOIN 문 작성, 가능한 단일 쿼리로 모두 해결하라 등…
오라클이 그렇게 ANSI JOIN 써라 써라 해도 치매걸린 새끼들은 한국 IT의 하느님 오라클 말도 씹고 그러는데 뭐.

이럴 거면 시발 8i를 깔지 뭐하러 비싸게 12c 구축하고 지랄이야.
하긴 10g 이하는 더이상 판매도 하지 않는데 뭐…

뭐 다른 건 모르겠고, 한가지 국내 오라클 개발자들이 구미가 당길만한 새로운 기능을 소개하고자 글을 쓴다.
12c 나온지 좀 됐긴 하지만, 12c 구축한 곳 치고는 12c의 혜택을 보는 프로젝트는… 절래절래 할 것이다.
당장 내가 소속된 프로젝트부터 2000년대부터 치매걸린 아키새끼들이 프로젝트 설계했는데 뭘 더 바라겠냐만은…

본문으로 들어가서, 오라클의 SQL에서는 TABLE이라는 함수가 있다.
다들 알다시피, 테이블 함수를 테이블로 이끌기 위해 많이들 쓸 것이다.

SELECT * FROM TABLE(MY_TABLE_FUNC('FOO'))

하지만 그 뿐. 한계가 많았는데, 먼저 배열 타입(TABLE OF, VARRAY()) 조차도 지원 안한다. 테이블 함수와 외부 테이블 등을 지원한다.
예를 들면, 11g 까지는 이렇게 쿼리 짜면 안돌아간다.

CREATE OR REPLACE TYPE emp_typ IS OBJECT (
   emp_name VARCHAR2(16);
   emp_rank NUMBER(1);
);
CREATE OR REPLACE TYPE emp_arr IS TABLE OF my_texts;
/
DECLARE

  my_emp emp_arr;

BEGIN

  SELECT emp_name, emp_rank
  BULK COLLECT INTO my_emp
  FROM emp
  WHERE emp_rank < 10;

  FOR my_row IN (
    SELECT * FROM TABLE(my_emp)
  ) LOOP

    DBMS_OUTPUT.PUT_LINE(my_row.emp_name);

  END LOOP;

END;

테스트는 안해봤지만, 문법에 문제가 없다 해도 “cannot access rows from a non-nested table” 오류가 뜰 것이다.
이제 12c부터는 배열이 지원된다. CREATE TYPE 문을 통해 선언한 배열은 당연히 지원되고, 심지어 CREATE PACKAGE 안에 있는 배열까지 지원한다.
백문이 불여일견, 예제를 보자.

CREATE OR REPLACE PACKAGE test_api AS
  TYPE t_row IS RECORD (
    empno NUMBER(4),
    ename VARCHAR2(10)
  );

  TYPE t_tab IS TABLE OF t_row
    INDEX BY BINARY_INTEGER;

  PROCEDURE test1 (l_tab1 test_api.t_tab);
END;
/

CREATE OR REPLACE PACKAGE BODY test_api AS

  PROCEDURE test1 (l_tab1 test_api.t_tab) IS
  BEGIN
    DBMS_OUTPUT.put_line('Loop Through Collection');
    FOR cur_rec IN (SELECT *
                    FROM   TABLE(l_tab1))
    LOOP
      DBMS_OUTPUT.put_line(cur_rec.empno || ' : ' || cur_rec.ename);
    END LOOP;
  END;

END;
/


declare

tt test_api.t_tab;

begin

select 1,'a'
bulk collect into tt
from dual;

test_api.test1(tt);

end;

안타깝게도 SQLFIDDLE은 아직 오라클 11g라 테스트를 돌려볼 수 없다.
대신 오라클에서 교육 용도로 무료로 오라클 실행환경을 제공하는 Oracle Live SQL 에서 테스트 가능하다.
어찌저찌 12c에서 실행하면 잘 되는데, TABLE(l_tab1) 부분을 주목하자.
엄연히 패키지 내에 선언한 배열이고, 그 배열은 심지어 RECORD 형식이다.
보통 RECORD 형식은 PL/SQL 전용 문이기 때문에 SQL 쿼리문에서는 절대 안돌아가는 게 정석이다. 11g까지는.
하지만 패키지에 한해 RECORD 형식도 SELECT 문 같은 쿼리문이 지원되니 참 편하지 아니할 수가 없다.

하지만 이 기능도 한계가 있다. SQLPL/SQL 문은 컨텍스트가 틀리다.
당연히 데이터베이스에서 선언해야 쿼리가 돌아가는 특성상,
인라인 형식(익명 블록 내 DECLARE)에서 선언한 배열은 지원하지 않는다. 물론 거기서 선언한 RECORD 문은 말할 것도 없고.
패키지의 경우에서는 PACKAGE BODY 문에서 선언한 배열이나 RECORD 형식에서 선언하면 지원하지 않는다.
이들 모두 “cannot access rows from a non-nested table” 오류가 뜰 것이다.
보통 개발자들에게 TYPE 권한을 잘 안열고, 프로시저, 함수, 패키지에 한해 권한을 어느정도 오픈하는 환경이기 때문에, 12c가 구축된 환경에서는
쿼리를 짜는데 있어서 부담이 덜할 수 있는 좋은 기능이다.

뭐 MSSQL의 테이블 변수 기능에 흠뻑 젖은 개발자라면 여전히 불편한 건 매한가지다.

끗.

참고

composite / 2017년 11월 10일 / Piss Development / 0 Comments

우분투 17.10 이상에서 IP 설정하기

우분투 17.10부터는 여태까지 우리가 쓰던 NetworkManager 에서 netplan 이 기본값으로 변경됐다.
근데 한국에서 몇몇 리눅스 진영에서 “우분투 17.10 부터 netplan으로 바꾼다더라” 외에는 아무런 정보가 없다.

하긴… 신문물을 거부하는 김치새끼들이 뭐 그렇지 뭐. 그러면서 iOS 운영체제 알파만 나와도 하악하악…

어쨌든, 어쩌다 보니 깐 사람이던 쓰고 싶어서 깔던 뭐 어쩌던 우분투 17.10 환경에서 IP 설정하는 법을 지금부터 싸지르도록 하겠다.

우분투에서 네트워크 관리가 재밌게 변했는데, 사용자가 netplan을 통해 네트워크를 설정하면, netplan은 우리가 썼던 NetworkManager 에 설정을 자동 적용하여 네트워크를 관리하는 그런 도구다.
이는 영문이지만 우분투 위키 에 소개되어 있다.

이 도구는 설정 파일이 파이썬이나 루비 개발자를 제외한 한국인에게 좀 생소한 형식으로 관리를 하는데, 바로 YAML 형식으로 관리한다는 것이다.
뭐… 우리가 많이 쓰는 텍스트 교환 형식이 XML, JSON, 그리고 자바에서 많이 쓰는 Properties와 행 단위로 설정하는 그런 것들인데…
설명하기 귀찮으니 기냥 위키백과 가서 봐라.

설정 파일은 대충 이렇게 생겼다.

# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
 version: 2
 renderer: networkd
 ethernets:
   ens33:
     dhcp4: yes
     dhcp6: yes

여기서 뭔자 이상한 문자가 있는데, 우분투 17.10부터 이더넷 식별자가 우리가 알던 ethX 방식이 아닌 ensXYZ 방식으로 바뀌었다.
ifconfig 로 볼 수 있으며, 만약 도커 때문에 가려져서 보기 어려우면 ipconfig | grep : 치면 IPv6 항목과 함께 네트워크 식별자들이 나올 것이다.
당연하겠지만 자동 IP 할당이 기본값이다. 이를 담당하는 게 IPv4의 경우 dhcp4, IPv6의 경우 dhcp6 키로 관리한다. 간단하게 쓸거면 yes, 아니면 no로 설정한다.

그렇다면 수동으로 IP를 관리하고자 한다면 어떻게 변경해야 하나?
바로 생소해 보이는 이더넷 식별자 아래 몇가지 사항을 추가하면 된다.
상하위 구분을 공백 수로 구분하기 때문에 공백으로 고생하는 파이썬 개발자들에겐 익숙할 것이다.

# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
 version: 2
 renderer: networkd
 ethernets:
   ens33:
     dhcp4: no
     dhcp6: no
     addresses: [192.168.1.2/24]
     gateway4: 192.168.1.1
     nameservers:
       addresses: [8.8.8.8,8.8.4.4]

여기서 3가지 속성이 추가되는데, addresses, gateway4, nameservers 이다.
뭐 별거 없다. 순서대로 할당할 IP주소, IPv4 방식의 게이트웨이 주소, 그리고 DNS 서버다.
DNS 서버에 하위 항목인 addresses 속성을 추가하여 대괄호로 감싼 쉼표(,) 구분으로 IP를 부여하면 된다.
눈치 깠다면 알겠지만 당연히 IPv6 방식의 게이트웨이 설정은 gateway6이다.
그렇다면 IPv6 방식으로 세팅하려면? 그냥 배열 쳐넣듯이 멀티IP 추가하여 IPv4 IPv6 이렇게 넣는다.
아가리 벌려라 예제 날아온다!

# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
 version: 2
 renderer: networkd
 ethernets:
   ens33:
     dhcp4: no
     dhcp6: no
     addresses: [192.168.1.2/24, '2001:1::2/64']
     gateway4: 192.168.1.1
     nameservers:
       addresses: [8.8.8.8,8.8.4.4]

자 이제 한가지 문제가 남았다. 서브넷 마스크는 어디로 간 것일까?
안타깝게도 서브넷 마스크 속성은 여기에 없다. 하지만, 할당 IP주소 뒤에 붙는 저 익숙치 않은 /24를 주목하자.
아는 사람은 알 것이다. 바로 저건 CIDR, 사이더라고 발음하는 마스킹 넘버다.
위 링크로 들어가면 슬래시 뒤에 들어가는 숫자를 “접두어 합침” 제목 아래 나열되어 있다. 저 숫자에 해당하는 서브넷 마스크를 친절하게 소개하니 참고하여 적용한다.
홈 네트워크나 소규모 네트워크라면 보통 IPv4의 경우 24, IPv6의 경우 64를 쓰면 된다. 끝자리 IP 개수만 할당하는 서브넷 마스크 255.255.255.0 주소와 동일하다.

자, 이제 수정을 했으니 적용해야겠지? 아래 명령어 한번 치면 끝난다.
sudo netplan apply

끝이다. 상당히 간결해졌다.
우부투 위키에서 소개하는 netplan 명령어가 몇가지 있는데, 소개하는 것으로 글을 마치도록 하겠다.

  • netplan generate : 명령어를 실행하면 네트워크 구성에 가장 필수적인 설정 파일을 생성하게 된다. 실수로 네트워크 구성이 망가졌을 경우 쓰면 되겠다.
  • netplan apply : 위에서 소개했듯이 변경한 네트워크 설정을 적용한다. 필요시 재시작할 수 있다.
  • netplan ifupdown-migrate : generate와 동일하긴 한데 /etc/network/interfaces 경로에 있는 네트워크 속성을 netplan 방식으로 마이그레이션 하는 명령어이다.

끗.

참고

composite / 2017년 11월 9일 / Piss Development / 0 Comments

웹 서버와 WAS 서버? 우린 웹으로 무엇을 만들고 있는가?

자바 지배적인 한국에서는 왠만한, 아니, 거의 표준이라고 할 만한 개발용어들 대부분이 자바에서 따왔다.
물론 자바에 없는 개념은 다른 언어에서도 가져오기도 한다.

웹에서는, 자바 경험자들이 IT 관리하다 보니 웹 서비스 시 웹 서버와 WAS 서버라고 칭한다.
웹 서버는 웹 페이지를 서비스하는 서버 프로그램이고. 이에 해당하는 제품이 Apache나 IIS, nginx, webtob 등이 있다.
WAS 서버는 Web Application Server의 약자로, 서버단 언어를 통해 웹 기반의 서비스를 제공하는 서버를 뜻한다. 이에 해당하는 제품이 Tomcat, Jetty, WebLogic, WebSphere, JEUS 등이 있다.

당연히 WAS 단독으로 운영은 가능하며, 자바로 아예 독립적인 웹 서비스를 제공할 수 있다.
하지만 관행적으로 반드시 Tomcat 같은 WAS 서버를 통해서 제공해야 대한민국 개발자들은 직성이 풀린다.

그렇다면 자바로 아예 독립적인 웹 서비스를 제공하는 것을 뭐라고 하느냐.
간단하다. 닷넷에서는 웹 응용 프로그램(Web Application)이라는 용어가 있다.

그렇다. 웹 앱이다. 내가 웹 애비다. 웹 어플리케이션. 웹 프로그램 등등… 그냥 웹 기반의 프로그램인 것이다.
초보들이 어려워하는 이유 안다. 대체적으로 WEB과 WAS 분리 운영, 그리고 서블릿 기반만 가르치다 보니,
자바 혼자서 운영하리라고 생각할 틈을 주지 않는다. PHP는 더하고, 하지만 파이썬이나 루비 등은 오히려 여기에 익숙하다.

갑자기 생각나네. C++ 으로 웹 어플리케이션 제작 후기 올렸는데 왜 생산성 좋은 자바 안쓰냐고 태클건 어느 코더의 댓글…

하지만, 특히 자바 개발자들, 우리는 지금 웹 어플리케이션을 만든다는 것을 잊어선 안 된다.
스프링은 웹 아닌 환경에서도 제공하지만, MVC를 통해 웹 개발 환경도 제공한다.
전자정부는 웹 어플리케이션이라고 칭하지 않는다. 웹 개발 환경이라 칭한다. 왜인진 나도 모른다.
어찌됐던, 우리가 자바던 닷넷이던 그 어떤 언어던 웹 기반의 프로그램을 작성하고 있다면,
웹 앱 또는 웹 응용 프로그램(Web Application)을 개발한다고 해야 모든 언어의 개발자들이 이해하기 쉽다.

이번 글은 웹개발하는 우리의 정체성을 일깨워 주기 위해 싸지른 글이라고 볼 수 있다.
홍콩행 게이바에서 핑크가 딜도 던지는 그런 정체성 말고.

composite / 2017년 10월 24일 / Piss Development / 0 Comments

Spring XML vs Annotation

스프링은 크게 3가지 방식의 설정을 할 수 있다. DB, 빈, 기타등등 스프링 관련 설정들 말이다.

XML             MIXED           ANNOTATION
<---------------------------------------->

그럼 ARABOJA.

XML

스프링의 전통적인 설정 방법이며, 구성을 포함해 모든 자바 빈들을 XML에 정의한다.

  • 원하는 빈만 XML에 담궈 놓고 클래스 목록을 한 번에 볼 수 있다.
  • 필요 시 특정 빈만 주석처리 하는 등 활성화/비활성화가 용이하다.
  • 빈 생성 시 반드시 XML에 정의해줘야 하며, 그렇지 않으면 일반 클래스가 되버린다.
  • 신규 작성시에는 많은 공수시간이 요구되지만, 유지보수 시 부담이 적다.

매우 큰 프로젝트일 경우, 여러 스프링 프로젝트를 운영할 경우 XML 방식을 선호하는 게 이 때문이다.
어노테이션을 쓰게 되면 클래스가 많을 수록 스캔 시간이 길어지지만, 완전 XML에서는 정의된 빈만 스캔하기 때문에 그럴 걱정이 없다.

Mixed

현재 대부분 스프링 프로젝트에서 사용하는 방법이며, 전자정부에서도 기본적으로 이 설정으로 시작하도록 유도하고 있고,
가장 흔한 방식으로, 기본 구성은 XML, 빈 등 가장 많이 차지하는 구성을 어노테이션으로 정의한다.

  • 기본적인 구성 설정(DB, 웹의 경우 Resolver 등)은 XML에 정의한다.
  • 나머지 빈은 패키지 범위를 정해놓고 어노테이션에 맡긴다 (annotation-driven)
  • 이후 빈 생성은 어노테이션만 정의하면 바로 클래스 작성 후 배포할 수 있다.
  • 신규 작성 시 XML보다 공수 시간은 줄어들지만, 수정 및 비활성화가 필요할 경우 재컴파일하여 배포해야 한다.

사실 완전 XML에 비해서 크게 단점으로 작용할 만한 요소는 없다. 대부분 많이 바뀌는 게 바로 기본 구성 성정인 DB나 메시지 정의들이니.
대신 스프링 앱 시작 시 스캔을 시작한다. 여기서 패키지 범위 내 클래스가 많을 수록 스캔 시간은 어쩔 수 없이 길어지게 된다.

Annotation

아예 XML을 쓰지 않고 모든 구성과 빈을 자바에 맡겨놓는 방식이다.

  • 기본 구성 설정부터 @Configuration 어노테이션을 정의한 기본적 클래스로 설정할 수 있다.
  • 이 때 가장 강점은, Strong Type에 가장 부합해 빈 클래스의 무결성을 가장 빨리 검사하고 보장할 수 있다.
  • Java 기반 구성 설정은 Spring 3.0부터 지원하기 때문에 이하 버전에서는 할 수 없다.
  • 자바만 쓰기 때문에 개발생산속도는 가장 빠르지만, 변경 시마다 재컴파일 해야 하기 때문에 유지보수 속도는 매우 떨어진다.

JRebel 같이 실시간 핫스왑으로 개발하거나, 이제 아예 Spring Boot 내부 기능을 통해 재시작 없이 개발할 수 있는 기술의 발달로
더이상 완전한 어노테이션 개발의 문제점은 사라진 상태. 하지만 구성 설정부터 빈까지 모두 스캔해야 하기 때문에 시작속도는 당연히 더 느린 편.
게다가 사소한 수정조차 재컴파일을 거쳐야 하기 때문에 대응속도가 빠르게 요구되는 프로젝트에서는 어려움이 따를 수 있다.

공통

역시 정적 문자열 정의는 properties 가 진리. 텍스트 바꾸고 배포만 하면 되니까.
Spring 4.0 부터는 yml 방식의 구성 또는 메시지도 지원한다고 하니, 좀 더 읽기 쉽고 구조적 구성을 원하면 이거 쓰는것도 나쁘진 않다.

결론

  • 대규모 프로젝트이거나 분산 프로젝트인가? 신규개발은 어렵지만 유지보수가 용이한 XML 설정을 사용하라
  • 별다른 특이사항이 없을 경우 가장 흔히 사용하는 Mixed 방식은 스프링에 접근하기 딱좋다.
  • 가볍고 빠른 생산성으로 소규모 서비스를 원한다면, Spring Boot를 통한 Annotation 기반이 도움이 될 것이다.
  • 프로토타입이나 목업인가? 데모 앱이 필요한가? 그러면 제발 스프링 쓰지마 병시나.

끗.

composite / 2017년 9월 12일 / Piss Development / 0 Comments

자바스크립트 콜백함수 관리 아이디어

Vue를 공부하다가 갑자기 생각나서 글 싸지른다.

자스에서는 가변인자 값은 가져올 수 있는데, 인자명은 못가져온다.
일단 자스에서 개체 까는 API인 ReflectProxy가 있는데,
대체적으로 개체 속성과 생성 관리를 담당할 뿐이다. 물론 유용하긴 하지만.
함수 내에서도 인자를 까는 메소드도 없고, API도 없다.
함수 내 arguments 개체 또한 인자값을 가져올 뿐이고.
최신인 ES2017에서도 이를 대응할 API는 없다…

물론 불가능한 건 아니다. 한가지 확실한 점은, 네이티브 함수(예: Object, Array 등)만 아니면
Function.prototype.toString() 메소드를 실행 시 함수 전체가 까발려진다.
거기서 함수명과 인자, 함수 내용이 모두 나오게 된다. 그 어떤 브라우저든 간에.

그래서 이를 이용해 인자 이름을 가져올 수 있는 방법이 있다.
출처: How to get function parameter names/values dynamically?

var STRIP_COMMENTS = var STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/mg;
var ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
  var fnStr = func.toString().replace(STRIP_COMMENTS, '');
  var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
  if(result === null)
     result = [];
  return result;
}

그러하다. 함수 내용을 파싱해서 코멘트 제거하고 인자명만 쏙 가져올 수 있다.

getParamNames(getParamNames) // returns ['func']
getParamNames(function (a,b,c,d){}) // returns ['a','b','c','d']
getParamNames(function (a,/*b,c,*/d){}) // returns ['a','d']
getParamNames(function (){}) // returns []
getParamNames(function (a=4*(5/3), b) {}) // returns ['a']

완벽하게 대응이 되는 것 같진 않아보여도 대부분 케이스에 대응이 가능하다.
굳이 대응 안되는 케이스가 있다면… 아무래도 화살함수(Arrow Function)가 되겠는데,
(a=>b).toString() 호출하면 크롬의 경우 "a=>b" 이렇게 나온다…
가장 쉬운 대응 방법은 babel로 강제 변환해서 써버리는 것이다… asyncawait 나오면 묵념…

추가로 명명된 가변인자(function(...args))도 대응할 수 없다. 근데 일반 가변인자처럼 대응이 더 어렵다. 패스.

어쨌든, 이제 내가 말하고자 하는 아이디어 예제를 내겠다.
document sandbox 예제다. 함수인자 까는 함수는 위에 것을 그대로 활용한다.

function sandbox(func){
    var anames = getParamNames(func);
    anames = anames.map(function(method){
        return function(){ return document[method].apply(document, arguments); };
    });
    return func.apply(window, anames);
}

sandbox(function(createElement, getElementById, createTextNode){
    var a, b;
    a = createElement('p');
    a.innerHTML = "hello world!";
    document.body.appendChild(a);
    b = getElementById('out');
    b.appendChild(createTextNode('YAY~!'));
});

참고로 document 객체의 모든 요소는 참조를 허용하지 않기 때문에, 어쩔 수 없이 함수로 감싸 꼼수를 썼다.
실행 결과는 jsfiddle 에서 볼 수 있다.
만약 Array.prototype.map 메소드가 실행되지 않는 구닥다리 브라우저의 경우는… jQuery.map() 으로 알아서 수정해서 테스트 해보라.

뭐 내가 말하려는 게 대충 이런 식이다. 이런 샌드박스형 콜백을 활용하면 더 유연한 콜백 대응이 가능할 거라 믿기 때문이다.
근데 왜 ECMA에서는 인자명에 관심을 가지지 않는걸까? 의문을 가지며 이것으로 마치도록 하겠다.

끗.

composite / 2017년 9월 7일 / Piss Development / 0 Comments

웹 사이트 프로젝트(Web Site Project)와 웹 응용프로그램 프로젝트(Web Application Project)의 차이

혹시 알고 넘어가는지 모르겠지만, 닷넷에서 웹 앱을 만드는 데 2가지 프로젝트 형식이 있다.
바로 웹 사이트 프로젝트와 웹 앱 프로젝트인데, 이 둘의 차이점은 간단하게 짚어보는 시간을 갖겠다.

웹 사이트 프로젝트(Web Site Project)

타 언어 웹 사이트로 치자면, ASP, PHP, 일반 JSP 페이지를 만드는 꼴이라고 보면 된다. VS 2005부터 소개되었다.
폴더 루트를 잡고, 거기에 페이지와 리소스, 백엔드 코드를 특정 폴더인 App_Code 에 넣는 방식이다.
프로젝트 생성이 빠르고, 단순하다. 그리고 프로젝트 파일도 생성하지 않는다. 그럼 구성 설정은 어디다가 저장하냐?
바로 솔루션 파일과 구성 설정 파일인 web.config에다 저장한다. 각기 역할은 당연히 틀리고 대부분 설정은 web.config에다 저장한다.
개발만 하고 폴더 그대로 IIS에 배포할 수 있다. 사이트 설정만 하면 작동을 시작한다. 나머진 IIS가 파싱하여,
각 페이지마다 변경 사항이 생길 때마다 컴파일 후, 각기 페이지마다 DLL 파일이 생성되어 페이지를 렌더링 한다.
그렇기 때문에 빠른 배포와 수정이 장점으로 통한다. 하지만 이런 특성이 단점으로 작용하는데,
이렇게 될 경우 각 페이지 내에서 클래스 네임 중복을 확인하지 않는다, IIS는 그걸 인식하지 않고 파일마다 컴파일 하기 때문에,
클래스 이름이 중복되더라도 다른 이름으로 클래스를 생성 후 컴파일하기 때문에 참조 등에서 어떤 문제가 나올 지 파악이 어렵다.
이런 불상사를 예방하기 위해 “게시” 기능이 있다. 게시할 때 “미리 컴파일(Precompiled)” 개념이 있으며, 최적화하고 정리하여 깔끔한 백엔드와 성능을 보장받을 수 있다.

이럴 때 웹 사이트를 쓰면 좋다. 프로토타입, 시연, 데모, 단순한 소개 사이트.

웹 응용프로그램 프로젝트(Web Application Project)

웹 앱을 아예 응용 프로그램처럼 프로그램 단위로 관리하고 운영하는 프로젝트로, VS2005 SP1부터 내장되었으며, 이런 개념은 이미 VS 2003부터 도입이 되었다.
폴더 루트에 .csproj.vbproj 등의 프로젝트 파일이 생기며, 프론트엔드 코드와 백엔드 코드를 아무 곳이나 넣을 수 있으며, 예외 설정 등이 가능하여
관리적 측면에서 아주 유리한 프로젝트이다. 왠만한 구성 설정은 프로젝트 파일에 저장하기 때문에 web.config 파일엔 서버 운영에 필수적인 구성 설정밖에 없는 것도 장점이다.
단점이라면, 매 수정시마다 빌드(컴파일)해줘야 하고, 당연히 컴파일된 상태로 배포를 해야 한다. 물론 아예 “게시”하여 배포할 수 있다.
빌드 후에는 모든 백엔드 코드가 하나의 DLL에 담게 된다. 배포 방식이야 웹 사이트처럼 폴더째로 담으면 땡이지만, 백엔드 코드를 DLL에서 바로 불러오기 때문에 성능 측면에서 이득이다.
또한 게시 기능을 통해 웹 사이트처럼 모든 페이지의 백엔드 코드까지 퉁쳐서 하나의 DLL로 담은 후 배포할 수 있기 때문에,
성능과 안정성 측면에서 당연히 가장 추천되는 웹 앱 프로젝트 방식이다.

이럴 때 웹 응용 프로그램을 쓰면 좋다. 웹 사이트에서 소개한 거 빼고 전부 다. 모든 서비스들 말이야.

결론?

참고로 ASP.NET Core 프로젝트는 웹 사이트 프로젝트가 아직 없다. 웹 앱 프로젝트 방식이다. ASP.NET 팀에서는 ASP.NET Core Web Pages 으로 만들고 있다.
닷넷 코어는 IIS 종속이 아니기 때문에 어떤 방식으로 배포하고 운영할 지는 모르겠으나, 어자피 정식 웹 앱을 만드는 데에는 웹 앱 프로젝트 만큼 관리가 좋은 건 없으니 그거 쓰자.
어자피 WebMatrix는 VS Code가 그 뒤를 계승 이미 끝났으니 신경 끄고.

composite / 2017년 8월 30일 / Piss Development / 0 Comments

WSL에서 리눅스 프로세스 관리하기

리눅스 프로세스 또한 윈도우 작업 관리자에서 관리할 수 있다.
물론 속성 확인 등 윈도우 특화 기능은 지원하지 않는다. 오로지 끝내기 뿐.

아이콘이 있을 리 없으니 흰 아이콘만 뜰 뿐이다.
그리고 Sysinternals 에서 제공하는 Process Explorer 에서도 볼 수 있다.

대체적으로 맨 아래로 내리나 보다.

다음으로는 서비스를 확인해 보도록 하겠다.

composite / 2017년 8월 25일 / Piss Development / 0 Comments

WSL(윈도우 내 리눅스) 에서 데몬 유지 및 sshd 서버 돌리기

먼저 WSL의 특징을 설명하겠다.
일단 리눅스기 때문에 백그라운드 서비스, 즉, 데몬도 존재하며, 똑같이 돌아간다.
하지만 윈도우에서 bash 프로세스가 하나도 없으면, 리눅스 서비스는 다 죽고 리눅스 전원이 꺼진 것이나 다름없다.
그래서 윈도우를 키자마자 리눅스 서비스를 돌리고 싶으면 윈도우 시작하자마자 bash 프로세스를 돌려야 한다.
이를 기초하여 SSH 서버 데몬을 돌림으로 리눅스의 기능을 윈도우 시작 때부터 유지하는 방법을 설명하도록 하겠다.
이를 잘 정리한 링크로부터 출처를 가져왔다.

How to run sshd as a windows service ? #612
How to run Ubuntu service on Windows (at startup)?

  1. 윈도우에서 bash 실행한다.
  2. sudo dpkg-reconfigure openssh-server 실행하여 SSH 호스트 재구성한다.
  3. sudo nano /etc/ssh/sshd_config 실행하여 SSH 설정 파일 편집에 들어간다.
  4. UsePrivilegeSeparation 항목을 찾아 옆에 yesno로 변경
    (이유는 UsePrivilegeSeparation 옵션은 chroot() 호출을 WSL에서 아직 지원하지 않기 때문)
  5. 비번으로 접속하고자 할 경우 PasswordAuthentication 항목을 찾아 (없으면 추가) yes로 세팅.
    (만약 없으면 SSH 접속할 경우 키 파일을 요구함. 유저 파일에 키를 생성하고 클라이언트도 가지고 있어야 함.)
  6. ctrl+O 단축키로 저장 후 ctrl+X 로 편집기를 빠져나간다.
  7. sudo visudo 실행하여 sudo 권한설정 파일을 편집한다.
  8. 적당한 줄을 찾아 $USER ALL = (root) NOPASSWD: /usr/sbin/sshd -D 문구를 추가한 후, $USER를 로그인 이름으로 바꾼다.
    (로그인 이름 알고싶으면 pwd ~/ 쳐서 /home/ 뒤 명칭을 봐라.)
  9. 단축키로 저장 후 나가서 메시지 뜬 게 있는지 확인하고, 메시지 나올 경우 visudo 오류이므로 적절히 수정하여 해결한다. (모르면 검색해라.)
  10. (옵션) SSH 서버를 외부에서 접속하고 싶은 경우, 윈도우에서 방화벽에서 포트번호 22를 허용한다. (개인 및 도메인 범위까지 한다. 공용 말고)
  11. 윈도우 시작 시 SSH 서버를 돌리기 위해 (적당한파일명).vbs 파일을 메모장이나 아무 편집기로 생성 후 아래 내용을 넣는다.
set ws=wscript.createobject("wscript.shell")
ws.run "C:\Windows\System32\bash.exe -c 'sudo /usr/sbin/sshd -D'",0
  1. 저장했으면, 모든 bash 프로세스를 끄고(리눅스 실행 모두 다 종료) vbs 파일을 더블클릭 후 PuTTY 등으로 SSH 접속 되는지 확인한다.
  2. 성공했으면 bash.exe 프로세스 종료 후, 위 vbs 파일을 작업 스케줄러에 등록한다. (모르면 좀 검색하고). 물론 “시스템 시작시”에.
    (시스템 시작 시, 파일은 vbs파일 다이렉트 호출, 사용계정은 반드시 로그인할 계정. LOCAL SERVICE 같은 시스템계정 말고. 암호 저장 안해도 됨.)
  3. 윈도우 껐다 킨 후 PuTTY로 SSH 접속 되는지 확인해서 접속 되면 이제 윈도우와 리눅스는 한몸으로 실제처럼 돌아갈 것이다. 서비스도 다.

왜 굳이 vbs로 하냐고? 물론 bat 파일 쓰거나 직접 작업 스케줄러에 등록할 수는 있어.
근데 작업 스케줄러던 bat 등록하던 뭘 하던 도스창 뜬다. 너같으면 좋겠냐? vbsws.run 에 두번째 0 인자가 바로 창 안띄워 주는 고마운 인자다.
내가 필요 시 즐겨쓰는 놈이기도 하지. 이제 리눅스 VM으로 깔 필요도 없다. 편리하다.

끗.

composite / 2017년 8월 25일 / Piss Development / 1 Comment

1 2 3 7