wrap이란 텍스트 영역이 우측 끝까지 글자가 이어지는 경우 줄이 자동으로 바뀌게
하는 속성을 나타내는데,
off를 하는 경우는 엔터 값이 없으면 자동으로 줄 바꿈을 하지 않는다. 스크롤이 생김
virtual은 자동으로 줄 바꿈을 하게 함.
physical은 강제적으로 줄 바꿈을 함.
hard의 경우는 칼럼 숫자가 넘어가면 자동으로 줄 바꿈만을 해주는 것이 아니라
칼럼에 맞추어서 한 칸씩 자료를 잘라주는 효과가 있다.
off나 virtual이나 결과값은 같다.
하지만 hard의 경우 자동으로 "\n"값을 주게된다.
이런 경우 $music = nl2br($music);거ㅏ 방법으로 코드를 추가해서 $music값을 뿌려주면
중간에 이 적용된다.
wrap의 속성을 무엇을 주는냐에 따라 데이터의 저장방식이 달다진다.
이러한 wrap은 연속된 긴 문자열을 사용하여 게시판 등에서 테이블이 길어지는 것을
방지하는 방법의 하나로 사용되지만, 강제적으로 "\n"을 사용하므로 HTML 태그를 사용
하는 경우에는 주의를 하여야 한다.
*** 테이블의 < td>태그안에 < td style="word-break:break_all;padding:0;> 사용
----------------------------------------------------------------------
Internet Explorer 대신 해당 Office 프로그램에서 Office 문서를 열도록 Internet Explorer를 구성하는 방법
현상
Microsoft Word 또는 Excel 문서와 같은 Microsoft Office 파일에 대한 HTML 링크를 누르면 해당 Office 프로그램에서 파일이 열리지 않고 Internet Explorer에서 파일이 열릴 수 있습니다.
위로 가기
원인
이 문제는 Internet Explorer가 컴퓨터에 설치된 Office 프로그램용 문서를 호스팅하도록 구성된 경우 발생할 수 있습니다. 기본적으로 Internet Explorer는 Office 프로그램용 문서를 호스팅하도록 구성됩니다.
위로 가기
해결 방법
Internet Explorer 대신 해당 Office 프로그램에서 Office 파일을 열도록 Internet Explorer를 구성하려면 다음 방법 중 하나를 사용합니다.
참고 다음 방법을 사용하면 모든 사용자에 대해 해당 Office 프로그램에서 Office 파일을 열도록 Internet Explorer가 구성됩니다.
위로 가기
방법 1: 폴더 옵션 도구 사용
참고 Windows NT 4.0을 실행 중인 경우 다음 절차를 사용하여 해당 Office 프로그램에서 Office 파일을 열도록 Internet Explorer를 구성할 수 없습니다. Windows NT 4.0을 실행하는 경우에는 방법 2를 사용하십시오.
참고 Windows 2000 또는 Windows Server 2003에서 Terminal Server를 실행 중인 경우 이 절차의 4단계에서 고급을 눌러 파일 형식 편집 대화 상자를 열지 못할 수 있습니다. 이 문제는 NoFileAssociate 정책을 사용하는 경우 발생합니다. 이 정책을 사용하면 관리자를 비롯한 사용자가 모든 사용자에 대한 파일 형식 연결을 변경할 수 없게 됩니다. 이 문제에 대한 자세한 내용은 Microsoft 기술 자료의 다음 문서를 참조하십시오.
257592 (http://support.microsoft.com/kb/257592/) Windows 2000 및 Windows Server 2003의 파일 형식 및 파일 연결 기능 변경
폴더 옵션 도구를 사용하여 해당 Office 프로그램에서 Office 파일을 열도록 Internet Explorer를 구성하려면 1. 내 컴퓨터를 엽니다.
2. 도구 메뉴(또는 보기 메뉴)에서 폴더 옵션(또는 옵션)을 누릅니다.
3. 파일 형식 탭을 누릅니다.
4. 등록된 파일 형식 목록에서 Microsoft Excel 워크시트와 같은 특정 Office 문서 형식을 누른 다음 고급(또는 편집)을 누릅니다.
5. 파일 형식 편집 대화 상자에서 같은 창에서 열기 확인란(또는 같은 위치에서 web 문서 열기 확인란) 선택을 취소합니다.
6. 확인을 누릅니다.
위로 가기
방법 2: Windows 레지스트리 편집
경고: 레지스트리 편집기를 잘못 사용하면 심각한 문제가 발생할 수 있으며 문제를 해결하기 위해 운영 체제를 다시 설치해야 할 수도 있습니다. Microsoft는 레지스트리 편집기를 잘못 사용함으로써 발생하는 문제에 대해 해결을 보증하지 않습니다. 레지스트리 편집기의 사용에 따른 모든 책임은 사용자에게 있습니다.
Windows 레지스트리를 편집하여 해당 Office 프로그램에서 Office 파일을 열도록 Internet Explorer를 구성하려면 해당 문서 형식에 대해 BrowserFlags DWORD 값을 8(Microsoft Excel 워크시트의 경우 9)로 설정합니다. 이렇게 하려면 다음과 같이 하십시오. 1. 레지스트리 편집기(Regedt32.exe)를 시작합니다.
2. 다음 레지스트리 키를 찾아 누릅니다.
HKEY_LOCAL_MACHINE\SOFTWARE\Classes
3. 특정 Office 문서 형식에 해당하는 하위 키를 찾습니다. 다음 표는 여러 일반적인 Office 문서 형식에 해당하는 하위 키 목록입니다.
문서 형식 하위 키
Microsoft Excel 7.0 워크시트 Excel.Sheet.5
Microsoft Excel 97 워크시트 Excel.Sheet.8
Microsoft Excel 2000 워크시트 Excel.Sheet.8
Microsoft Word 7.0 문서 Word.Document.6
Microsoft Word 97 문서 Word.Document.8
Microsoft Word 2000 문서 Word.Document.8
Microsoft Project 98 프로젝트 MSProject.Project.8
Microsoft PowerPoint 2000 문서 PowerPoint.Show.8
이 표에 없는 문서 형식에 해당하는 하위 키를 찾으려면 문서 형식과 관련된 확장명에 해당하는 하위 키를 찾습니다. 하위 키의 기본값에는 해당 문서 형식의 하위 키 이름이 포함되어 있습니다. 예를 들어, .xls 확장명은 Excel 워크시트와 연결되어 있습니다. .xls 하위 키 아래에는 기본값으로 문자열 "Excel.Sheet.5"가 포함되어 있습니다. 따라서 Microsoft Excel 워크시트 문서 형식의 하위 키는 다음과 같습니다.
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Excel.Sheet.5
4. 특정 Office 문서 형식의 하위 키를 확인한 후에 Excel.Sheet.5를 제외한 모든 하위 키에 대해 다음 값을 추가합니다.
값 이름: BrowserFlags
데이터 형식: REG_DWORD
값: 8
Excel.Sheet.5의 경우 아래와 같은 값을 추가합니다.
값 이름: BrowserFlags
데이터 형식: REG_DWORD
값: 9
5. 확인을 누른 다음 레지스트리 편집기를 종료합니다.
BACKUP DATABASE 대상DB TO DISK = 'c:\DB_back\대상DB.bak'
서버 쿼리분석기에서 복원
방법 1:
-- 로지컬 네임을 알아낸다.
restore filelistonly from disk = 'F:\FTP\medical_20080522.bak'
-- 데이버 베이스 생성 과 restore를 동시에 해야한다.
create database medical
-- 저장 경로 지정해주고, restore 시작~!
restore database medical from disk = 'F:\FTP\medical_20080522.bak'
with recovery, replace,
move 'medical_Data' to 'C:\Program Files\Microsoft SQL Server\MSSQL\Data\medical.mdf',
move 'medical_Log' to 'C:\Program Files\Microsoft SQL Server\MSSQL\Data\medical.ldf'
방법 2:
DB 생성 - create database medical
DB 복원 - restore database medical from disk = 'c:\DB_back\대상DB.bak'
서울에서 부산 지사에 있는 스토리지에 저장된 데이터를 짧은 시간 안에 액세스할 수 있다면 굳이 많은 비용을 들여 각각의 지사에 스토리지를 구축할 필요성은 없을 것이다.
하지만 대부분의 기업들은 원거리에 있는 사무실과 거리가 멀어질수록 액세스 시간이 길어지기 때문에 각각의 지사에 스토리지를 배치해 액세스 시간을 최소화하는 것을 궁극적인 목표로 하고 있다.
그러나 이같은 방법은 비용 대비 저조한 스토리지 이용률, 데이터 보안에 대한 위험성 문제뿐만 아니라 글로벌 액세스 제한 등의 약점을 갖고 있다.
이러한 측면에서 기업들은 원거리 액세스에 있어서의 시간 단축을 비롯해 이에 따른 문제점을 보다 효과적으로 해결할 수 있는 ‘왑스(WAFS, Wide Area File Service)’를 주목할 필요성이 있다.
◆‘왑스(WAFS)' 의 개념과 기술적 환경
‘왑스’는 원거리통신(WAN)에서 데이터에 대한 느린 속도의 액세스를 개선해 마치 랜(LAN) 환경에서 데이터를 사용하는 것과 같은 기능을 제공하는 솔루션이다.
즉 지사에서 기업의 스토리지에 저장돼 있는 데이터를 보다 신속하게 액세스할 수 있도록 하는 ‘왑스’는 사무실 간 거리 확대, 데이터 보호 등 기업에게 기술적인 혁신을 가져다 줄 것으로 기대된다.
나아가 ‘왑스’는 현재 폭발적으로 증가하는 데이터의 처리문제와 원격지에서의 데이터 관리 기능에 대한 기업의 불안 문제 등을 효과적으로 해결할 것으로 생각된다. 보통 여기서 말하는 액세스의 최소 시간은 3초 미만으로 보고 있다.
그렇다면 기업에게 신속한 원격지 액세스를 제공하는 왑스에 대해 보다 자세히 알아보도록 하겠다.
우선, 이러한 ‘왑스’를 구성하는 기술들로는 보통 ‘NFS(Network File System)’, ‘CIFS(Common Internet File System)’, TCP/IP 프로토콜, 애플리케이션 프로토콜 최적화 그리고 관리 툴 등이 있다.
특히 획기적인 속도 향상은 프로토콜 최적화와 디스크 캐시를 통해 이뤄진다고 할 수 있다.
예를 들어, 100MB 이상의 데이터에 액세스를 하기 위해서는 원격지와 데이터 센터 사이에서 상호 교환되는 신호는 수십만개 이상에 달할 것이다.
그렇기 때문에 원거리 통신환경 속에서 액세스 시간이 지연되는 것은 당연한 이치일지도 모르지만 ‘왑스 ’는 보통 이러한 프로토콜을 간소화해 데이터 액세스를 용이하게 한다는 것이다.
물론 ‘왑스’ 이전에는 원거리 통신(WAN) 가속기 등 제품이 있었지만 WAN 가속기 시장은 기업들로 하여금 체감할 수 있을 정도의 높은 속도 향상을 경험토록 하지 못했기 때문에 스스로 도태되고 말았다.
두번째로 ‘왑스’ 구현에 대한 문제에 대해서 살펴보도록 하겠다.
‘왑스’를 구현해 기존 SAN과 백엔드 스토리지를 전면 교체할 필요는 없다. 그 이유는 ‘왑스’를 프론트엔드와 기존 NAS 및 CIFS 서버로 구성된 IP네트워크 및 NAS 게이트웨이 등에 추가하기만 하면 되기 때문이다.
원거리 사무실에 있는 데이터를 보다 효율적인 방법으로 관리하고자 할 경우에는 이러한 데이터를 데이터 센터에 호스팅해 보다 간편하게 원거리 사이트 설정 관리를 비롯, 이러한 데이터가 규제 요건에 부합하도록 보안 관리 및 유지를 가능케 한다.
이렇듯 ‘왑스’의 궁극적인 목표는 데이터 센터와 원거리 사무실 간의 지연 시간을 단 몇초의 LAN 환경까지 줄임으로써 데이터를 중앙 데이터 센터에서 호스팅하고 관리할 수 있도록 하는 것이다.
즉 ‘왑스’는 원거리 사무실에 있는 사람이 본사에서 보호 및 관리하는 파일들을 신속하게 액세스 할 수 있게 도와주는 것이다.
다만 이러한 과제를 해결하기 위해 ‘왑스’ 유지를 위한 운용비와 인프라 전반의 총소유비용(TCO)을 낮추는 작업이 선행돼야 할 것이다.
한 조사기관에 따르면 현재 전세계 기업 데이터의 75% 이상이 데이터 센터 외부에 존재하고 있으며 전체 데이터의 60% 이상이 보호를 받지 못하고 있는 실정으로 나타났다.
이렇듯 데이터 보호 및 관리를 위해서라도 ‘왑스’의 중요성을 인식해야 할 것이다.
◆왑스 솔루션 사업자간 움직임
‘왑스’ 시장에서 일어나고 있는 각 벤더들간 움직임들을 살펴보면 맥데이터는 GEDI 전략의 일환으로 서버와 스토리지 연결에서 애플리케이션과 데이터 연결로 그 가치를 확대하고자 하고 있다.
이렇게 함으로써 ‘왑스’는 SAN을 통해 데이터에 대한 블록 액세스와 파일 액세스를 통합할 수 있는 기회를 제공하며 기존 SAN과 결합함으로써 데이터 센터 내에 있는 데이터를 중앙집중적으로 저장 및 관리할 수 있다.
결국 MAN과 WAN을 통해 이러한 데이터를 원격으로 신속하게 액세스할 수 있도록 한다.
따라서 사용자는 데이터 관리 비용 절감, 데이터 손실 위험 절감, 원거리 사이트의 장비수 감소, CIFS 서버 및 백업용 테이프 드라이브, 스토리지 이용도 증대 등을 통해 TCO 절감의 효과를 누릴 수 있다.
브로케이드는 MS 오피스 환경에 최적화된 솔루션 테이프스트리 ‘왑스’ 솔루션을 공급중이다.
MS 오피스 관련 문서와 기타 CIFS 및 NFS 표준에 기반을 둔 응용 프로그램의 WAN 대기 시간에 대한 문제점를 완화한 것이다.
테이프스트리 왑스는 MS의 ‘브랜치 오피스 프로그램’을 활용하게 되는데 브랜치 오피스 프로그램은 MS가 지사 관리용 오피스 프로그램을 별도로 구성해 놓은 것이다.
시스코시스템즈 역시 EMC와 공동으로 시스코 ‘왑스’ 솔루션과 EMC의 NAS 솔루션을 연계해 지역별로 분산된 데이터 서버나 데이터 센터를 통합하는 시장 공략에 본격 나선다고 밝힌 바 있다.
결론적으로 데이터 센터와 지사간 지연 시간을 줄임으로써 데이터를 중앙 데이터 센터에서 호스팅하고 관리할 수 있도록 하는 ‘왑스’의 필요성과 보호받지 못하고 있는 데이터의 보호와 관리를 위해서 ‘왑스’의 중요성을 기업들은 간과해서는 안 될 것이다.
뿐만 아니라 ‘왑스’ 구현을 통해 갈수록 증가하는 소프트웨어 비용 절감 등 운영 및 관리에서의 비용을 50%까지 절감이 된다는 사실은 ‘왑스’의 비용 대비 효율성을 입증하는 좋은 예라고 할 수 있을 것이다
PL(Project Leader)은 그동안 많이 쓰여져 왔던 프로젝트 매니저에게 좀더 경영자적인 자질을 요구하면서 등장시킨 지위라고 보시면 되겠습니다.
그럼 프로젝트 리더의 역할과 자질에 대해서 알아보도록 하겠습니다.
PL(Project Leader)의 5가지 역할
1. 전략적 기획가(Strategic Planner)
-프로젝트 목표와 비전 설정
-목표달성을 위한 전략계획 수립
-연구업무와 연구원의 연계(Matching) 및 프로젝트 추진일정(Scheduling)
2. 동기부여자(Exciter)
-팀 응집력, 팀정신(Team Spirit)의 구축
-팀 구성원들에 대한 Empowering(신바람)
3. 기술적 전문가(Technical Expert)
-신선한 아이디어나 새로운 접근방법에 대한 제안
-기술적 문제점 파악과 대안있는 비판
-다양한 아이디어, 접근방법, 시각들을 통합
-개개인의 아이디어나 연구결과에 대한 피드백
4. 기술정보통(Gatekeeper)
-활발한 외부 기술정보원접촉과 Networking
-시장 및 수요자 욕구에 대한 민감한 탐색(Monitoring)
-의사소통의 구심점 역할(Communication Star)
-경우에 따라서는 대변인이나 통역 역할
5. 열성적 추진자(Champion)
-프로젝트 목표와 리더개인 목표의 합일
-프로젝트의 열성적 추구자
-프로젝트 실행을 위한 승인과 자원획득
-관련부서와의 제휴 및 연대구축
-대외적인 홍보와 Salesman 역할 (Ambassador)
프로젝트리더의 자격요건
-주인의식(Ownership)이 있어야 함.
-하고 있는 일에 전적으로 몰입하고 사명감이 있어야 함.
-성공을 위한 강한 에너지와 열정(Need for Achievement)이 있어야 함.
-부문별 목표보다는 조직전체를 생각하는 팀정신 소유자(Team Player)
-자유로운 의사소통(Communicator)을 할 수 있어야 함.
-거시적 안목에서 일을 처리할 수 있는 자신감(Confidence)이 있어야 함.
-팀원들을 격려하고 도와주며 활력을 줄 수 있어야(Empowerment) 함.
-팀원을 관리하기 보다는 계발, 육성(Develop)할 수 있어야 함.
세상에는 수많은 프로그래밍 언어가 존재한다. 각 프로그래밍 언어는 자신만의 독특한 장단점을 가지고 있기 때문에 모든 프로젝트에 적합한 최고의 프로그래밍 언어는 존재하지 않는다. 결국 프로젝트의 요구 사항과 성격, 개발자의 자질, 여러 환경 요소를 모두 고려하여 가장 적절한 프로그래밍 언어를 고르는 일이 중요하다. 이 글에서는 프로그래밍 언어를 선택할 때 어떤 요소들을 고려해야 하는지 알아보자.
소프트웨어 개발자들은 성경에 나오는 바벨탑의 교훈을 잊어버린 걸까? 세상에 존재하는 수많은 언어 때문에 존재하는 불편함을 잘 알고 있는 프로그래밍 언어 개발자들이 왜 각자 문법과 어휘가 다른 수많은 프로그래밍 언어를 만들어 냈을까? 프로그래밍 언어는 단순히 의사소통을 하기 위한 수단만은 아니다. 소프트웨어는 세상에 산재하는 수많은 도메인(domain)의 문제를 풀어야 하고, 이 모든 문제들을 쉽게 풀 수 있는 최적의 언어는 존재하기 힘들기 때문이다. 소프트웨어 개발자들은 자신이 개발해야 하는 소프트웨어의 성격에 따라 프로그래밍 언어를 달리해야 한다. 시스템 소프트웨어를 작성한다면 C 언어와 어셈블리 언어가 적합할 것이며, 간단히 자신의 알고리즘을 테스트해보거나 프로토타이핑을 한다면 인터프리팅(interpreting)되는 스크립트 언어가 적합하다.
비교적 간단한 프로그램을 작성해보는 것이라면 사실 어떤 언어를 사용해도 무방하다. 하지만 비교적 큰 프로젝트의 산출물은 여러 가지 요소에 의해서 그 품질이 결정되는데, 여기에는 적절한 프로그래밍 언어의 선택이 중요하다. 따라서 프로젝트 초기에 프로젝트를 계획하면서 개발 도구와 환경을 결정할 때 프로그래밍 언어를 정하는 과정도 반드시 포함되어야 한다. 이 과정에서 여러 개의 프로그래밍 언어를 후보로 올려놓고, 프로젝트의 성격에 따른 여러 기준을 적용하며 의사 결정을 하게 된다. 프로그래밍 언어를 고르는데 있어서 절대적인 잣대는 없지만, 이 글에서는 이 과정에서 사용할 수 있는 몇 가지 유용한 판단 기준을 제공하고자 한다.
컴파일 vs. 인터프리터
숙련된 프로그래머 중에서 컴파일되는 프로그래밍 언어와 인터프리터되는 프로그래밍 언어의 차이점을 모르는 사람은 없을 것이다. 인터프리터되는 언어는 비교적 빠른 속도로 프로그램을 짤 수 있고, 결과를 쉽게 확인할 수 있다. 반면 컴파일되는 언어는 수행 속도가 빠르다. 프로그래밍 언어를 선택할 때 가장 먼저 적용해봐야 할 잣대 중에 하나는 해당 언어의 컴파일러나 인터프리터가 존재하느냐는 것이다.
경우에 따라서는 컴파일러와 인터프리터가 모두 존재할 수도 있고, 두 가지가 혼합된 형태일 수도 있다. 예를 들어 자바의 경우 자바 프로그램이 바이트코드(bytecode)로 컴파일되고, 자바 가상 머신(Java Vir tual Machine)에 의해서 다시 인터프리트되는 것이 일반적이다. 그러나 모바일 컨텐츠나 게임을 만들 때는 자바로 프로그램을 만들고 수행 속도 향상을 위해 타겟 플랫폼에 맞춰 미리 컴파일(AOTC, Ahead Of Time Compilation)하는 경우가 흔한데, 이는 자바 언어의 컴파일러라고 볼 수 있다. 비슷한 예로, 수행되기 직전에 머신 코드로 컴파일되는 JIT(Just In Time) 컴파일 방법도 있다.
같은 언어로 프로그래밍되더라도 컴파일러냐 인터프리터냐에 따라 성능과 사용성이 크게 달라진다. 일반적으로 컴파일되는 프로그래밍 언어는 두 가지 장점이 있는데, 하나는 수행 속도 향상이고 또 하나는 소스코드의 암호화(obfuscation)이다. 컴파일러가 인터프리터에 비해 같은 프로그램을 빠른 속도로 수행하게 만드는 것은 분명하다. 컴파일 시간은 런타임과 별도로 한 번만 수행되면 되기 때문에 각종 최적화(optimization) 기술을 적용하기가 유리하다. 물론 최근에는 자바 가상 머신(JVM)이 이런 컴파일러의 최적화 기술을 빌려와 동적으로 머신 코드를 생성하는 기술(adaptive compilation or HotSpot)을 도입했지만, 일부 최적화 기술은 그 특성상 많은 시간이 걸리기 때문에 같은 언어를 컴파일하여 얻어진 프로그램보다 빠를 수는 없다.
또 하나의 차이점은 소스코드를 얼마나 알아보기 힘들게 만들 수 있는가이다. 컴파일된 프로그램의 경우 해당 고급 언어의 특징이 거의 사라진, 기계어로 번역되어 있기 때문에 머신 코드를 바탕으로 원본 소스코드를 복원해 낼 수 있는 가능성은 거의 없다. 반면에 인터프리터되는 언어는 수행을 위해 소스코드가 건네져야 하므로, 소스코드 공개 의사가 없는 상업적인 프로젝트의 경우 해결하기 힘든 문제에 봉착할 우려가 있다.
필자도 프로젝트를 수행하면서 소스코드의 비밀 유지 때문에 많은 문제를 겪었다. 필자는 디지털 텔레비전을 위한 미들웨어 플랫폼을 만드는 일을 했었는데, 여기서 하드웨어와 운영체제를 바탕으로 시스템을 빌드하는 일은 C 언어로 했지만, 해당 플랫폼이 자바를 기반으로 하기 때문에 API를 자바 기반으로 작성해야 했다. 문제는 이를 배포하기 위해 바이너리를 줘야 하는데, C 언어로 컴파일된 바이너리는 문제가 없었지만 자바로 작성한 클래스를 배포할 때 문제가 생겼다.
자바의 경우 일단 한 번 바이트코드로 컴파일된 후에 자바 가상 머신 위에서 인터프리트되지만, 바이트코드는 가상 머신에서 동작하는 일종의 기계어임에도 불구하고 실제 기계어인 인텔이나 ARM, PowerPC 등의 어셈블리 언어에 비해서는 대부분의 자바 심볼(symbol)을 보존하고 있는 고급 언어라 할 수 있다. 시중에는 자바의 클래스 파일을 바탕으로 원래의 자바 소스코드를 복원해주는 디컴파일러(decompiler)가 많이 존재한다. 따라서 자바로 만든 프로그램을 배포할 때는 이를 컴파일하여 클래스 파일만 배포하더라도 누군가가 소스코드를 엿볼 수 있다는 불안에 시달려야 하는 것이다.
필자의 회사에서 시도한 첫 번째 방법은 자바 소스코드를 뒤죽박죽으로 만들어 주는 프로그램(Java Obfuscator)을 이용하는 것이었다. 이 프로그램은 원래 자바 프로그램의 의미를 훼손시키지 않고, 단순히 변수 이름과 클래스 이름을 a, b, c 등의 의미 없는 이름으로 바꾸어서 해당 프로그램을 해독하기 힘들게 만들어 준다. 그러나 이 방법도 완벽하진 않았다. 클래스와 변수 이름을 이상하게 바꿀 수는 있어도, 외부로 참조해야 하는 API의 이름을 바꿀 수는 없을 뿐더러, 비교적 제한된 애플리케이션 범주라면 숙련된 자바 프로그래머의 경우 바이트코드에서 복원된 소스코드를 읽는 것이 어렵지 않기 때문이다.
이 미들웨어는 결국 자바 클래스 파일을 JAR가 아닌 별도의 암호화 방법으로 압축했다. 그리고 이 클래스를 읽는 방법은 비밀에 붙인 채, C 언어로 암호화된 클래스 파일을 해석하여 원래의 클래스로 복원하여 자바 가상 머신에 로딩해 주는 방법을 사용하게 되었다. 이와 달리 일반적인 애플리케이션의 경우 인터프리팅되는 언어를 사용한 프로그램의 소스코드가 공개되지 않기를 바란다면, 이는 패키지로 만들어서 서버에서 수행한 후 결과만 웹 브라우저를 통해 알려주는 서블릿(servlet) 형태가 되어야 할 것이다.
결국 프로젝트에 있어서 성능이 중요하거나 소스코드 유출 방지가 높은 우선순위를 차지한다면, 인터프리터 언어가 주는 유용성, 개발의 편리성을 감안하더라도 치러야 할 대가가 크다는 사실을 알 수 있다. 따라서 특정 프로그래밍 언어를 선택하기 위해서는 해당 프로그래밍 언어의 컴파일러가 존재하는지, 혹은 인터프리터가 존재하는지를 확인해보는 것이 필요하다.
언어간 통합 문제
완벽한 한 가지 프로그래밍 언어는 존재하지 않는다고 말했다. 프로그래밍 언어가 가지는 각각의 특징 때문에 한 프로젝트 안에서 2~3개 이상의 프로그래밍 언어를 사용해야 할 경우는 생각보다 빈번하다. 이 경우 각각의 프로그래밍 언어가 가지는 특징도 중요하지만, 두 언어가 얼마나 유기적으로 잘 융합되어 하나의 시스템을 만들 수 있는지도 중요한 판단 기준이 된다. 대부분의 소프트웨어를 C++로 작성하고, 일부 테스트 프로그램과 간단한 유틸리티를 파이썬으로 작성했다면 언어간 통합은 큰 문제가 아닐 수도 있다. 그러나 시스템의 특성상 2가지 이상의 언어가 서로 유기적으로 얽혀서 구성되어야 하는 경우 두 언어간 통합이 원활하지 않다면 이는 프로젝트의 위기로 연결될 수도 있다.
필자는 프로그래밍 언어간 통합 문제로 크게 고생을 한 적이 있다. 이미 언급했듯이 필자가 참여했던 DTV용 미들웨어 프로젝트는, 셋탑 박스에 올라가는 실시간 운영체제(Real-time OS) 위에 미들웨어를 올리고 미들웨어 응용 프로그램을 위한 자바 API을 제공해야만 했다. 즉 자바 API는 자바로 작성하되, 셋탑 박스(STB)의 하드웨어 자원에 접근해야 하는 경우 C 언어를 사용할 수밖에 없었다. 또한 셋탑 박스 또한 임베디드 환경이기 때문에 메모리가 한정되어 있고, CPU 속도가 충분치 않아 자바로 수행할 경우 속도가 느린 모듈은 C 언어로 내리는 작업도 병행해야 했다.
자바의 경우 “한 번 작성하고 모든 곳에서 사용한다(Write Once, Run Everywhere)”는 모토에 따라 시스템 의존적인 C 언어와 통합할 이유가 없을 것 같다. 하지만 실제로 임베디드 시스템의 경우 자바를 사용하더라도 하드웨어가 제공하는 고유의 기능에 접근하기 위해서는 C 언어로 된 시스템 API를 호출해야 하기 때문에 C 언어와의 통합이 필수적인 경우가 많다. 자바도 이 필요성을 인지하고 JNI(Java Native Inter face)라고 하여, 자바 메쏘드를 C 언어로 작성할 수 있는 표준 인터페이스를 정의해 놓았다.
C 언어와의 통합을 위한 표준 인터페이스까지 존재하는 언어인 자바는 C 언어와 통합이 필요한 경우 이상적인 언어라고 판단할 수도 있다. 사실 다른 언어와의 인터페이스를 표준화하거나 구체적으로 명시한 언어조차 드문 상황이다 보니, 이 정도면 언어간 통합 문제를 어느 정도 해결해주고 있지 않느냐는 결론을 내릴 수도 있다.
그러나 실제로 자바와 C를 사용하여 프로젝트를 수행한 필자의 경험에 따르면, 언어간 통합은 절대로 쉬운 일이 아니었다. 자바에서 C 언어로 작성된 라이브러리를 로드하고 이 메쏘드를 부르는 것은 물론이고, C 언어로 작성된 자바 메쏘드에서 자바 객체의 필드에 접근하고 자바 메쏘드를 호출하게 만드는 일이 결코 간단하지 않았다. JNI 자체가 프로그래머의 실수를 유도하기 쉽게 만들어진 면도 많았고, 숙련된 프로그래머조차 버그 없이 한 번에 C와 자바를 통합하는 일은 힘들었다.
이는 어떻게 생각해보면 당연한 일인지도 모른다. C 언어에서 자바 메쏘드를 호출하고 객체를 사용하기 위해서는 기존의 C 언어에는 존재하지 않는 개념인 클래스나 객체, 필드, 메쏘드 등 객체지향 프로그램 언어의 특징을 C 언어의 구조체(struct)나 함수 포인터(function pointer) 등을 이용해 표현해줘야 하고, 이를 이용하는 것도 자바처럼 간단하지 않다. 자바에서 지원하는 예외 처리(exception handling) 방법도 C 언어에서 일일이 특정 함수를 호출하여 확인한 후 적절히 리턴해줘야 하고, 자바의 메모리를 접근하기 위해서도 가비지 콜렉터(garbage collector)와의 연관 관계를 생각해야만 한다. 즉 자바가 가상 머신 속에 감추어둔 내부 구조가 C 언어로 건너오면서 노출되는 것이다.
좀 더 일반적으로 말하면 두 언어를 연결하기 위해서는 두 언어 중 하나의 언어가 다른 언어의 기능을 흉내내줘야 한다. 프로그래밍 언어가 처음 만들어질 때부터 다른 언어와의 연관 관계를 생각하지 않았다면 이런 기능을 바라는 것은 힘들 수도 있다. 이상적인 관점을 버리고 특정 언어가 최소한 C 언어와 얼마나 잘 통합될 수 있느냐만 보는 것도 현실적인 접근 방법이다. 왜냐하면 대부분의 라이브러리가 C 언어로 작성되어 있기 때문이다. 파이썬이 태생부터 다른 언어와의 접착성(glue)을 강조하며 나타났던 것도 이런 생각이 깔려 있으리라 짐작 된다.
이 문제를 근본적으로 접근하여 해결책을 제시한 것은 마이크로소프트(MS)였다. MS가 닷넷 플랫폼에서 강조한 내용 중에 하나가 교차 언어(cross-language) 플랫폼인데, 이 개념의 핵심은 서로 다른 언어로 작성한 모듈이나 클래스를 서로 호출하여 사용할 수 있음을 의미한다. 대표적인 예로 VB.NET으로 작성한 클래스를 아무런 수정 없이 C#에서 사용할 수 있다는 점을 들 수 있다. 물론 서로 기본형(primitive-types)과 기능이 다른 프로그래밍 언어가 아무런 제약 조건 없이 서로를 호출해 사용할 수는 없기 때문에 CLS(Common Language Specification)를 만들어 이에 부합해야만 교차 언어를 사용할 수 있다. 그러나 닷넷이 언어간 통합 문제를 어느 정도 해결한 것은 분명해 보인다.
비슷한 움직임으로 썬(Sun)에서도 자바 외에도 자바 바이트코드로 변환되어 실행되는 프로그래밍 언어의 표준화 작업을 시작했다. 일례로 그루비(Groovy)는 바이트코드로 변환되어 실행되는 스크립트 언어인데, 자바와 그루비 모두 바이트코드 형태로 변환되기 때문에 그루비는 자바로 짠 라이브러리와 API를 마음대로 접근하여 사용할 수 있는 특성이 있다. 언어 간의 통합 문제가 점차 더 큰 요구 사항이 된다면, 이러한 시도는 점차 확대되리라 생각한다.
얼마나 객체지향적인가
지난달에 기고했던 ‘프로그래밍 언어론을 배우자’에서 프로그래밍 언어의 4가지 패러다임에 대해 설명한 바가 있다. 프로그래밍 언어는 크게 지시형(procedural) 언어, 객체지향 언어, 함수형 언어, 선언형 언어로 나뉘고 각 패러다임에 따라 언어의 특징이 크게 다르다고 이야기했다. 그러나 프로젝트를 위한 프로그래밍 언어를 선정하는 시점에 오면 판단 기준은 한 가지로 집중된다. 얼마나 객체지향적인가?
함수형 언어나 선언형 언어는 프로그래밍 방법론에 있어서 여러 가지 가치있는 시사점을 전달해주고, 기존의 지시형 언어와 객체지향 언어에 많은 영향을 미친 것이 사실이지만, 그 자체로 함수형, 선언형 언어는 비교적 도메인에 제한적이고, 실제로 프로젝트에 사용되는 일이 드문 편이다. 결국 C와 C++로 대변되는 지시형 언어와 객체지향 언어의 사이에서 어느 지점을 택할 것인가가 가장 현실적인 문제로 남게 된다.
객체지향 언어의 장점은 잘 알려져 있다. 데이터의 캡슐화(encapsulation), 코드 재사용(code reuse), 상속(inheritance), 다형성(polymorphism) 등 기존의 지시형 언어가 가지지 못한 여러 장점을 선사한다. 그러나 좀 더 객체지향적일수록 프로젝트에 적합하다는 일반론은 옳지 않다. 순수 객체지향(OO)을 표방하는 언어들이 비교적 느린 수행 속도로 악명 높고, 실제로 객체지향적일 필요가 없는 코드까지 객체지향적으로 사고하도록 강요하는 경우도 있다. 간단히 몇 가지 일련의 명령을 수행하고 싶은데도, 이를 추상화하여 클래스로 만들고 객체를 생성하고 메쏘드를 호출해야 하는 것은 분명 장점만은 아니다. 또 순수 객체지향 언어일수록 비교적 수행 속도가 느리다는 단점도 안고 있다.
반대로 객체지향 언어의 특징 중 일부만 빌려와도 크게 생산성이 향상될 수 있는 경우도 있다. 임베디드 시스템의 경우 칩셋(chipset) 회사들이 보통 컴파일러까지 제공한다. C++나 다른 고급 언어 컴파일러도 제공하면 좋겠지만, 칩셋 회사들의 특성상 보통 C 언어 컴파일러를 제공한다. 따라서 이런 임베디드 시스템에서 프로그래밍을 한다면 할 수 없이 C 언어를 사용해야 하는 경우가 많다. 팜과 같은 초창기 임베디드 시스템의 API를 보면 프리픽스(prefix)만 달리한 수많은 함수의 나열에 기겁한 경험이 있을지도 모른다. 비슷한 기능을 하는 함수들을 묶어서 네임 스페이스만 달리 줄 수 있었어도, 이런 환경에서 프로그래밍하는 개발자의 생산성을 훨씬 높아졌을지도 모른다.
그 예로 비교적 성공한 OS로 평가받고 있는 스마트폰용 운영체제 시스템인 심비안(Symbian)이 있다. 심비안 OS의 API가 C++로 작성되어 있어서 기존의 C 언어 API에 비해 비교적 정리가 잘 되어 있고 개발도 용이한 편이다. 그러나 이 성공이 C++ 언어 전체의 기능 때문만은 아니다. C++의 특성 중 일부인 클래스를 이용한 네임 스페이스 분리, 예외 처리 등만 C에 추가되었어도 비슷한 효과를 얻었을 것이다.
객체지향과 관련하여 또 하나 언급하고 싶은 것은, 객체지향 언어의 기능 중 일부는 아직도 완전한 동의 없이 서로 다른 방법으로 구현되고 있다는 점이다. 대표적인 예가 다중 상속(multiple inheritance)이다. 다중 상속은 말도 많고 탈도 많은 기능 중 하나이다. 잘 사용하면 강력한 기능이 되기도 하지만, 코드를 복잡하고 이해하기 힘들게 만드는 주범 중에 하나이기도 하다. 자바는 C++의 다중 상속이 마음에 들지 않아 이를 인터페이스로 대체했고, 또 루비를 비롯한 일부 언어는 믹스인(mix-ins)이라는 방법을 이용하여 코드를 조합하여 사용하기도 한다. 또 일부 언어는 일반적인 상속 관계와 코드 재사용을 구분하여 코드 상속(code inheritance)을 따로 지원하기도 한다. 언어를 선택할 때 이런 논쟁적인 부분을 해당 언어에서는 어떤 접근 방법으로 해결하고 있는지를 잘 살펴보는 것도 중요하다.
부수적인 조건이 아닌 안정성
보통 프로그래밍 언어의 안정성(reliability)은 부수적인 요건으로 여겨졌다. 하지만 프로그래밍 언어의 안정성은 개발 속도와 버그 발생률, 디버깅의 편의성, 테스트 등에 모두 영향을 미치는 매우 중요한 요건이다. 안정성이나 테스트의 편의를 결정하는 프로그래밍 언어의 특징은 타입 시스템(type system), RTTI(Run Time Type Inspection), 가비지 컬렉션 등을 들 수 있다. C 언어는 비교적 약한 타입 시스템을 가진 언어이다. C 언어에서 데이터 형은 어떤 다른 형으로도 캐스팅될 수 있고, 이 점은 C 언어의 강력한 장점이자 가장 큰 문제점이기도 하다. C 언어 타입 시스템의 약점은 개발 후반에 재앙으로 나타날 수 있는데, 이는 해결하기 힘든 버그 중에 하나이다.
임베디드 시스템 개발에 C 언어를 사용하는 예를 들어보자. 이 경우 C는 최선의 대안임이 분명하지만, C 언어의 특징 때문에 여러 가지 문제가 일어난다. C 언어에서 가장 흔히 하는 실수는 배열의 인덱스가 잘못되어 잘못된 메모리에 값을 쓰는 경우, 포인터 연산이 잘못되어 잘못된 메모리의 값을 읽거나 쓰는 경우다. 임베디드 시스템이 사용하는 OS는 대부분 메모리 공간이 하나로, 커널과 유저 모드의 구분이 없다. 즉 잘못된 메모리에 접근하더라도 세그먼테이션 폴트(segmentation fault)가 나지 않는다. 즉 커널 영역의 메모리 주소에 잘못된 포인터 연산으로 특정 값을 쓰더라도 그 시점에는 아무런 문제없이 넘어간다. 문제는 그렇게 바뀐 메모리 주소를 나중에 읽으려고 할 때 잘못된 값을 읽어 와서 프로그램이 이상 동작할 경우이다. 이 경우 문제 시점과 원인의 발생 시점이 다르기 때문에 그 원인을 파악하는 게 사실상 거의 불가능해 진다.
만약 C 언어가 아니라 자바처럼 메모리 포인터가 없고, 배열의 경우 항상 배열의 경계값 검사를 해주는 프로그래밍 언어를 사용했다면 저런 문제는 절대 발생할 수 없었을 것이다. 즉 프로그래밍 언어의 타입 시스템에 따라 어떤 종류의 프로그램 버그는 원천 봉쇄할 수도 있다는 이야기다. 이러한 점은 프로그래밍 언어를 선택할 때 반드시 고려해야 한다.
리플렉션(reflection)이라 불리는 언어의 기능은 테스트 프레임워크를 만드는데 많은 도움을 준다. 리플렉션은 런타임에 프로그래밍 언어의 타입을 동적으로 조사하고 이를 호출하여 사용할 수 있는 기능을 말한다. 즉 프로그램이 동작 중에 어떤 데이터 타입이 있는지 확인한 후에, 해당 메쏘드를 무작위로 불러보는 일이 가능해진다. 이 기능은 보통 자바로 작성된 API의 경우, API가 표준에 맞는 클래스 이름과 메쏘드 이름, 그리고 인자들을 가지고 있는지 동적으로 확인한다. 또 해당 시스템의 API를 무작위로 호출하여 시스템의 안정성을 테스트할 때 사용된다.
언어의 런타임이 가비지 컬렉션을 지원하느냐의 여부도 넓게 봐서 언어의 안정성에 포함된다. malloc/ free나 new/delete를 사용하는 프로그래밍 언어는 대부분 자원 관리를 적절히 하기 위해 엄청난 노력이 소요된다. malloc한 메모리는 반드시 어느 시점에서인가 free해줘야 하는데, 이를 여러 조건에 빠짐없이 처리해주는 것만으로 시스템의 복잡도가 상당히 올라감을 알 수 있다. 이를 실수하면 곧바로 메모리 누수(memory leak)로 이어지기 때문에 여간 신경쓰이는 일이 아니다. 가비지 컬렉션을 지원한다면 프로그래머를 이러한 자원 관리 문제에서 어느 정도 해방시키기 때문에 생산성이 향상되고, 자원 관리 문제로 인한 버그를 예방할 수 있는 장점이 있다.
얼마나 많은 라이브러리가 표준화되어 있나
프로그래밍 언어를 선택함에 있어서 가장 중요한 부분은 어쩌면 그 언어의 사용을 도와주는 얼마나 많은 지원이 있느냐 일지도 모른다. 여기서 지원은 각종 프로그래밍 언어 서적, 웹 사이트, 그 프로그래밍 언어를 사용하는 사람들의 숫자, 전문가, 바로 사용할 수 있는 라이브러리 등이다.
프로그래밍 언어도 네트워크와 마찬가지(network effect)로 사용하는 사람이 많을수록 그 언어를 사용하는 모든 사람이 이득을 얻는 특징이 있다. 사람들은 전문적인 지원이 없으면 그 언어의 선택을 꺼리는 경향이 있고 더 많은 사람들이 사용하는 언어를 선택하는 경향이 강하다. 컴퓨터 산업이 어느 정도 성숙되고 나서 상업적으로 성공한 언어가 대부분 MS나 썬과 같이 대기업의 전폭적인 지원이 있었다는 사실도 이를 보여준다. 수많은 책을 펴내고 그 언어의 사용을 장려하기 위해 여러 프로모션 정책을 펴는 것이 프로그래밍 언어의 성공에 있어서 생각보다 중요한 요소인 것이다.
이런 지원 중에서 가장 중요한 요소는 사용 가능한 라이브러리가 얼마나 많이 있느냐다. 자바의 성공은 자바 프로그래밍 언어의 특징에도 있었지만, 또 하나의 요소는 바로 사용 가능한(out-of-the-box) 표준 라이브러리가 언어의 런타임과 함께 배포되었다는 점이다. 프로그래밍 언어의 이러한 특징으로 인해 개발 작업은 새로운 것을 만들어내는 일에서 이미 작성된 라이브러리를 최대한 잘 활용하며 어떻게 조합하느냐로 바뀌었을 정도다. 이러한 변화를 잘 반영하는 말이 있다. 흔히 자바 프로그래밍을 처음 시작하는 사람에게 해주는 충고로 “어디에 있는지를 알아라!(Know Where)”라는 이야기를 많이 한다. 과거 프로그래밍은 언어의 기본적인 기능만으로 모든 것을 만들어 써야 하던 ‘Know What, Know How’의 시대였다면 현재의 프로그래밍은 자신이 사용하고자 하는 기능이 어떤 클래스에 어떻게 구현되어 있는지를 알고 이를 재빨리 찾아서 사용하는 것으로 바뀌었다. 따라서 얼마나 다양하고 많은 라이브러리를 제공하느냐는 프로그래밍 언어의 성패를 정하게 되었다.
여기서 주목해야 할 것은 단순히 얼마나 많은 라이브러리가 있느냐가 아니라 얼마나 많은 라이브러리가 표준화(standard library)되어 있느냐다. 사실 C 언어의 경우 정말 엄청난 양의 라이브러리가 존재하고, 상당수가 오픈소스로 존재하지만 서로 다른 컨벤션(convention)과 스타일을 사용하는 라이브러리를 자신의 구미에 맞게 요리하여 사용하기란 쉬운 일이 아니다. 남의 코드를 가져다 쓴다는 게 얼마나 어려운 일인지는 조그마한 라이브러리를 가져오려고 시도해 본 적이 있는 사람은 모두 공감할 것이다.
결국 프로그래밍 언어 자체가 이미 표준화된 라이브러리를 매우 풍부하게 제공하여 대부분의 기능한 제3자를 통하지 않고서도 직접 프로그래밍할 수 있는 환경을 만들어 주는 것이 중요하다. MS와 썬은 이미 이런 방향으로 자신들의 언어를 개발하고 있고 많은 성공을 거두었다. 우리가 프로젝트에서 어떤 언어를 선택한다면 그 언어의 특징은 물론 그 언어의 표준 라이브러리가 얼마나 잘 정리되었는지도 반드시 고려해야 할 것이다.
절대 기준은 없다
앞에서 프로그래밍 언어의 선택 기준을 몇 가지 언급했지만, 사실 프로그래밍 언어를 선택하는 절대적인 기준이란 없다. 바꿔 말하면 거의 모든 요소를 고려해도 부족하다는 말이 될 수도 있다. 언어의 특징을 규정짓는 요소들, 예컨대 가독성, 이식성(portability) 등도 모두 언어를 선택할 때 고려해야 할 요소들이고 각각의 생산성에 어떤 식으로든 영향을 미친다. 중요한 점은 프로젝트 시작에 앞서 몇 가지 선택된 기준을 바탕으로 몇 개의 프로그래밍 언어를 평가한 후에 프로젝트 언어를 결정하는 신중함을 가지라는 점이다. 프로젝트 초반의 시간 절약은 나중에 더욱 큰 화살이 되어 돌아올 수 있음을 항상 명심해야 한다. [maso]