반응형

* 디자인패턴이란?

- 객체지향 하면서 여러 문제가 발생하는데, 이때 처음부터 해결하는 것이 아닌 이전에 사용했던 해결책을 다시 사용

- 객체지향 설계시 좋은 아키텍처나 설계를 재사용할 수 있도록 만든 패턴이다.

 

 GOF 디자인 패턴에서는 크게 세가지로 구분한다. 생성, 구조, 행위 패턴

 

1> 생성 패턴 

- 시스템이 어떤 클래스를 사용하는지에 대한 정보를 캡슐화한다. 

- 특정 객체가 변경되거나 추가되어도 프로그램 구조에 크게 영향을 미치지 않는다.

- 싱글톤, 빌더패턴, 추상팩토리, 팩토리메서드, 프로토타입 등이 있다.

 

2> 구조패턴

- 객체나 클래스를 조합해 더 큰 구조를 만드는 패턴

- 서로 다른 인터페이스를 지닌 2개를 묶어 단일 인터페이스를 제공하거나 객체들을 서로 묶어 새로운 기능을 제공하는 패턴

- 퍼사드, 프록시, 브릿지, 컴퍼지트, 데커레이터

 

3> 행위패턴

- 객체나 클래스 사이의 알고리즘이나 책임 분배에 관련된 패턴

- 한 객체가 혼자 수행할 수 없는 작업을 여러개의 객체로 나눠서 분리, 그렇게하면서 결합도를 최소화

 

반응형

'개발공부 > 디자인패턴' 카테고리의 다른 글

디자인패턴1. 팩토리 메서드 패턴  (0) 2018.08.30
반응형

예외처리는 개발자의 숙명인것 같다.초반엔 이 개념에 대해 크게 고려를 안했던것 같은데 개발을 하면서 적절한 처리를 하는것이 추후, 시간을 낭비하지 않는 방법이라는 것을 알기에 토비의 스프링 중 예외처리 부분은 따로 정리한다.

 

 

예외를 처리할 때 피해야할 것들

1> 예외 블랙홀

try {
	...
} catch (Exception e) {
	
}

 

기껏하여 예외를 잡아, try~catch를 사용해놓고, catch 문에 아무런 액션을 하지않는 경우, 

이 경우에는 개발자 및 운영자가 예외가 발생하였는지를 못알아차릴 뿐만 아니라 예외가 발생하여도 아무런 대책을 취하지 못하는 최악의 방법이다.

 

try {
	...
} catch (Exception e) {
	sytem.out.println(e); 또는 e.printStackTrace();
}

이 역시, 로그에 뿌리기만 할뿐, 지나가면 못잡는 예외처리이다. 필자는 이 경우에 차라리 잡지말고, 상위클래스에 throws로 예외를 전달하여 책임을 전가하라고 한다.

 

2> 무의미한 throws

public void method1() throws Exception () {
	method2();
}

public void method2() throws Exception () {
	method3();
}
...

모든 예외를  위로 던져 버리는 throws 역시, 심각한 문제점이 있다. 무조건 복붙하여 넣었는지..아니면 이 예외를 어느선에서 잡아야 하는지 에외를 다룰 수 있는 기회를 박탈해버린다.

 

예외의 종류와 특징

1>Error

시스템에 비정상적인 상황이 발생했을 경우에 사용, 주로 JVM에서 발생시키는것이기 잡아도 대응방법이 없다. 따라서 이 에러에 대한 처리는 신경쓰지 않아도 된다.

 

2>Exception과 체크예외

Exception에서는 체크예외와 언체크예외로 나눠진다. 이 둘의 구분은 RuntimeException을 상속했느냐 아니냐의 차이다.

RuntimeException을 상속했다면, 언체크예외이다. 일반적으로 예외라면, 체크예외를 말한다. 사용할 메소드가 체크예외를 발생시킨다면 try~catch로 잡든지, throws를 사용하여 위에 던져야한다.

-> 일부에서 이에대한 비난이 있다. 강제하여 오류를 잡게하기 떄문에 불필요한 throws를 남발할 수 있기 때문이다.

 

3> RuntimeException과 언체크/런타임예외

명시적인 예외처리를 강제하지 않기 때문에 언체크예외라고 불린다. 에러와 마찬가지로 런타임예외는 catch문으로 잡거나 trhows로 던지지 않아도 된다. 오류가 있을때 발생하도록 의도된 것들이기 때문이다. nullpointException이나 illegalArgumentException 은 개발자가 주의하면 피할 수 있다. 개발자의 부주의에 의해서 발생하는 것이기 때문에 발생하도록 만든것이 런타임 예외다. 충분히 예상할 수 있는 상황에서 발생한 예외이므로 예외처리를 하지 않는다.

 

예외 처리 방법

그렇다면 이러한 예외들을 어떻게 처리하여야 할까? 다음과 같은 방법이 있다.

 

1> 예외복구

예외상황을 파악하고 문제를 해결해서 정상상태로 돌려놓는 것이다. 예외로 인해 기본작업 흐름이 불가능하다면, 다른 작업흐름으로 자연스럽게 유도해주는 것이다. 예를 들어 파일 전송이 되지 않으면 사용자에게 파일 업로드를 다시하라는 로직을 추가하거나, 네트워크 접속이 원할하지 않으면 일정 조건을 두어 해당 횟수만큼 재시도를 하도록 유도하여야 한다.

int maxTry = MAX_RETRY;

while(maxretry --> 0) {
	try {
    	..	//예외 발생 가능성이 있는 코드
    	return;
    } 
    catch(Exception e) {
    	// 로그출력, 정해진 시간만큼 대기
    }
    finally {
    	//리소스 반납, 정리작업
    }
    
    throw new RetryFailedException; // 최대 재시도 횟수를 넘기면 excception 발생
}

 

2> 예외처리 회피

자신이 직접 처리하지않고 throws로 예외를 던지는 방법이다. 또는 try~catch로 로그만 남기고 throw로 예외를 던지는 방법이 있다. 하지만 긴밀한 협력관계가 아니면 이는 다른 메소드에게 책임을 전가하는 무책임한 회피가 될 수 있음을 기억하자.

public void add()  throws Exception {

}
public voi add() throws Exception {
	try {
    	...
    } catch (Exception e){
    	//로그출력
        throw e;
    }
}

 

3> 예외 전환 

발생한 예외를 그대로 던지는게 아닌 적절한 예외로 전환하여 던진다.

 

이에 대한 목적은 두가지가 있다. 첫째, 의미를 분명하게 해줄 수 있는 예외로 바꿔준다. 예를 들어, id가 중복인 예외라면 sql익셉션보다 idDuplication예외를 선언하여 던지는것이 더 의미가 분명할 것이다.

 

둘째, 예외처리를 강제하는 체크예외를 언체크예외로 바꾸려는 경우 사용한다. 어차피 잡기 불가능한 예외라면, 런타임예외로 포장하여 던지게 하여 다른 계층이 코드를 작성할때 불필요한 throws를 작성하는것을 막아준다. 코드에서는 런타임예외로 던지고, 에외처리 서비스 등을 이용하여 관리자에게 메일로 남기거나 로그로 던지는 등의 추가 로직을 넣는것이 바람직한다. 

 

출처: 토비의 스프링3.1 vol1

반응형

'개발공부 > Spring' 카테고리의 다른 글

Spring에서 Bean을 주입하는 방식  (0) 2020.03.16
SPRING AOP  (0) 2018.07.02
SLF4J와 Logback  (1) 2018.06.26
Tiles란, Spring tiles3 적용법  (2) 2018.06.14
반응형

실수를 하여 기록해둔다.

 

Java Map 객체에서 값을 빼올 때 

 

예)

HashMap<String, Object> apiResponse = new Map<>();
logger.debug(apiResponse.get("aaa").toString());

aaa라는 이름의 객체를 빼온다고 하자. 

이때 값이 null이면 NullPointException 이 떨어진다. 이때는 값을 굳이 형변환을 할필요 없이 값 앞에다 알맞은 형을 명시해둔다. 이미 Object객체임으로 컴파일러에게 String이라고 아래와 같이 명시해주면 된다.

 

HashMap<String, Object> apiResponse = new Map<>();
logger.debug((String)apiResponse.get("aaa"));

 

아니면 NPE 방지를 위해서 String.valueOf()를 쓰는것도 한 방법이다.

String.valueOf()은 파라미터가 null이면 null인 문자열을 반환시킨다.

String lowerCoatingVal1 = String.valueOf(destItemMap.get("LOWER_VAL"));

String lowerCoatingVal2 = destItemMap.get("LOWER_VAL").toString();

 

lowerCoatingVal1 = "null"

lowerCoatingVal2 = NullPointerException 발생

 

String.valueOf()의 null 체크

String lowerCoatingVal1 = String.valueOf(destItemMap.get("LOWER_VAL"));

if("null".equals(lowerCoatingVal1)) {

    // To do Somting....

}

 

출처 : https://swjeong.tistory.com/146,https://okky.kr/article/71363

반응형
반응형

1) @Autowired

2) setter

3) 생성자

 

이 중에서 가장 권장하는 방식 : 생성자로 주입받는 방식

lombok 어노테이션의 @RequiredArgsConstructor 에서 해결 - final 선언된 모든 필드를 인자값으로 하는 생성자를 대신생성해줌

 

그렇다면 @Autowired를 권장하지 않는 이유는 무엇일까?

- 순환 의존성 (클래스a <-> 클래스b를 서로 참조할 수 있음)

- final 선언이  아니므로 객체가 변할 수 있다.

 

이런 이유로 스프링팀에서는 생성자 방식을 권한다.

 

출처 :

스프링부트와 AWS로 혼자 구현하는 웹 서비스 - 이동욱 저

https://yaboong.github.io/spring/2019/08/29/why-field-injection-is-bad/

 

 

 

반응형

'개발공부 > Spring' 카테고리의 다른 글

예외처리(1)  (0) 2020.10.01
SPRING AOP  (0) 2018.07.02
SLF4J와 Logback  (1) 2018.06.26
Tiles란, Spring tiles3 적용법  (2) 2018.06.14
반응형

객체의 리스트 형태에서 조건에 맞는 객체를 삭제 하고 싶을때 for loop를 돌려서 삭제하는 경우가 있다.

아래의 코드는 오류가 나니 항상 주의해서 사용하여야 한다.

잘못된예 >>

List<String> names = .... 

for (String name : names) { 

                  names.remove(name);

 }

객체를 꺼내서 사용하는 대신 iterator 를 이용하여야 오류를 막을 수 있다.

List<String> names = .... 

Iterator<String> i = names.iterator(); 

while (i.hasNext()) {

                String s = i.next(); 

                i.remove(); 

}

해당 개념과 관련하여 업무상 실수를 한적이 있어 기록해둔다.

 

출처 : https://stackoverflow.com/questions/1196586/calling-remove-in-foreach-loop-in-java

반응형
반응형

Tomcat 설치 시 소스 경로를 설정할 때 두가지 방법이 있다.

 

1) {톰캣 폴더}/conf/Catalina/localhost/ROOT.xml 에 해당 경로를 넣는 방법 - 이때 유의해야 할것은 server.xml 의 Host 경로를 수정하지 말아야 한다는 점이다.

 

ROOT.xml 파일 내용를 아래와 같이 설정한다.

<Context docBase="{해당 소스가 위치한 경로를 넣어준다}" reloadable="true" privileged="true" antiResourceLocking="false" useHttpOnly="false"> </Context>

 

2) server.xml 에서 직접 설정해준다. 단, 붉은 색으로 표시한 컨텍스트 패스를 함께 설정해주어야 오류가 나지 않는다.

<Host name="localhost" appBase="{해당 소스가 위치한 경로를 넣어준다}" unpackWARs="false" autoDeploy="false">

<Context path="" docBase="" reloadable="true" />

 

 

반응형
반응형

유니캐스트, 브로드캐스트, 멀티캐스트

  1.    유니캐스트란?
-  목적지 맥 어드레스로 자신의 랜턴들 맥 주소를 비교하여 맞으면 통신, 맞지 않으면 버리는 방식
- 1대1이기 때문에 다른 피씨에 성능 저하가 일어나지 않으며 가장 많이 사용하는 트래픽

  2.     브로드캐스트
- IP주소를 보내고 MAC주소를 알아내기 위한 ARP를 할때, 브로드캐스트 방식을 이용한다. 이외에 라우터끼리 정보를 주고 받거나 서버들이 자신의 서비스를 클라이언트에게 알릴때 사용

- 브로드캐스트가 많아지면 성능 저하를 일으키게 된다. 그 이유는 자신의 맥 주소와 다름에도 불구하고 일단 인터럽트를 걸기 때문에 피씨는 당연히 느려질 수 박에 없다.

3. 멀티캐스트
  - 유니캐스트는 1대1방식이기 때문에 목적지 수가 많아지면 네트워크상에서도 같은 데이터가 많아지기 때문에 트래픽 문제가 생기게 된다. 
브로드캐스트를 사용하면, 필요없는 그룹도 데이터를 받아야 하기 때문에 성능 문제가 생긴다. 이를 해결하기 위한것이 바로 멀티캐스트

 - 그룹에 속해있는 사람들만 선택적으로 한번에 보낼 수 있다. 단, 라우터가 스위치에서 이 기능을 지원해 주어야만 쓸 수 있다는 제약이 있다. 

   OSI 7 레이어

    OSI 7 레이어를 나누는 이유?

   데이터의 흐름이 한눈에 보인다. 어떻게 데이터가 날아가는지 보기 위해

문제를 해결하기 편리하다. 어느계층의 문제인지 알 수 있다.

여러 회사 장비를 써도 층별로 표준화를 하니까 이상 없이 돌아간다.


***  OSI 7 레이어의 종류

피지컬 계층 - 통신 케이블로 전송하는 것, 1과 0 으로 나타냄. ex) 케이블, 리피터, 허브..


데이터링크 계층 - 송, 수신 되는 정보의 오류와 흐름을 관리하여 안전한 정보의 전달을 수행할 수 있도록 한다. 오류를 찾아주기, 재전송하는 기능도 가지고 있음. 전송되는 단위를 프레임이라고 부름

         ex) 브리지, 스위치..

네트워크 계층 - 목적지까지 데이터를 안전하고 빠르게 전달. 이를 라우터라고부름. 경로를 선택하고 주소를 정하고, 경로에 따라 패킷을 전달해주는 것이 이 계층의 역할.  ex) 라우터, 스위치중에서도 이러한 기능을 수행하는 스위치가 있다. (Layer3 스위치 라고 부름.)


트랜스포트 계층 - 플로컨트롤과 에러 복구 기능. 에러복구를 위해 패킷 재 전송하거나 플로어를 조절해서 데이터를 정상적으로 전송될 수 있게 한다. ex) TCP, UDP

—단계가 낮을 수록 헤더가 추가 되며 헤더를 하난씩 제거하면서 통신을 하게 된다.

프로토콜이란?

    -컴퓨터까지 통신을 하고 있는 규약, 협약..
    -인터넷을 사용하기 위해서는 TCP/IP라는 프로토콜을 사용해야 하듯이 모든 통신에서는 프로토콜을 이용하여 통신을 해약한다. 



반응형

'개발공부 > 네트워크' 카테고리의 다른 글

후지의 쉽게 쓴 시스코 네트워킹 정리 1,  (0) 2019.03.24
반응형
*이더넷 - 네트워킹을 한 방식- CSMA/CD 방식을 사용한다.

  1. CSMA/CD란? 
- 여러 대의 컴퓨터가 네트워크상에서 연결되어있을 떄 동시에 신호를 보낸다. 이때 두대이상의 신호가 동시에 보내주면 충돌이 나게 되는데 이러한 충돌이 15번이상 동시에 나면 포기하게 된다. 충돌이 나지만, 너무 많은 충돌이 발생하게 되면 통신 자체가 불가능 해지는데 이러한 방식을 말한다.

  1. 토큰링 ?
-충돌을 막기 위해 토큰을 가진 PC만이 네트워크에 데이터를 실어 보낼 수 있다. 충돌이 발생하지 않고 네트워크의 성능을 미리 예측하기 쉽다. 단, 보낼 PC가 하나도 없더라도 토큰이 올때까지 기다려야 하는 성장성을 단점이 있다.

*UTP 케이블 - 케이블의 주위를 감싸지 않은 케이블
*STP 케이블 - 어떤 절연체로 감싸서 만든 케이블
—> 보통은 UTP케이블이 많이 쓰이고 STP는 토큰이에요 많이 쓰인다. 

*케이블의 종류
-케이블 종류 읽는 방법 : 10 base T - 앞의 10은 속도, base는 베이스밴드(디지털방식)인지 브로드밴드(아날로그적인)인지, T는 UTP방식을 말한다. 
-속도가 빨라질수록 전송 거리는 점점 짧아진다.

*맥 어드레스 (MAC address)
-통신을 위해서 서로가 구분할 일종의 주소, IP주소가 있긴 하지만, 실제로는 IP주소를 MAC주소로 바꾸는 과정(ARP)가 필요하다. 같은 라우터 안에 있는 피씨끼리 통신을 한다고 하면, 같은 네트워크상에서 있는 피씨 전체에게 목적지 IP주소를 보낸다. MAC주소로 바꿔달라고, 이때 목적지주소를 가지고 있는 피씨는 자신의 MAC주소를 보내주고 서로 통신을 시작하게 된다.

그러나, 같은 네트워크에 없을 경우 - 라우터라는 중간의 개체가 자신의 MAC주소를 전달하고 라우터는 자신의 네트워크상에서 목적지 IP를 찾고 MAC주소를 알아낸다.

모든MAC 주소의 형식은 다음과 같다.

00-60-97-8F-4F-86
원래는 2진수짜리 48개로 이루어져있어서 48비트인데, 보통은 16진수로 표현한다.

주소의 앞쪽의 절반은 제조사 코드, 뒤쪽의 절반은 일련번호로 이루어져 있다. 
반응형
반응형
자바로 HttpsURLConnection을 사용하여 https 사이트에 connect 하면 오류가 난다.

이 경우에는 SSL을 무시하여 우회하도록 하는 코드를 작성하여야 한다.

먼저, 해당 URL이 https 인지 판별하는 코드를 썼다.

1
2
3
4
5
6
URL aURL = new URL(url);
 
if (aURL.getProtocol().equals("https")) {    //해당 url이 https이면
      resultData = httpsGet(url);            //ssl인증서를 무시하는 함수를 호출한다.
      logger.debug("https resultData: {}" , resultData);
}
cs


httpsGet함수 - 다른 부분은 http 호출방식과 유사하나 ignoreSSL 처럼 connection 전에 처리해줘야할 사항들이 있다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    public static String httpsGet(String strURL) throws Exception
    {
        URL url = null;
        HttpsURLConnection con = null;
        String ret = new String();
        
        try {
            url = new URL(strURL);
            ignoreSsl();
            con = (HttpsURLConnection)url.openConnection();
    
    
            BufferedReader br = null;
            br = new BufferedReader(new InputStreamReader(con.getInputStream()));
    
            String input = null;
    
            while ((input = br.readLine()) != null){
                ret += input;
            }
            
            br.close();
        }
        catch (IOException e) {
            ExceptionUtil.getStackTrace(e);
        } finally {
            if (con != null) {
                con.disconnect();
            }
        }
        
        return ret;
        
    }
cs


ignoressl()함수
1
2
3
4
5
6
7
8
9
    public static void ignoreSsl() throws Exception{
        HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String urlHostName, SSLSession session) 
                return true;
            }
        };
        trustAllHttpsCertificates();
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    private static void trustAllHttpsCertificates() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new miTM();
        trustAllCerts[0= tm;
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }
 
    static class miTM implements TrustManager,X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
 
        public boolean isServerTrusted(X509Certificate[] certs) {
            return true;
        }
 
        public boolean isClientTrusted(X509Certificate[] certs) {
            return true;
        }
 
        public void checkServerTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
 
        public void checkClientTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
    }
cs



핵심은 connection 전에 호출 처리를 해줘야 오류가 나지 않는다.


반응형
반응형
리눅스 상에서 tar 명령어를 이용할때 절대경로를 이용해서 하면  원하는 곳에 풀수가 없고 만들때 지정된 절대경로를 사용해서 그대로 풀린다.
얼마전 하루넘게 절대경로로 압축된 tar 파일을 상대경로로 풀기 위해 삽질을 하여 이곳에 적어둔다. 이는 다시 상대경로를 이용해서 압축하는 방법을 이용하는 수밖에 없다. 아니면 임시폴더를 이용하여 압축을 풀고 cp를 하던가..

그럼 상대경로를 이용하여 tar 압축을 하는 법을 알아보자

예를 들어 /root/aaa/bb/ex폴더를 압축할때 

tar cfP new.tar /root/aaa/bb/ex      

이렇게 지정하면 압축풀때 /root/aaa/bb/ex 폴더로 풀리게 된다.

따라서  tar 로 압축할때는 상대경로로 이동해서 압축을 하여야 한다.

이미 절대경로를 사용해서 만들었다면 이걸 상대경로로 푸는방법이 있긴 하다. pax 명령어를 이용하는 것이다.
# cd /target 
# /usr/bin/pax -r -s ',^/,,' -f /test.tar 

$ pax -r -s ',^ __없앨 경로들___ , __원하는 경로들___ ,' -f 파일.tar
---> 없앨 경로 : 이미 압축 파일에 포함되어있는 없애고 픈 경로들
---> 원하는 경로 : 압축 파일에 있지만, 압축 해제와 동시에 새로운 경로로 풀리기를 바라는 경로

단,  파일 이름이 . 으로 시작하는 hidden file들은 풀리지 않고 tar -C 처럼 지정한 경로에 풀수 없다는 단점이 있다.


참고

https://kldp.org/node/90185


반응형

+ Recent posts