Java - Exception ( Feat. Effective Java)

이미지
이전 글  에서 Error 와 Exception 에 대해서 정리해보았다. 이번 글에서는 Java 개발자라면 읽어야 한다는 Effective JAVA Third Edition 기준으로 예외 핸들링에 대해서 정리해보겠다. 책에서는 이렇게 말하고있다.  "예외를 제대로 활용한다면 프로그램의 가독성, 신뢰성, 유지보수성이 높아지지만, 잘못 사용하면 반대의 효과만 나타낸다." 그렇다면, 제대로 활용하는 방법에 대해서 책이 알려주는 내용을 정리해보겠다. 예외는 진짜 상황에만 사용하라 책에서는 운이 없다면 언젠가 다음과 같은 코드를 마주할지 모른다고 한다. 나는 운이 없는가 보다.. ㅎㅎ 해당 코드를 보고 무슨 일은 하는 코드인지 알기 어렵다. 전혀 직관적이지 않다. 해당 이유만으로 코드를 이렇게 작성하면 안된다는 이유가 분명하다. 해당 코드를 분석하면, 아주 끔찍한 방식으로 배열을 순회하고 있다. 무한루프를 돌다가 배열의 끝에 도달하여 ArrayIndexOutOfBoundsException 이 발생하면 끝이 난다.  해당 코드를 표준적인 관용구대로 작성했다면 바로 이해할 수 있을것이다.  왜 예외를 써서 끔찍한 코드를 만들어 냈을까?  책에서는 잘못된 추론을 근거로 성능을 높이려 시도할 경우 발생할 수 있다고 한다. 나의 개인적인 생각으로는 아마 해당 코드 작성자가 정확한 배열 순회 메커니즘을 이해하지 못한다거나, 혹은 겉멋(?)이 들어서가 아닐까 의심이 된다. ArrayIndexOutOfBoundsException 을 사용한 코드가 표준 관용구보다 성능이 안좋다. try-catch 블록 안에 코드를 넣으면 JVM 이 적용할 수 있는 최적화가 제한 된다. try catch block 사용은 소량의 데이터 케이스에서 성능 차이는 미비하여, 하드웨어 성능으로 어느정도 커버가 가능하다고 말할 수 있다.  하지만 제일 중요한 점은 가독성을 해치는 것이라고 나는 생각한다. 이는 유지보수에 상당한 어려움을 유발한다. try cat...

Java - Error, Exception

이미지
 Error 는 JVM 실행에 문제가 생겼다는 것을 의미한다. JVM 위에서 실행되는 프로그램은 실행 불능이 된다. 개발자는 안타깝게도 Error 에 대처할 방법이 전혀 없다. Exception 은 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류이다. Exception 이 발생하면 프로그램이 곧바로 종료된다는 점에서는 Error 와 동일하다. 하지만 Exception 은 Exception Handling 을 통해서 프로그램을 종료하지 않고 정상 실행 상태를 유지되도록 할 수 있다. Virtual Machine Error 의 종류에는 java.lang.OutOfMemoryError, java.lang.StackOverflowError, java.lang.UnknownError, java.lang.InternalError 등이 있다. Exception 은 두 가지로 나뉜다. Checked Exception 과 Unchecked Exception 이다. Checked Exception 은 컴파일러 체크 예외라고도 하는데, 자바 소스를 컴파일하는 과정에서 예외 처리 코드가 필요한지 검사하기 때문이다. Checked Exception 에 예외 처리 코드가 없다면 컴파일 오류가 발생한다.  Unchecked Exception 의 경우에는 컴파일 과정에서 예외 처리 코드를 검사하지 않는 예외를 말한다. 컴파일 과정에서 예외 처리 코드를 검사하지 않지만, Unchcked Exception 도 마찬가지로 예외 처리가 필요하다. Checked Exception 은 Exception 을 상속받는다. Unchecked Exception 은 RuntimeException 을 상속받는다. RuntimeException 은  또한 Exception 을 상속받지만, JVM 은 RuntimeException 을 상속했는지 여부를 보고 Checked Exception 과 Unchecked Exception 을 구별한다. RuntimeE...

Tomcat War Deploy 404 (Feat. EC2) - Maven Clean

이미지
 오늘의 글은 나의 경험담을 정리하려고 한다. 무슨 경험이라고? 내가 삽질한 경험이다. 우선, 개발 환경부터 간단하게 정리해보겠다.  단일 EC2 환경이다. 아래와 같이 여러 가지 개발 툴 을 설치했다. - Jenkins (9090 port) - Tomcat (8080 port)  - Github - Maven Tomcat 에 Github 의 Spring 프로젝트를 Maven 을 이용하여 War 로 패키징하는 간단한 Deploy 방식이였다. Deploy 는 Jenkins 프리스타일 프로젝트를 사용했다. 1. Git Parameter Plugin 을 이용해서 브랜치를 선택할 수 있게 한다. 2. NodeJS Plugin 과 기존에 설치해 둔 Maven 을 이용하여 Shell Script 를 실행하여 War 패키징 및 해당 EC2 Tomcat 에 올리고 실행하게 한다. 아래는 간단한 shell script 이다.  maven PATH 를 잡아주고, 미리 설정해 둔 S3에서 properties 파일을 가져온다. 그리고 mvn 명령어를 통해서 war 로 패키징하고, 패키징 한 war 를 S3 에서 버전관리 한다. 그리고 톰캣을 우선 정지하고, 새로 패키징한 war 를 tomcat 경로에 맞게 올린다. 그리고 잠시 스레드를 5초 동안 잠재운다.  그후에 다시 톰캣을 시작한다. 이러한 과정에서 여러 브랜치를 아마 대략 70 번 (?) 정도 배포 했다.  70번 밑으로 배포는 정상적으로 배포가 잘 되었고, 테스트로 잘 할 수 있었다.  그러나 70번 정도가 넘어가자, 달콤한 404 를 맞이하게 된다. 뭐지? 왜 잘 되던게 갑자기 안될까??? 제일 짜증나는 부분이다. 삽질을 하다가 tomcat log 를 찾아봤다. /var/log/tomcat8/catalina.out 아래와 같이 ConflictingBeanDefinitionException 을 확인한다.  ConflictingBeanDefinitionEx...

Jenkins - Publish over SSH (feat. AWS EC2)

이미지
 많은 사람들이 알다시피, Jenkins 는 유용한 CI / CD 오픈소스 툴이다. 온프레미스 환경 및 클라우드 환경을 넘나들며 유용하게 사용할 수 있다. Jenkins 가 제공하는 수많은 기능들이 있다. 그 수 많은 기능들 중에 이번 글에서 정리할 내용은 Publish over SSH Plugin 이다. 기존에 이미 Jenkins 는 EC2 에 설치가 되어있고 배포 대상이 되는 EC2 도 있다는 전제하에 정리해보겠다.  혹시라도 Jenkins 설치 방법이 궁금하다면 예전 글에서 정리한 것을 참고하길 바란다.  https://infondgndg91.blogspot.com/2020/06/install-jenkins-in-aws-ec2.html 이번 글에서 무엇을 정리할 것인가 나열하겠다. 1. Github 에서 Source code 를 땡겨온다. ( 이번 글에서 Github 설정은 다루지 않는다. ) 2. Gradle 로 Spring boot project 를 jar 로 빌드한다. ( 이번 글에서 Gradle 설정은 다루지 않는다. ) 3. 빌드한 jar 를 Publish over SSH 플러그인을 통해서 Deploy EC2 에 전송한다. 4. Deploy EC2 에 있는 shell script 를 Jenkins EC2 에서 원격 호출한다. 우선, Publish over SSH 플러그인 부터 설치해보자. 아래는 해당 플러그인 공식 Documentation 이다. https://plugins.jenkins.io/publish-over-ssh/ admin 으로 들어가든, 권한이 있는 계정으로 들어가자. Jenkins 관리로 들어가자. 그리고, 플러그인 관리로 들어가자. 나는 이미 설치를 했기 때문에, 설치된 플러그인 목록에서 검색을 통해서 확인할 수 있다. 설치가 되지 않은 상태라면, 설치 가능 목록에서 Publish over SSH 검색 후 설치하면 된다. 플러그인 설치가 되었다면, 이제 시스템 설정으로 들어가자.  들어가서, 스...

IaC (Infrastructure as Code) - Import existing AWS resources into Terraform (Feat. Terraforming)

이미지
 요즘에, AWS 를 사용하면서, 여러가지 Resource 들을 다루어 보고 있다. 이러한 과정속에 다루는 Resource 가 많아질수록 또는 여러사람들이 Resource 를 추가하고 삭제하고 변경하는 과정에서 추적이 쉽지 않고 관리가 어려워지는 것을 느꼈다. AWS 에서 기본적으로 제공하는 서비스인 CloudFormation 도 있고, 최근에는 CDK 를 지원하고 있기도 하고 이외에도 Ansible, Chef, Puppet 등 다양한 IaC 도구들이 있다는 것을 알지만, 나는 아직 초짜라서 이 모든것을 경험해보진 못했다. https://aws.amazon.com/ko/about-aws/whats-new/2019/07/the-aws-cloud-development-kit-aws-cdk-is-now-generally-available1/ 요즘 새롭게 꽂혀서 Terraform 을 이것저것 만져보고 있다. 새롭게 Infrastructure 를 구축할 때는 실습해보면서 감을 익히는 정도인데, 문득 기존에 존재하는 수많은 Resource 들을 Terraform 으로 쉽게 관리할 수 있는 방법은 없을까? 라는 의문점이 생겼다. existing AWS Resource import Terraform 라는 키워드로 구글링을 하는 과정에서 Medium 에서 블로깅한 내용을 발견했다. https://medium.com/@yoga055/importing-existing-aws-resources-to-terraform-using-terraforming-3221b26e015 해당 내용을 보고, 오! terraforming 역시, 누군가가 괜찮은걸 이미 만들어 놨군! ㅋㅋ https://github.com/dtan4/terraforming 사용법도 정말 간단하다. 우선 Mac OS 기준으로 사용법을 정리하고 마치겠다. 먼저 필요한건 AWS CLI 이다. AWS CLI 설치 방법은 간단하다. 아래 링크로 들어가서 인스톨러 다운받고 설치하면 된다. https://docs.aws.am...

Network Basic - IP Address & DNS

이미지
IP Address IP 주소는 Network Address 와 Host Address 로 구성되어 있으며, 32 bit로 4 byte 데이터이다. 예를들어, 10.11.12.13 이라는 IP Address 는 아래와 같이 구성되어있다. 10.11.12 .0 → 00001010.00001011.00001100. ( Network Address ) 0.0.0. 13 → 00001101 (Host Address) 전체 IP Address 를 32비트로 보면 아래와 같이 나타낼 수 있다. 10.11.12.13 → 00001010.00001011.00001100.00001101 하나의 8비트 섹션을 옥텟(octet)이라 부른다. Subnet Mask TCP/IP 프로토콜에 의해 Host 가 로컬 서브넷에 있는지 아니면 원격 네트워크에 있는지를 확인하는 데 사용된다. 10.11.12.13 → 00001010.00001011.00001100.00001101 255.255.255.0 → 11111111.11111111.11111111.00000000 이는 10.11.12.0/24 를 의미한다. 24 는 24 bit 를 의미하는데 앞서 255.255.255.0 은 8bit.8bit.8bit.0 을 의미한다. 따라서, 8bit * 3 = 24bit 을 의미하며, 8bit 이라는 의미는 더이상 해당 옥텟에 host 부여가 불가능하다는 의미이다. 따라서 해당 네트워크의 호스트가 부여가능한 IP range 는 10.11.12.1 ~ 10.11.12.254 범위를 의미한다. 여기서, 10.11.12.0 과 10.11.12.255 는 포함되지 않는다. 호스트 번호 부분의 비트 값이 모두 0 또는 1인 경우는 특별한 의미를 가진다. 모두 0 → 서브넷 자체를 가리킨다. (10.11.12.0 → 00001010.00001011.00001100. 00000000 모두 1 → 서브넷에 있는 기기 전체에 패킷을 보내는 브로드캐스트  를 나타낸다. (10.11.12.255 →...

AWS - VPC 만들어 보자 2.

이미지
 지난 글  https://infondgndg91.blogspot.com/2020/08/aws-vpc.html  에서 서울 리전에 VPC 및 서브넷을 생성해 보았다. 이전 글에서 만들었던 VPC 를 기준으로 인터넷 게이트웨이와 NAT 게이트웨이, 라우팅 테이블, 탄력적 IP, 네트워크 ACL, 보안 그룹을 실습 하면서 아래와 같이 정리해보겠다. 우선, 라우팅 테이블은 VPC 생성 시 자동으로 생성 된다. 기본 VPC 를 통해 확인이 가능하다. 먼저, 기본 VPC 기본 VPC 에 매핑 된 라우팅 테이블 기본 VPC 의 CIDR 블록을 172.31.0.0/16 의 대상은 local 로 기본 VPC 에 속한 모든 Subnet 에 대하여 라우팅을 제어하는 역할은 한다.  그리고 기본 VPC 가 아닌 새로 VPC 를 생성하는 것과의 차이는 바로 Internet Gateway. 기본 VPC 에는  Routing table 에 자동으로 Internet Gateway 가 붙어 있다.  Internet Gateway 가 하는 역할은 VPC 내의 Instance 와 인터넷 간의 통신이 가능하게 만들어 준다. 하지만 기본 VPC 가 아닌 새롭게 생성한 VPC 의 경우에는 Internet Gateway 가 자동으로 생성되지 않고 라우팅 테이블에 추가 되지 않기에, 새롭게 Internet Gateway 를 생성해주고 새로 생성한 VPC 라우팅 테이블에 추가해줘야 인터넷과 새로 생성한 VPC 내의 Instance 간의 통신이 가능하게 된다. 아래와 같이 Internet Gateway 를 생성하고,  새로 생성한 giri-vpc 에 attach 했다. Destination 0.0.0.0/0 Target 은 새로 생성한 Internet Gateway 가 새로 생선한 giri-vpc 라우팅 테이블에 추가 되었다.  여기서 중요한 점은 이전 글에서 생성한 Public Subnet 과  Private Subnet 에...