Pacemaker를 통한 Clustering (서버 이중화)

Clustering이란 두대 이상의 서버가 하나의 서버가 처리하는 것처럼 보이도록 서버들 간의 확립된 연결(Establishing Connectivity) 입니다. 이 클러스터링은 장애 대응 시스템(fail-over), 부하분산(load balance) 시스템 혹은 병렬처리 프로세싱에 사용될 수 있는 기술입니다. 한 예로, 장애 대응 시스템의 클러스터링은 응용프로그램과 서비스의 고가용성(High-Availability)을 유지하기 위해 동시 작동하는 서버들의 집합입니다.  예를 들어 어떤 이유에서 하나의 노드에 장애가 생기면 다른 노드는 그 처리를 받고 사용자에게 무중단의 서비스를 제공합니다. < Clustering Diagram >   클러스터 관리는 별도의 서버에서 수행되며 두 노드를 관리합니다. 이 관리서버는 주기적으로 두 노드에 상태 점검(Hearbeat)하여 하나의 노드에 장애가 발생시 다른 노드로 부하를 이전하는(Fail-Over) 역할을 수행합니다.   클러스터를 사용하려면 업계에서 사용하는 클러스터링의 종류, 장단점을 알아야 합니다.   클러스터링의 장점 클러스터링은 확장가능한 솔루션입니다. 이는 나중에도 자원을 추가할 수 있습니다. 또한 Fail-over의 기본 속성이 있어 서버 작업 시 무중단으로 작업이 가능합니다. 클러스터링의 단점 비용이 매우 높습니다. 하드웨어의 고 사양과 평범하지 않는 설계는 더 많은 비용이 요구되지만 비용대비 효과는 더 크게 작용합니다. 더 많은 서버는 모니터링과 유지보수의 어려움으로 더 많은 비용이 발생합니다. 노드간 데이터 동기화 등의 이유로 노드의 처리량도 non-clustering 보다 더 많은 부하가 발생합니다.   근래 컨설팅 중 HA를 위해 시스템 이중화한 사례를 소개할까 합니다. WEB, WAS, DB는 A(Active)/A 구조로 tire간 클러스터링 구조이며 서비스를 위한 Daemon은 A/P(Passive) 구조입니다. 이로 인해 L4는 A/P 구조이며 SVC의 Daemon을 감지하여 A/P 방식으로 트래픽을 제어합니다. 결과적으로 Active SVC1는 L4로 트래픽을 보내 재귀호출 하는 방식이 되어버립니다. 서버 자체적으로 해결할 수 있는 프로세싱이 불필요 트래픽과 부하가 발생하게 됩니다. < 서비스 flow > 이를 보완하기 위해 HA Cluster 구성을 위한 여러 솔루션 중 본 글에서는 요즘 OpenSource에 사용중인 “Pacemaker”를 다뤄보겠습니다. Pacemaker는 Cluster 관리를 위해 근래 apache storm, openstack 등에 사용하는 분산 코디네이터 입니다. Pacemaker 는 크게 5가지 기능이 있습니다. 응용프로그램 모니터링 및 제어기능 : 프로세스(리소트 에이전트:RA)를 모니터링 하고 제어합니다. 네트워크 모니터링 및 제어기능 : 클러스터 노드에 주기적으로 ping을 전송하여 연결 상태를 모니터링 합니다. 노드 모니터링 기능 : Heartbeat을 이용하여 노드를 모니터링하고 STONITH(Shoot The Other Node In The Head : Fencing Daemon) 기능은 통신 불가한 노드의 전원을 가제로 중지하여 split-brain(클러스터 내의 모든 노드들은 자신이 Primary 노드라고 인식하여 네트워크의 일시적 단절, 과반수 이상의 노드가 장애를 일으키는 현상)을 피합니다. 자기 감시 기능 : Pacemaker 관련 프로세스 감시합니다. 디스크 모니터링 및 제어기능 : 지정된 디스크 읽기를 정기적으로 실시, 액세스 상태를 모니터링 합니다.   그 외에 다양한 구성의 HA 클러스터에 대응합니다. 서비스 수준의 실패 시 노드와 서비스를 탐지하고 복구합니다. 공유 스토리지가 필요없이 스토리지에 종속되지 않습니다. 스크립트로 클러스터링 할 수 있다면 어떠한 서비스에도 종속되지 않습니다. 데이터 무결성을 보장하는 펜싱(STONITH)을 지원합니다. 대형, 소형 클러스터를 지원합니다. 중앙 컨트롤 형식의 quorate(quorum)과 계층구조의 resource-driven cluster 모두 지원합니다. 거의 대부분의 이중화 구성을 지원합니다. 자동으로 복제된 설정은 임의의 노드에서 업데이트 할수 있습니다. 동일지역이나 원격지에 걸처 광범위하게 클러스터를 구성할수 있습니다. 멀티 노드에서 활성화할 서비스에 대해 복제 기능 지원을 합니다. 서비스에 대한 멀티모드(master/slave, primary/secondary)를 지원합니다. 통합된 클러스터 관리 도구를 제공합니다. 보통 데이터 전환 방식과 노드 수에 따른 분류 두가지 방식이 쓰입니다. 데이터 전환 방식으로는 공유 구성, 비공유구성(PG-REX, twitter나 Instagram에서 사용하는 DRDB)와 노드 수에 따른 분류로는 1+1(Active/Standby구조), N+1(다수의Active노드와 하나의 Standby노드), N+M(다수의 Active노드와 다수의 Standby노드)로 분류합니다.   코어 컴포넌트는 다음과 포함합니다. Pacemaker : 핵심이며, 노드의 클러스터 집합에서 상호 관련 서비스를 시작, 복구를 조정하는 분산 상태를 유지합니다. Corosync : Corosync API는 노드 멤버에게 메시지(노드의 프로세스 상태)와 quorum을 제공합니다. libQB : 재사용을 통해 노드의 성능을 주목적으로 하는 라이브러리 입니다. 이는 고성능의 로깅, 트레이싱, ipc, 폴링을 제공합니다. Resource Agents : Pacemaker가 서비스를 관리할 수 있는 추상 개념입니다. 논리적으로 클러스터가 start, stop, 상태 점검을 위한 로직을 포함합니다. Fence Agents : Pacemaker가 장애상태인 노드를 분리할 수 있는 추상 개면입니다. 노드의 전원을 끄거나 네트워크 혹은 공유 스토리지의 엑세스를 막음으로 팬싱 기능을 수행합니다. OCF specification   내부 컴포넌트의 구성은 다음과 같습니다. CIB : Cluster Information Base CRMd : Cluster Resource Management daemon LRMd : Local Resource Management daemon PEngine or PE : Policy Engine STONITHd : Fencing daemon   < Pacemaker Stack >     <...
read more

Infrastructure as code (AWS CloudFormation)

클라우드 서비스 유형으로 몇가지가 있습니다. IaaS(Infrastructure as a service)는 인프라를 인터넷 서비스로 제공하며 플랫폼을 제공하는 PaaS(Platform as a service)와 소프트웨어를 제공하는 SaaS(Software as a service) 3가지 유형이 대표적입니다. 요즘은 LXC(Linux Container) 기반의 Docker Container 호스팅 서비스를 하는 CaaS(Container as a Service)등  여러 서버스도 나타나고 있습니다. < 이미지출처 : https://blogs.technet.microsoft.com/kevinremde/2011/04/03/saas-paas-and-iaas-oh-my-cloudy-april-part-3 > AWS에서  IaaS와 PaaS 서비스를 이용할수 있으며 또한 Infrastructure를 Code화 하여 관리가 가능합니다. Infrastructur as Code란 “인프라를 코드화 한다”, “인프라를 코드로 기록한다”의 의미입니다. Infrastructure as Code라는 말은 , 2005년 경 Puppet과 Chef 등 Configuration Management Tools이 원조이며, 현재 Infrastructure as Code의 흐름에 미친 영향은 큽니다. 현 Chef 사의 CTO Adam Jacob의 2008년 4월경 공개한 Why your startup needs an Automated Infrastructure의 24페이지에서 사용되기 시작했습니다.   인프라를 코드화 하면 시스템의 가독성이 높아집니다. 시스템 버전 관리르 할수 있습니다. 응용프로그램 개발 방법론을 인프라에도 적용할 수 있습니다. 개발의 테스트 주도 개발과 마찬가지로 코드화된 인프라 역시 테스트를 기록하고 인프라 코드에 대해서 테스트를 수행할수 있습니다. 이 테스트 주도 인프라는 직접 확인을 자동화 할 수 있으며 인프라 코드를 리팩토링 할 수 있습니다. 또한 관리적인 측면에서 인프라 코드 변경의 영향을 조기에 감지 할수 있고 인프라의 지속적인 개선을 수행할 수 있게됩니다.   이 코드화된 인프라를 이용하여 올 2월 AWS Region이 국내 정식 오픈되어 Tokyo Region에 구축한 AWS 환경을 CloudFormation(AWS 서비스의 인프라 구성을 코드로 관리)을 사용하여 전산센터 이전하는 방법을 소개합니다. 초기 구축 시 CloudFormation을 이용하여 구성을 했으면 코드 재사용이 가능하나 수작업으로 구성한 환경은 CloudFormer를 사용하여 코드화하는 작업을 우선 진행합니다. ( 보통 글로벌 서비스는 하나의 Backend Office 와 다수의 Frontend Office(Localization) 구성시 Frontend Office는  코드 재사용에 아주 유용합니다. )   CloudFormer 기술문서 •    Step 1: Create a CloudFormer Stack •    Step 2: Launch the CloudFormer Stack •    Step 3: Use CloudFormer to Create a Template CloudFormer의 Launch 역시 CloudFormation 탬플릿을 통해 생성을 하고, 만들어진 서버(CloudFormer)를 통해 인프라 환경을 CloudFormation 탬플릿으로 생성을하게 됩니다.   https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#cstack=sn~AWSCloudFormer|turl~https://s3.amazonaws.com/cloudformation-templates-ap-northeast-1/CloudFormer.template   탬플릿은 UI를 제공하여 디자인으로 구성할수도 있고 Text 형식의 코드로도 작성할수 있습니다.   이 코드는 JSON 형식의 포맷이며 여러 스택으로 구분됩니다. Description : 탬플릿의 상세 설명을 기술합니다. Parameters : 사용자 입력 매개변수로 Resource내에 사용할수 있도록 변수를 입력받을수 있습니다. { "AWSTemplateFormatVersion":"2010-09-09", "Description":"Copyright (c) 2015 thlee@nextree.co.kr All right reserved.", "Parameters":{ "ServiceName":{ "Description":"Environment Type", "Type":"String", "Default":"test", "AllowedValues" : ["prod", "test"], "ConstraintDescription":"must be a valid Service name." } }, 123456789101112 {   "AWSTemplateFormatVersion":"2010-09-09",   "Description":"Copyright (c) 2015 thlee@nextree.co.kr All right reserved.",   "Parameters":{      "ServiceName":{         "Description":"Environment Type",         "Type":"String",         "Default":"test",         "AllowedValues" : ["prod", "test"],         "ConstraintDescription":"must be a valid Service name."      }   },   Mappings : 변수 설정 부분으로 선언된 변수는 Resource에서 참조할수 있습니다. 예에서는 us-east-1의 요소중 VPC, ExtELB1, ExELB2의 변수 값을 지정했습니다. "Mappings":{ "myVPCSubnetConfig":{ "us-east-1":{ "VPC" :"10.0.0.0/16", "ExtELB1" :"10.0.11.0/24", "ExtELB2" :"10.0.111.0/24" } } }, 12345678    "Mappings":{      "myVPCSubnetConfig":{         "us-east-1":{            "VPC"      :"10.0.0.0/16",            "ExtELB1"  :"10.0.11.0/24", "ExtELB2"  :"10.0.111.0/24"         }      }   },   Conditions : 조건 설정. 예에서는 Parameter 구문에서 입력받은 값을 비교합니다. "Conditions" : { "CreateProdResources" : {"Fn::Equals" : [{"Ref" : "EnvType"}, "prod"]} }, 123    "Conditions" : {      "CreateProdResources" : {"Fn::Equals" : [{"Ref" : "EnvType"}, "prod"]}   },   Resources : AWS Resource 설정부분으로 실제로 CloudFormation이 작업이 이뤄지는 구문으로 조건에 맞는 값으로 수행이 됩니다.  AWS::XXX::YYY 형식의 Type 항목은 미리 정의되있는 형식이며 기술문서에 각 Type별로 Syntax가 필수와 옵션으로 정의되어 있습니다. “Fn::FindInMap” 함수는 Mapping에 선언된 MapName의 top-level과 second-level 두개의 인자를 반환합니다.  Intrinsic 함수에 대한 자세한 내용은 기술문서를 참고. "Resources":{ "VPC":{ "Type":"AWS::EC2::VPC", "Properties":{ "EnableDnsSupport":"true", "EnableDnsHostnames":"true", "CidrBlock":{ "Fn::FindInMap":[ "myVPCSubnetConfig", { "Ref":"AWS::Region" }, "VPC" ] }, "Tags":[ { "Key":"Name", "Value":{ "Fn::Join" : [ "-", [ { "Ref" : "ServiceName" }, { "Ref" : "AWS::Region" } ] ] } } ] } }, }, 1234567891011121314    "Resources":{      "VPC":{         "Type":"AWS::EC2::VPC",         "Properties":{            "EnableDnsSupport":"true",            "EnableDnsHostnames":"true",            "CidrBlock":{               "Fn::FindInMap":[ "myVPCSubnetConfig", { "Ref":"AWS::Region" }, "VPC" ]            },            "Tags":[ { "Key":"Name", "Value":{ "Fn::Join" : [ "-", [ { "Ref" : "ServiceName" }, { "Ref" : "AWS::Region" } ] ] }             } ]         }      },   },   Output  : 탬플릿 Stack이 완료되면 내용을 출력할수 있습니다. 자동으로 생성된 인프라의 정보를 표시하기 위하여 유저가 설정합니다. "Outputs" : { "myVPCCIDR" : { "Description" : "VPC CIDR of the newly created VPC",...
read more

시작은 부담없이 클라우드(AWS)로…

Start-up 인프라를 클라우드로 구성하면 장점이 많습니다. 사업성이 보장되지 않는 상태에서 장비 구매비용(혹은 연단위 임대비용)과 장비 delivery에 대한 시간투자, 장비 관리 시간투자 등의 비용을 많이 절약할 수 있습니다.  이런 이점은 Start-up 기업들이 우선적으로 고려하는 인프라 환경을, 클라우드라는 가상의 환경으로 고려하는 이유이기도 합니다. 그러나 클라우드는 사용한 비용만큼 지불하는 구조임에도 불구하고, 결코 저렴하다고는 말할 수 없습니다. 또한 클라우드 환경의 관리가 편하다라고 말할 수는 없습니다. 비용 효율화를 위해 관리자(클라우드 인프라 관리자)는 쓸데없는 비용 누수에 신경써야하며 누구나가 의심하는 클라우드 환경의 보안 부분을 신경써야 합니다. 하지만 잘 구성되어있는 환경이라면, 저렴한 비용과 관리의 편리가 가능합니다. 처음 잘 구성되어야 한다는 선행조건을 만족하기 위해, AWS 클라우드 환경의 인프라 설계와 설계된 구성에서의 기본적이지만 필수적인 사항을 이야기 하려 합니다.  작년 하반기 정부의 클라우드 발전법 발의와 이번달(2016년1월) AWS 한국 지역 오픈으로, 지금까지보다 클라우드 환경이 더 많이 사용될 것으로 예상됩니다. 다음 그림은 WEB – WAS – DB 구조의 평범한 3-tire  아키텍쳐입니다.  CDN사용과 캐쉬용도의 in-memory 서버, 세션 클러스터링을 위한 No-SQL이 부가적으로 구성되있습니다.   AWS 아키텍쳐는 기본적으로 다음의 사항을 고려해야합니다. 1. HA(High-Availability) : SPOF(Single Point of Failure)제거 고가용성은 가상의 환경에서 서비스를 위한 필수적 요건입니다.  HA를 하나의 지역(Region)에 2개 이상의 가용영역((Availability Zone : AZ)) 구성과 DR를 위한 여러 국가(Region)를 이용하는 방법이 있습니다.(주: local서비스를 위해서 Backend 서비스는 HQ에 Frontend 서비스만 전국가로 배치하여 구성하는 경우가 많습니다.)  AWS가 99.5%의 신뢰성을 보장하지만, 0.5%의 실패 가능성 때문에 가상의 환경에서는 반드시 Fault-Tolerant 환경으로 구성해야합니다. 요즘 대부분의 솔루션(FOSS 혹은 상용제품)들은 HA구성과 Clustering를 지원합니다.  반드시 가상화 환경에서는 Standalone 상태의 SPOF를 제거하는 설계를 해야합니다. 2. 보안 보안은 귀찮고 불편하지만 클라우드 발전법의 정보보호 대책이 구체화되면서 좀더 신경을 써야될 부분입니다. AWS에서 제공되는 기본적인 서비스를 이용하여 최소한의 보안 구성을 할 수 있습니다. 다음 그림은 AWS에서 서비스를 위한 최소한의 VPC 구성을 나타냅니다. Public Subnet과 Private Subnet을 구분하고 Public 구간은 DMZ에 해당하는 구간으로 외부 ELB, Bastion Host만 위치시킵니다. 그외 biz logic 처리 서버들은 Private Subnet에 위치하여 외부로의 침입을 차단합니다. 이 VPC 환경과 Public/Private subneting은 기본으로 설계되어야 합니다.   다음 그림은 VPC에서 지원하는 Subnet/ RouteTable/ SecurityGroup / NetworkACL과의 보안관계를 나타냅니다. 보안 구성 요소를 서비스별로 나열하면 다음과 같습니다. IAM : ROOT계정은 credential을 생성하지 않습니다. ROOT계정은 MFA 인증으로 two-factor 인증으로 구성하며, 웹 콘솔 사용은 Admin 권한의 신규 유저(two-facto인증)를 사용합니다. EC2 : On-premis의 보안 수준에 준하여(iptable, TCPWapper등) 구성합니다. 사설망과 공인망의 EC2 MasterKey(KeyParis)는 분리하여 보관합니다. EC2는 Role을 부여하여 서버내에 혹은 AWS API 소스내 Credential를 저장하지 않습니다.  VPC : 사설망과 공인망을 분리하여 Tier간 subneting으로 구분합니다. RDS를 포함한 서비스 EC2는 반드시 사설망에 위치시킵니다.  SecurityGroup : ALL(0.0.0.0/0)의 Source, Port는 제거합니다. NetworkACL : Subnet간 ACL를 구성합니다. RouteTable : Subnet 간 통신을 위한 라우팅을 설계합니다. Bastion Host : 사설망의 EC2는 Bastion Host를 통해서만 접속하도록 구성합니다. 평소 사설망 EC2 접속이 필요없다면 stop상태를 유지합니다. NAT G/W : 사설망의 EC2는 외부접근을 위해 NAT G/W를 이용합니다. NAT EC2는 외부에 취약요소가 됩니다.  S3 : bucket의 policy를 적용하여 bucket내 자료 접근을 통제합니다.  CloudFront : WAF를 구성하여 XSS, SQL-Injection의 위협을 완화합니다.  ELB : SSL 적용으로 웹구간 암호화를 적용합니다. RDS : DB관리자의 원격지 서버접속은 SSL을 이용합니다. EBS는 Encrypt 옵션을 적용합니다. (Oracle이면 HSM를 적용하여 TDE로 구성합니다.) 참고가 될 AWS 백서 : http://media.amazonwebservices.com/AWS_Security_Best_Practices.pdf   3. Decoupling = Loose-coupled => 자동화 사용 리소스를 넉넉히 할당하여 서비스를 하면 리소스 관리는 편하지만 그만큼 비용이 발생하게 됩니다. 클라우드의 자원 50% 내외의 사용량을 유지할 정도로 리소스를 할당하고, 클라우드의 강점인 Auto-Scaling 기능을 이용하면 비용 효율화를 할 수 있습니다. Auto-Scaling은 리소스의 Spike 대응으로 scale in/out, scale up/down이 유연하게 자동으로 구성할 수 있습니다. AWS에서 서비스되는 ELB, DynamoDB, SQS등 Auto-Scaling을 자체적으로 지원하는 서비스를 우선으로 고려하고, 자체 서비스 특성상 솔루션을 도입해야할 경우 scaling에 적합한 구조로 구성해야합니다. 예를 들어, WEB서버와 WAS서버 연동을 위해 중간에 Internal ELB를 구성하여 WEB서버 증설시 WAS가 영향을 받지 않고, WAS 증설시 WEB서버에 영향을 받지 않는 구조로 구성해야 합니다. 이는 기본적으로 tier간 decoupling으로 구성해야 하는 이유입니다. Auto-Scaling 기능의 비용 절감 이외   Java heap 메모리 조절로 EC2 type을 다운 사이징   예약인스턴스(Reserved Instance) 도입 (단, RI 계약은 해지시 제약이 있으므로 신중해야합니다.)   유휴시간의 개발서버(RDS포함)는 STOP   GP2의 Brusting...
read more

버추얼 머신을 통한 개발 환경 설정

스마트폰이 처음 등장했을 때, 내가 원하는 기능을 제공하는 앱을 검색해서 설치해 사용하고, 더이상 필요가 없으면 바로 없앨 수 있는 기능을 보고, 개발환경도 설치나 설정에 있어서 앱 스토어와 같은 곳에서 필요한 도구나 프로그램을 가져와 사용하도록 갖추어진다면, 정말 편리하고 간편할 것 같다는 생각을 했었습니다. 이러한 상상을 했던 것이 불과 몇년전인데, 상상했던 환경을 구성한다는 것이 이제는 현실이 되는 것 같습니다. 현실이 되게 하는 그것이 바로, ‘가상화 기술’입니다. 요즘과 같이 시스템 구성 요소가 다양한 OS, 다양한 서버, 다양한 솔루션들로 이루어지는 환경에서는 개발환경을 하나의 머신이나 OS에 구성하기가 쉽지 않습니다. 반대로, 여러 머신이나 OS에 있는 내용을 하나의 개발 머신또는 OS로 구성하는 것도 쉽지 않습니다. 여기에는 실제 운영환경과 다른 개발환경을 만들어야하는 노력이 필요하며, 다양한 설정 방법을 통해 테스트 및 운영 서버에 배포하도록 해야하기 때문에 그로 인한 부담이나 노력은 상당합니다. 또한 운영팀에서도 하나의 소스를 여러 프로젝트팀들이 접근하여 각자의 개발환경에 맞게 세팅하도록 만든다던지 하는 노력이 필요하고, 여러 개발환경에서 개발된 내용을 운영계에 배포하고자 할 때에는 개발자 로컬 환경이나 소스에 설정된 내용이 각기 다르도록 해야하기 때문에 그로 인한 각별한 주의가 필요하고 배포에 대한 부담 역시 증가합니다. 최근 이러한 부담을 버추얼 머신(Virtual Machine, VM) 기술을 통해서 어느 정도 줄일 수 있는 방법들이 강구되고 있으며, 실제로 VM을 통한 CI 기술(참조 : Travis CI)까지도 등장하고 있는 상황입니다. 따라서, 본문에서는 오픈 소스 버추얼 머신인 VirtualBox를 통해 Linux를 설치하고, 여기에 개발 환경을 설정하여 로컬 PC에서 VM 상의 별도 OS에 다양한 개발 환경을 설정하고 개발할 수 있는 방법을 소개하고자 합니다. 가상 머신(Virtual Machine) 이란? 가상 머신(Virtual Machine, VM)은 단순하게 컴퓨터 기능을 가상으로 흉내내는 에뮬레이터 기능을 하는 프로그램입니다. 1960년대를 거슬러 올라가면 시스템 가상 머신과 프로세스 가상 머신이라는 영역에서 출발했으며, 이는 하나의 머신에서 여러 사용자들이 사용하도록 하는 기술을 발전시키다보니 나타난 영역입니다. 이러한 VM 기술은 하드웨어나 OS 영역까지도 가상으로 만들 수 있도록 발전하여, 현재는 서로 다른 OS 상에서 다양한 OS를 설치하고 가동할 수 있습니다. (참고 : 가상화 개요) 예를 들어, Windows OS 환경에서 VM 프로그램을 설치하여 Linux나 또 다른 Windows OS, 심지어 Unix나 Mac OS 까지도 설치할 수 있으며, 이 OS 위에서 하드웨어까지도 가상으로 실행할 수도 있습니다. 특히, 이러한 VM 기술은 클라우드나 서버 가용성 기술까지 적용되어, 단순히 사용자 PC에서의 가상화를 넘어 서버 기술까지도 확장되고 있는 추세입니다. 로컬 PC에서의 가상 머신 종류 로컬 PC는 크게 Windows, Mac, Linux로 나뉘며, 이러한 OS에서 사용할 수 있는 소프트웨어는 유료인 VMware와 Paralles가 대표적이고, 오픈 소스로는 VirtualBox가 대표적입니다. (참조 : VM 애플리케이션 종류) 최근 Microsoft에서도 Windows 10을 본격적으로 배포하면서 Windows 또는 iOS에서 실행되는 앱을 Windows 10 OS에서도 실행할 수 있는 VM인 Islandwood 프로젝트를 오픈소스화 했습니다. (관련기사 : Islandwood 프로젝트 오픈소스화) VM을 사용하여 점점 더 많은 영역들에서 더 확장된 기술을 사용하도록 지원하고 있는 추세입니다. VirtualBox 설치하기 VirtualBox는 설치가 아주 간단합니다. virtualbox.org 사이트에 접속해서 로컬 OS에 해당하는 파일을 다운받아 설치하면 됩니다. 일반적인 VM이 그렇듯이 크게 Windows, Mac OS X, Linux 등을 지원하며, 설치한 프로그램을 실행 후 ‘새로 만들기’를 이용해서 또 다른 OS를 설치하면 됩니다. VirtualBox에서 Linux 설치 Linux를 설치하려면 CentOS나 Ubuntu에서 설치파일을 다운로드 받고, VirtualBox를 통해 설치 파일(통상 이미지 파일)을 지정해주면 됩니다. 개발 환경을 구성할 때 Oracle DB를 설치해야 한다면, Ubuntu 보다는 CentOS를 설치하는 것이 Oracle 설치 과정을 좀 더 쉽게 진행할 수 있는 방법입니다. Linux 배포 이미지를 다운로드 받았다면, VirtualBox에서 ‘새로 만들기’ 메뉴를 통해 해당 설치 파일(이미지 파일을) 지정해서 설치를 하면 됩니다. 가상 머신을 만들때 설치에 필요한 메모리나 저장소 용량은 선택하도록 되어 있으며, 적정한 값을 입력 혹은 조정하여 만들면 됩니다. 최초 시작시 실행할 설치 파일을 지정하게끔 되어 있으며, 해당 설치 이미지 파일을 지정하여 절차에 따라 OS 설치를 진행하면 됩니다. VirtualBox를 개발환경으로 사용하기 VirtualBox에 Linux가 설치되면 필요한 소프트웨어를 Linux에 설치하여 개발환경을 갖추어서 사용하면 되는데, 이러한 개발환경을 갖추는데에 필요한 지식이 네트워크를 구성하는 방식입니다. VirtualBox는 다양한 네트워크 방식을 지원하지만, 개발환경에서는 외부 네트워크가 연결되지 않더라도 VirtualBox가 설치된 호스트와 VirtualBox 내에 설치된 게스트와의 통신이 유지되는 것이 중요합니다. 따라서 이를 위해 호스트 전용 네트워크(Host-only networking)를 사용합니다. 이 네트워크 방식은 호스트와 게스트 머신끼리 내부 IP를 사용하여 연결되기 때문에 외부 인터넷 연결과 상관없이 로컬...
read more

서버룸이 아니라 서버가든(garden)입니다.

서버룸이 아니라 서버가든(garden)입니다.
서버룸(Server Room)에서 나오는 소음이 신경쓰인다. 그렇다고 서버룸의문을 닫을 수도 없다. 내부 열기가 대단하다. 주말에 혼자 사무실에 있을 때는 서버룸을 닫았다 열었다를 반복하기도 한다. 거대한 랙과 요란한 팬소리는 언뜻 서버의 위엄을 보여주는 듯 하지만, 요즘 시대에는 어울리지 않는 느낌일 뿐이다. 소음, 에너지 낭비, 열기, 그리고 공간 낭비까지 보태서 쾌적해야할 사무공간을 망치는 골치덩이일 뿐이다.  그래서 이 넘들을 어떻게든 손을 보겠다고 벼르고 있었다. 2013년 사무실을 바로 옆 건물로 이사를 했다. 기회가 왔다. 시꺼먼 사각 고철덩어리 모양을 하고 있는 랙과 서버를 중고로 팔아 치웠다. 그리고 기존 서버의 용량보다 한 단계 더 높은 수준으로 장비를 준비했다. 6테라 NAS 2대, 맥미니 서버 2대, 에어포트 익스트림 2대. 이 세 종류 만으로도 기존 서버를 훌쩍 뛰어 넘었다. 거기다 모든 사무실 컴퓨터는 무선으로 연결하기로 했다. 따로 서버룸을 마련할 필요가 없다. 여섯 대의 기기가 차지하는 공간은 작은 테이블이면 충분했다. 앓던 이를 뺀 것처럼 속이 다 시원했다. 사무실에서 더 이상 서버의 소음은 들리지 않았다. 대신 건물 옆의 1호선 기차소리가 그 자리를 대신했다. 하지만, 가끔씩 여행의 추억을 들춰주니까. 그래서 낭만적으로 들리니까 참아줄 수 있다. (이미지출처:http://jordaneunson.com/wp-content/uploads/2010/05/IMG_0256.jpg) 시간이 흐르면서 여섯 개의 기기는 사람들의 관심 밖으로 사라져갔다.  아무런 소리 없이 아무런 오류도 없이 너무 잘 돌아가다 보니, 어느 누구의 손길도 가지 않은 탓이다. 정전이 되어도 알아서 재시동되고, 웬만한 문제는 알아서 진단하고 수정한다. 당연히 작고 이쁜 기기들은 먼지를 한 겹 한 겹 뒤집어 쓰기 시작했다. 이 기기옆에 멋없이 엎드려 있는 길쭉한 허브는 네트워크 케이블 몇 개를 물고 있다. 자연스럽게 네트워크 케이블, 전원 케이블 등이 뒤엉켜 함께 먼지를 뒤집어 쓴다. 가끔씩 닦아 주지만, 서너 달 잊어버리는 일이 흔하다 보니 기기들은 당연히 먼지 속에서 존재감을 서서히 잃어갔다. 이대로 둘 수 없다는 생각이 고개를 들기 시작했다.당번을 정해두고 돌아가며 청소하는 것으로는 부족하다. 여섯 개의 이쁜 기기에 대한 예의를 어떻게 갖출까하는 고민이 시작된다. 그 즈음 눈이 자꾸 침침해서 불편했다. 친구에게 하소연을 했더니 하늘과 푸른 숲을 자주 보라 한다. 하루 종일 모니터만 들여다 보며 일하는 소프트웨어 개발자에게 하늘과 숲을 볼 여유는 없다. 일을 한 번 시작하면 문제를 다 풀 때 까지 자리를 뜨지 못하는 습관 때문일게다. 그래서 소프트웨어 개발자의 눈은 편할 날이 없다. 하늘이나 숲을 보러 밖으로 나갈 수 없다면 나무라도 사무실에 들여놓으면 어떨까 하는 생각이 들었다. 그 생각이 들자마자 곧바로 서버 가든(??) 구축 계획이 머리를 휙 스쳐 지나갔다. 네트워크 허브(HUB)와 각종 케이블을 숨긴다. 서버 기기를 나무아래 둔다. (서버 기기도 좋아하겠지…) 한 술 더 떠서, 음악이 흐르면 좋겠다. 세 가지 바램을 갖고 준비에 들어갔다. 허브와 케이블을 감추려면 받침대가 필요하다. 옥션을 열심히 뒤져서쓰임새에 꼭 맞는 원목 받침대를 샀다. 다음으로 오디오가 필요하다. 개발실에는 음악이 흘러야 하니까. 그 오디오는 NAS나 맥미니 서버와 잘 어울려야 한다. 이 컨텍스트에서는 음질보다는 외모가 중요하다(죄송^^). 한 마디로 걸그룹급의 오디오가 필요하다. 사무실에 있던 시크한 스타일의 오디오는 직원에게 분양하고, 아이리버에서 만든 하얀 오디오를 주문했다. 마지막으로 나무가 필요하다. 아는 사람이 딱 어울리는 상품을 소개해 주었다. 이제 세 가지 모두 갖추었다. (상품 검색에 많은 시간을 들였기에, 필요하신 분들의 시간절약을 위해 링크도 함께 걸어둡니다.) 원목 받침대 (상품명: 프로방스원목화분대, 18,900 x 3개) 오디오(상품명: iRiver IA160, 16만원 x 1대) 나무 화분(상품명: 네 가지 정원, 100,000 x 2)   서버가 있던 테이블을 깨끗하게 닦고, 원목 받침대를 두고, 기기를 배치했다. “백문이 불여일견”이라 했다. 자 보실까요? 서버 정원을… 반대 쪽에서 봐도 봐줄 만 하다. 아니 멋지다. 남은 화분을 개발자 사이에 하나씩 배치했다. 서로 보고 싶지 않을 때도 좋고, 나무가 보고 싶을 때도 좋고, 서로 보고 싶을 때도 좋다. 숲은 아니더라도 몇 그루의 나무가 들어왔을 뿐인데 분위기가 사뭇 달라졌다. 비주얼, 사운드, 성능 모두 만족스럽다. 오디오는 하루 종일 클래식 음악을 들려준다.  물론 국악, 그것도 판소리가 흐르는 시간이면 개발실에 작은 반란이 일어난다. 우리는 평화로운 개발실로 한 걸음 다가섰다. 소음과 열기의 상징인 서버룸이 두 단계 변신을 거쳐서 서버 가든이 되었다. 사무실을 방문하는 분들이 저게 뭐냐고 물어본다.  “서버가든”이라고 말하고 싶은데 쑥쓰러워 그냥 회사 서버들이라고 대답한다. 하지만 내 마음 속에서는 “Nextree Server Garden”입니다라고 대답하고 있다.  다들 신기하다고 한다. 회사 개발환경이 하나둘 클라우드로 이사가고 있어서 내부 서버가 예전 만큼 중요하지 않다. 그럼에도 “Nextree Server Garden(version one)”은 또 다른 변신을 꿈꾼다....
read more

알고보면 쉬운 웹서비스

알고보면 쉬운 웹서비스
웹 서비스를 적용한 애플리케이션을 구축하는 것은 쉽지 않습니다. 그러나 웹서비스의 개념과 구성을 큰 그림으로 이해한다면, 웹서비스를 구축하는 과정이 다르게 느껴질 수 있습니다. 오늘은 그동안 웹서비스를 공부하면서 개운치 않았던 부분들을 긁어드리려 합니다. 알고보면 쉬운 웹서비스에 대해 함께 살펴봅니다.   왜 웹 서비스를 선택할까요? 먼저 왜 웹서비스를 사용하는지에 대한 궁금증부터 해소해볼까요. 우리가 웹서비스를 사용하는 목적 중 핵심은 바로 플랫폼 중립(neutrality)입니다. 하나의 서비스를 제공하면, 다양한 플랫폼의 클라이언트가 서비스를 받아서 사용할 수 있도록 위함입니다. 외부 애플리케이션의 기능을 연결하기 위해서는 여러 기술적 제약이 따르기 마련입니다.  하지만 현재, 많은 애플리케이션은 PC 뿐 아니라 모바일기기와 태블릿 PC 등 다양한 기기가 사용 가능합니다. 하나의 기능을 각 플랫폼에 맞게 붙이는 것은 아주 비효율적이기 때문에, 플랫폼에 상관없이 기능을 제공하고 사용할 수 있는 기술이 필요했습니다. 이러한 목적을 가지고 애플리케이션을 서비스로 제공하자며 등장한 아키텍쳐가 SOA(Service Oriented Archetecture)이며, 이를 실현시키는 방법이 바로 웹서비스인 것입니다. 하지만 웹서비스를 이해함에 있어서, 플랫폼 중립만큼 중요한 것이 독립성입니다. 플랫폼 중립을 이루겠다는 것은 서비스의 기술 셋을 알지 못해도 클라이언트는 서비스를 사용할 수 있도록 해주겠다는 의미가 담겨있습니다. 클라이언트가 플랫폼에 관한 결합도를 제거하여 재사용성을 크게 높일 수는 있었지만, 효율적인 상호작용을 위해서는 플랫폼 이외의 발생하는 결합도를 고려해야 합니다. 즉 기술셋 뿐 아니라 서비스를 사용하기 위해서 알고 있어야 하는 것들을 최소화시키는 것이 좋습니다. 그래야만 클라이언트와 서버간의 느슨한 결합을 이룰 수 있고 서버와 클라이언트가 각각 독립적인 진화를 지속할 수 있습니다.     예를 들어, 웹서비스 소유자가 서비스의 데이터 타입을 하나 변경했다고 가정합니다. 클라이언트는 변경된 데이터타입을 적용시키기 위해서 클라이언트 쪽의 로직을 수정해야만 합니다.  클라이언트는 단순히 UI를 표현하는 애플리케이션일 수도 있고, 또 다른 기능을 연결하는 애플리케이션일 수도 있습니다. 클라이언트 쪽에서도 충분히 기능구현에 대한 복잡함이 존재하고 있습니다. 그런데 서비스의 진화에 영향을 받게 되면 그림1과 같이 클라이언트는 서비스보다도 무수히 많은 변화를 적용해야만 합니다. 즉, 좋은 웹서비스란 기존 클라이언트의 중단없이 서비스를 진화시킬 수 있어야 합니다. 이렇게 웹서비스는 독립성을 강조하고 있습니다. 때문에 제대로 웹서비스를 설계한다면 서버와 클라이언트가 독립적으로 진화할 수 있기 때문에, 유지보수 및 재사용성이 큰 이점이 됩니다.   웹서비스는 어떻게 연결될까요? 이번엔 비즈니스 로직의 흐름에서 웹서비스가 어떻게 자리잡고 있는지 알아봅니다. 웹서비스의 서비스와 클라이언트는 어떠한 레이어로 제한되어 있지 않고 기능을 제공하고 받는 역할에 따라 구분합니다. 반드시 서비스 프로바이더는 비즈니스로직의 구현체가 있고 클라이언트는 UI구현만 있는 것은 아닙니다. 하나의 기능을 처리하기 위해서 여러 웹서비스 호출이 일어날 수 있고, 클라이언트는 또다른 웹서비스를 제공하는 프로바이더가 될 수 있습니다. 그래서 웹서비스는 어딘가 위치하고 있는 비즈니스 로직의 흐름의 한 영역이라고 말합니다.   위 그림2와 같이 웹서비스는 비즈니스로직과 비즈니스로직을 연결합니다.  먼저 서비스 소유자는 제공하려는 비즈니스 로직을 구현합니다. 이렇게 바로 제공할 수도 있지만, 웹서비스로 제공하기 위해서는 인터페이스에 제공하려는 서비스를 나열합니다. 그럼 서비스를 클라이언트들이 사용할 수 있도록 특정 위치에 제공해야 합니다.  웹서비스의 특징 중 하나는 서비스가 네트워크상의 공간에 위치하고 있어야 한다는 것입니다. 그래서 웹서비스는 서비스를 설명하는 언어인 WSDL을 사용합니다. WSDL을 통해 서비스를 구성하는 오퍼레이션과 요청/응답 메시지 구조, 데이터 타입 등을 인지할 수 있습니다. 때문에 WSDL이 어디에 있는지만 안다면 바로 적용해서 서비스를 사용할 수 있기 때문에, 적용이 아주 편리합니다. 그럼 WSDL은 어디에 위치하고 있을까요? 흔히 WSDL이 위치하는 곳을 UDDI(Universal Description Discovery & Integragion)라고 설명하는 경우가 많습니다. 하지만 WSDL은 UDDI에 있을 수도 있고 혹은 없을 수도 있습니다. UDDI는 웹서비스 공개저장소라고 생각하시면 이해가 쉽습니다. WSDL을 찾을 수 있는 마켓이라고 보시면 됩니다. 클라이언트가 UDDI에서 WSDL을 Find해서 호출한다는 문구를 많이 보셨을 겁니다. UDDI는 여러 WSDL을 가지고 있는 마켓이기 때문에 이 곳에서 원하는 WSDL을 이름별, 카테고리별로 검색하고 사용하는 공간입니다. 원하는 서비스를 찾아서 적용한다는 의미가 바로 이것입니다. 하지만, UDDI가 아니더라도 네트워크상으로 접근이 가능한 곳에 위치시킨다면 웹서비스는 성립됩니다. 따라서 반드시 WSDL이 UDDI에 존재하는 것은 아닙니다. 실무에서는 주로 서비스 개발사와 클라이언트 개발사 사이의 협약을 통해 WSDL의 위치를 공개합니다. WSDL은 단순히 서비스에 관련한 정보를 가지고 있기 때문에, 프로젝트 초기에 웹서비스를 제공하는 쪽과 받는 쪽의 협약이 필요합니다. 이러한 과정을 서비스 협약이라고 합니다. 서비스 협약을 통해서 웹서비스의 위치, 성능, 품질 등에 관하여 논의합니다. 하지만 서비스 협약에서는 서비스를 호출할 때 어떻게 보내야하고 어떤 형태로 응답받는지에 대한 세부내용은 논의하지 않습니다. 이 것은 WSDL을 통해 유추할 수 있기 때문입니다. 그렇다면 실제 프로젝트에서 WSDL만 가지고 어떻게 웹서비스를 연결할 수 있는지 알아봅니다.   우리는 어떻게 웹서비스를 호출할 수 있을까요?...
read more

CI (Continuous Integration) 이란?

CI (Continuous Integration) 이란?
소프트웨어 개발에서 유지보수로 연결되는 지점은 소스관리/빌드/배포의 활동이 됩니다. 물론, 소스코드 수정이 발생되기는 하지만, 소스관리/빌드/배포의 활동이 주로 발생하기 마련이며, 이는 유지보수 시점에 확실한 절차와 방법을 필요로 합니다. 개발 시점에 이러한 활동을 지원하는 기법 중에 CI (Continuous Integration)가 있으며, 이는 오래 전부터 소프트웨어 개발에 있어서 위험을 줄이는 방식으로 사용되고 있었습니다. CI 라는 용어가 직접적으로 사용되지는 않았지만, 1993년 Mattew Pittman이 쓴 ‘Lessons Learned in Managing Object-Oriented Development’라는 논문[참조 1]에서 “예정된 통합(scheduled integration)” 이라는 용어를 사용하고 있으며, 이는 CI를 수행할 때의 한가지 이슈에 대해 완벽한 테스트의 부족을 언급하고 있습니다. 즉, CI가 단순히 소스코드의 빌드와 배포만을 의미하지 않고 그 안에는 소스코드를 검증할 수 있는 방법이 분명 필요하다는 것을 말하고 있습니다. 코드 컴플리트(Code Complete)라는 책을 쓴 Steve McConnell은 1996년 ‘Daily Build and Smoke Test'[참조 2]라는 글에서 Microsoft사에서 일일 빌드 체계를 통해서 통합에 대한 위험을 격감사키고, Smoke Testing을 통해서 품질을 확보하고 있다는 내용을 언급하고 있습니다. 특히, 일일 빌드는 프로젝트에서 심장 박동(heartbeat)에 비유한 Jim MacCarthy의 말을 인용하여 일일 빌드(daily build)를 하지 않는다면, 그 프로젝트는 죽은 것과 같다고 표현하고 있습니다. 1990년대 후반부터는 XP(Extreme Programming)에서 CI를 기법으로 채용했으며(참조 : http://www.extremeprogramming.org/rules/integrateoften.html), Martin Fowler의 Continuous Integration이라는 글에서 본격적인 CI 기법에 대한 기본 원칙이 만들어지기 시작헀습니다. 이 글에서 Fowler는 자동화된 일일 빌드에 대한 기본 원칙을 다음과 같이 4가지로 설명합니다. 모든 소스 코드가 살아있고(현재 실행되고) 어느 누구든 현재의 소스를 접근할 수 있는 단일 지점을 유지할 것 빌드 프로세스를 자동화시켜서 어느 누구든 소스로부터 시스템을 빌드하는 단일 명령어를 사용할 수 있게 할 것 테스팅을 자동화시켜서 단일 명령어를 통해서 언제든지 시스템에 대한 건전한 테스트 수트를 실핼할 수 있게 할 것 누구나 현재 실행 파일을 얻으면 지금까지 최고의 실행파일을 얻었다는 확신을 하게 만들 것 위의 원칙들은 기본적으로 CI 도구들이 지원하고 있지만, CI가 단순히 도구만으로 구현할 수 있는 부분은 어디까지나 한정적이라고 보면 됩니다. 단순히 형상관리도구나 CI 도구, 테스트 프레임워크를 적용했다는 사실만 가지고는 CI를 적용한다라고 말할 수는 없다는 의미입니다. CI를 적용하는데 있어서 주요한 부분을 자세히 살펴보면 다음과 같이 4가지 영역으로 구분을 해볼 수 있습니다. 형상관리 항목에 대한 선정과 형상관리 구성 방식 결정 단위테스트/통합테스트 방식 비기능 속성(품질 속성) 관리 방식 빌드/배포 자동화 방식 1. 형상관리는 CI를 위해서는 필수로 적용해야 하는 기법 중 하나 Martin Fowler도 CI에 대해 언급하면서 소스 접근에 대한 단일 지점을 거론했는데, 이와 같이 형상관리는 CI에 있어서 반드시 적용해야 하는 기법 중에 하나입니다. 국내의 대부분 기업에서 사용하는 오픈소스인 Subversion(SVN)을 비롯하여, 상용버전인 ClearCase, VSS, Harvest 등이 형상관리를 지원하는 도구입니다. 하지만, 이들 형상관리 도구를 단지 사용한다는 것이 CI의 그 전제 조건만은 아닙니다. 사용하되 다음과 같은 내용이 모두 포함되어야만 CI 적용이 가능합니다. 우선, 형상 항목을 명확하게 지정하여 관리하야 합니다. 이 형상 항목(Configuration Item)에는 개발시 필요한 내용(소스 코드, 설정 파일 등)도 포함되지만, 빌드 및 배포시 포함되어야 하는 항목들도 존재합니다. 예를 들어, 컴파일되어 바이너리 파일로 배포되는 형태의 언어라면 소스 코드는 형상 항목이 되지만, 배포 항목이 되지는 않습니다. (물론, 소스 코드를 배포한다고 해서 문제가 되지는 않지만, 물리적으로 소스코드가 배포되는 경우 보안 등을 포함하여 여러가지 이슈가 발생될 수 있습니다.) 마찬가지로 물리적인 서버에 배포할 바이너리 파일은 형상관리를 할 항목은 아니지만, 배포 항목은 포함되어야 합니다. (바이너리 파일 역시 형상 항목으로 포함시킬 수도 있지만, 이 경우에는 소스 코드와의 동기화와 같은 이슈가 발생될 수 있으며, 어느 기준[컴파일러의 버전 업그레이드 등]으로 바이너리 파일을 유지할 것인지에 대해서도 문제가 됩니다.) 형상 항목과 배포 항목을 결정했다고 하더라도 형상관리를 할 대상 항목들이 어떠한 구조(주로 패키지 구조)를 갖도록 할 것인지에 대해서도 결정이 필요합니다. 이는 배포 대상 항목과도 밀접하게 관련이 있기는 하지만, 배포 항목은 형상관리의 항목을 통해서 어떤 형태로 배포 항목을 만들 것인지는 주로 빌드나 통합 도구가 이를 대신 수행하기 때문에 형상 항목과 배포 항목을 반드시 맞출 필요는 없습니다. 하지만, 배포 항목이 본질적으로 형상 항목으로부터 만들어지기 때문에 형상항목에 대한 관리 구조는 배포 항목까지 영향을 미치게 됩니다. 자바(Java)와 같은 경우, 배포 항목의 단위가 WAR나 JAR, EAR 묶음이 되지만, 이를 형상항목에서 표시하는 방식은 참으로 다양합니다. WAR를 하나의 최상위 디렉토리에 위치하고, 그 하위에 관련 배포 항목들이 모두 위치하도록 배포 구조를 가지고 갔을 때 형상 항목들의 구조와 배포 항목들의 구조를...
read more

Java: enum의 뿌리를 찾아서…

Java: enum의 뿌리를 찾아서…
이번 글에서는 자바 1.5버전부터 새롭게 추가된 열거형 상수인 enum(enumeration)에 대해 알아보겠습니다. 열거형은 서로 연관된 상수들의 집합입니다. 이번 글은 enum 정의와 enum 사용방법, 그리고 enum 활용법을 살펴 봅니다.   1. enum이란? 관련이 있는 상수들의 집합입니다. 자바에서는 final로 String과 같은 문자열이나 숫자들을 나타내는 기본 자료형의 값을 고정할 수 있습니다. 이렇게 고정된 값을 상수라고 합니다. 영어로는 constant입니다. 어떤 클래스가 상수만으로 작성되어 있으면 반드시 class로 선언할 필요는 없습니다. 이럴 때 class로 선언된 부분에 enum이라고 선언하면 이 객체는 상수의 집합이다. 라는 것을 명시적으로 나타냅니다. enum은 enumeration이라는 셈, 계산, 열거, 목록이라는 영어단어의 앞부분만 따서 만든 예약어입니다.   2. 상수를 정의하는 다양한 방법 자바 1.5버전 이후에는 상수를 정의할 때 enum을 많이 사용합니다. 하지만 enum이 나오기 이전에는 다양한 방법으로 상수를 정의했습니다. 그래서 enum에 대해 알아보기에 앞서 자바 1.5버전 이전에는 어떻게 상수를 정의했는지 알아보겠습니다. 아래 다음과 같은 코드가 있습니다. Java public class EnumExample { public static void main(String[] args) { /* * 월요일 == 1 * 화요일 == 2 * 수요일 == 3 * 목요일 == 4 * 금요일 == 5 * 토요일 == 5 * 일요일 == 6 */ int day = 1; switch (day) { case 1: System.out.println("월요일 입니다."); break; case 2: System.out.println("화요일 입니다."); break; case 3: System.out.println("수요일 입니다."); break; /* * ... 생략 ... */ } } } 123456789101112131415161718192021222324252627282930 public class EnumExample { public static void main(String[] args) { /* * 월요일 == 1 * 화요일 == 2 * 수요일 == 3 * 목요일 == 4 * 금요일 == 5 * 토요일 == 5 * 일요일 == 6 */ int day = 1;        switch (day) { case 1: System.out.println("월요일 입니다."); break; case 2: System.out.println("화요일 입니다."); break; case 3: System.out.println("수요일 입니다."); break; /* * ... 생략 ... */ } }} 위 소스에서는 항상 1은 월요일 2는 화요일 그리고 7은 일요일로 정의되어야 합니다. 변하지 않는 상수 값에 따라 그 값에 해당하는 요일을 고정하고 있습니다. 그런데 위 소스는 주석으로 상수 의미를 전달하고 있습니다. 만일 주석이 사라지거나 혹은 주석 부분과 상수를 사용하는 부분이 분리된다면 각각의 숫자들이 어떤 것을 의미하는지 이해하기 어렵습니다. 그래서 이름 만으로 어떤 것을 의미하는지 알 수 있다면 더 좋을 것입니다. Java public class EnumExample { private final static int MONDAY = 1; private final static int TUESDAY = 2; private final static int WEDNESDAY = 3; private final static int THURSDAY = 4; private final static int FRIDAY = 5; private final static int SATURDAY = 6; private final static int SUNDAY = 7; public static void main(String[] args) { int day = MONDAY; switch (day) { case MONDAY: System.out.println("월요일 입니다."); break; case TUESDAY: System.out.println("화요일 입니다."); break; case WEDNESDAY: System.out.println("수요일 입니다."); break; /* * ... 생략 ... */ } } } 12345678910111213141516171819202122232425262728293031 public class EnumExample { private final static int MONDAY = 1; private final static int TUESDAY = 2; private final static int WEDNESDAY = 3; private final static int THURSDAY = 4; private final static int FRIDAY = 5; private final static int SATURDAY = 6; private final static int SUNDAY = 7; public static void main(String[] args) { int day = MONDAY;        switch (day) { case MONDAY: System.out.println("월요일 입니다."); break; case TUESDAY: System.out.println("화요일 입니다."); break; case WEDNESDAY: System.out.println("수요일 입니다."); break; /* * ... 생략 ... */ } }} 위 소스 코드에서 final을 사용하여 한번 지정하면 바뀌지 않게 설정하면서 동시에 static을 사용하여 메모리에 한 번만 할당 되게 설정하였습니다. 또한, 이름이 있어 이것이 무엇을 의미하는지 한눈에 알 수 있습니다. 여기에도 한 가지 안 좋은 점이 있습니다. 예를 들어 위 소스에 달에 대한 상수를 더 추가해야 합니다. 그렇게 작성하면 상수가 너무 많아 지고 한눈에 상수들이 어떤 것에 관련된 것인지 보기 힘듭니다. 또한, 각각의 상수의 집합에서 같은 이름으로 정의된 상수가 있다면 중복된 이름이기 때문에 컴파일 단계에서 오류가 발생합니다. 그래서 class 또는 인터페이스를 사용하여 각각의 집합끼리 상수가 정의되고 중복된 이름이 있어도 오류가 발생하지 않게 할 수 있습니다....
read more

« Previous Entries