리눅스는 정신건강에 매우 해롭다....


하지만 쉬우면 재미없듯이 OS 공부하는 재미가 있고 


개발용 OS에 매우 좋은 리눅스 



window10  가격이 15만원 


Linux Ubuntu17 가격 0원 무료!



15만원이면 CPU 사양 조금 더 좋게 맞추거나 RAM 업그레이드가 가능한 가격인데


돈 아쉬운 대학생인데... 나쁘지 않은 선택이다.

 


리눅스를 데스크탑 OS로 사용했을때 장점


1. 강제로 운영체제 공부하고 


2. 무료! 


3. 개발에 특화된 환경 구축!


리눅스를 OS로 추천하는 사람은 

히오스를 하라고 추천하는 사람과 같습니다.

그게 접니다







리눅스를 데스크탑 OS로 사용했을때 단점 


1. MS Ofiice 사용불가

대처법 1 : 웹 애플리케이션 환경에서 사용할 수 있다.

대처법 2: LibreOffice 사용 (안좋음 ) View로 사용하거나 

약간의 파일 수정은 가능하지만 레이아웃이 매우 잘깨짐


2. 게임을 할수 없다.

대처법 : 안하면된다. 강제로 게임 끊음



3.그래픽카드가 심심하면 사라진다.


리눅스의 아버지 리누스 토르발즈께서 말씀하셨습니다.


F*ck you Nvidia



그래픽카드드라이버랑 커널 버젼이랑 호환이 안되면 

가차없이 외장그래픽을 인식 안해줍니다.



이게 Nvidia 홈페이지 들어가서 찾은 호환 드라이버를 설치해도 

커널버젼이 안맞으면 외장그래픽 카드 인식 못 합니다.

커널 버젼 업그레이드하면 아마 또 그래픽카드가 사라질꺼같아요 .....눈물...






그밖에


바로가기아이콘 만들려면 vi에서 약간의 코딩이 필요함

(윈도우에서처럼 클릭으로 못함)


카카오톡pc 안됨(wine쓰면되는데 그래도 쫌...)


윈도우와 다른 리눅스 단축키 익숙해지는것에 시간이 필요


한국어 지원이 되지만 완벽하지않음 

주석을 한국어로 달다가 갑자기 이유모를 단축키 실행되서 엉뚱한거 페이지 막 켜지기도 하네요 


이건 잘하면될거같은데 귀찬....




이런 엄청난 불편에도 왜 리눅스를 사용하느냐? 라고 


물으시는 분들이 계시는데 


개발환경이 매우 클린합니다.


사실 플라시보인가?....


cmd 창에서 왠만한 개발환경 구축이 단 몇줄의 명령어로 셋팅이 완료됩니다.


mysql 가필요하다?


sudo apt-get install mysql-server 

설치끝

sudo apt-get install mysql-workbench

설치끝



redis가 필요하다?


sudo apt-get install redis-server

설치끝입니다.


개발환경이 운영환경과 비슷해서 괜찮기는하지만


사실 공부하는 목적이 더 크다.


2~3달만 OS를 리눅스를 사용하면 

온갖 삽질을 강제로 경험하면서 성장할수있다.



컴공이나 개발자라면 리눅스 OS를 한번쯤은 사용하는거 추천한다


개발 실력은 삽질하는 기간에 비례하듯이


OS를 리눅스로 가져가면 환경에 익숙해지면서 OS이론으로 배웠던 내용들이 내 손위에서 움직이는것을 경험한다


물론 그런 것 보다 그냥 업데이트를 했는데 컴퓨터가 부팅이 안되서 맨탈나가는 상황들이 더많기는 하다. 


근데 무료잖아요?  무료니까 그냥 한번 써보는정도...

























'Computer Science' 카테고리의 다른 글

리눅스 Service 등록 하기  (0) 2018.07.17
프로세스란 무엇인가 Operating System  (1) 2018.01.11

org.springframework.web.bind.MissingServletRequestParameterException: Required MultipartFile parameter 'file' is not present




아주 희안한 버그였다 


//Servlet 2. x 에서 사용하는 설정

@Bean

public MultipartResolver multpartResolver() {


CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();


multipartResolver.setMaxUploadSize(1024*1024*100L);

multipartResolver.setMaxInMemorySize(1024*1024*40L);


return multipartResolver;

}




스프링 MultipartFile 로 파일 받아오는 api를 짜고있는데 


PostMan 으로 테스트 해보니  확장자 .mp3  파일은  성공적으로 받아지는데


그 이외의 확장자들은 전부 BadRequest 


org.springframework.web.bind.MissingServletRequestParameterException: Required MultipartFile parameter 'file' is not present
 


이렇게 에러코드 400을 뱉는 것이였다.

(이게 원래는 전부 안되야 되는데 .mp3 확장자만 되는 것은 무엇????)



아 이거 Spring In Action 에서 봤던 내용이였는데 


이걸 읽어놓고 까먹어서 구글링하고 있다



스프링 부트는 1.2.x 버젼 이상에서는 기본적으로 Servlet 3.x 을 사용한다


 서블릿 3.x 이상 스펙에서는  multipartResolver를 외부 라이브러리 없이 


쓸수있게 자체 구현되어있는데 


스프링에서 Servlet 2.x 와 3.x 에서 다르게 구현체를 만들어놓았음



  • Servlet 3.0 Part API를 바탕으로 한 MultipartResolver 인터페이스 구현체
  • bean 을 선언할 때 별다른 확장설정을 하지 않고 “multipartResolver”로 선언
  • multipart와 관련된 업로드 파일 최대크기, 저장위치 등 설정을 하고 싶다면
    • web.xml에서 하거나
    • Servlet 등록하는 과정에서 MultipartConfigElement을 선언하면서 설정
    • @MultipartConfig라는 애노테이션 사용
  • Servlet 3.0 에서는 MultipartResolver 레벨에서 설정하는 것을 허용치 않는다.


  • 출처: http://java.ihoney.pe.kr/351 [허니몬(Honeymon)의 자바guru]




    //Servlet 3 이상 버젼에서의 설정 

    @Bean

    public MultipartConfigElement multipartConfigElement() {

        MultipartConfigFactory factory = new MultipartConfigFactory();


        factory.setMaxFileSize(MAX_UPLOAD_FILE_SIZE);

        factory.setMaxRequestSize(MAX_REQUEST_SIZE);

        factory.setFileSizeThreshold(FILE_SIZE_THREADHOLD);

        


        return factory.createMultipartConfig();

    }


    @Bean

    public MultipartResolver multipartResolver() {

        return new StandardServletMultipartResolver();

    }

















    해결 방법 참고 url


    https://www.cameronezell.com/failed-to-start-service-unit-service-not-found/





    스프링 부트 jar 파일을 Aws에 배포하려고 


    서비스 등록을 하려고 스크립트 파일을 짜서 올렸는데 


    Failed to start service: Unit service not found 


    계속해서 서비스 파일이 등록안되고 찾을수 없다고 에러가 떳다





    원인은 이거다 


     It turns out that between the LTS versions of Ubuntu, Canonical decided that 15.04 would be the start of a transition from upstart to systemd as the default for managing boot and system service startup.


    Ubuntu의 LTS 버전 사이에서 Canonical은 부팅 및 시스템 서비스 시작 관리를위한 기본값으로 15.04가 upstart에서 systemd 로의 전환의 시작이라고 결정했다.






    우분투 14 에서 16으로 버전이 올라가는 과정에서 무언가가 있던게 사라진듯 싶다...



    해결법


    1. sudo apt-get install upstart-sysv

    2. sudo update-initramfs -u



    명령어 두번으로 15버젼에서 패치된 내용을 이렇게 적용 줄수있다 
















    프로세스의 개념 


    정의 : 행중인 프로그램 & 비동기적(Asynchronous) 행위



    실행중인 프로그램이란 


    디스크에 있던 프로그램을 메모리에 적재하여 


    운영체제의 제어를 받는 상태가 되었다는 의미이다




    프로그램에는 코드 , 정적 데이터가 들어가있다








    스택: 지역변수 ,호출함수 반환 주소  (스택은 아래쪽으로 주소할당)


    힙: 동적 메모리 할당 (힙은 위로 주소할당)


    데이터: 전역변수 ,정적변수 할당 , 실행전에 초기화 한다 


    코드: 실행 명령을 포함하는 메모리 또는 목적파일에 있는 프로그램 영역이다




    --------------------------------------------------------------------------


    프로세스의 상태변화 








    1. 준비 -> 실행 : Dispatch(p1) //디스패치


    2. 실행 -> 준비 : timeout(p1) // 타임아웃


    3. 실행 -> 대기 : block(p1) //블락


    4. 대기 -> 준비 : wakeup(p1) //깨움



    프로세스 제어 블록 (PCB)


    PCB는 프로세스 상태 정보를 저장한다 



    PCB 에 저장 되는 정보는 다음과 같다


    1.식별자 : 각 프로세스 고유 식별자


    2. 상태 : 생성, 준비, 실행, 대기, 중단 등 상태


    3. 프로그램 카운터(PC) : 프로세스 실행하는 다음 명령의 주소 표시


    4. 레지스터 저장 영역 :  컴퓨터 구조에 따라 형태가 다르다  인터럽트 발생시 PC와                                 함께 저장하여 재샐행할때 원래대로 복귀


    5. 프로세서 스케줄링 정보 : 프로세스의 우선순위, 스케줄링 큐의 포인터 

    기타 스케줄 매개변수


    6. 계정 정보 : 프로세서 사용 시간, 실제 사용시간  계정번호 , 프로세스 번호 등등


    7. 입출력 상태정보...

    8. 메모리 관리 정보 ..


    ...이하 기타 생략 ...




    프로세스의 문맥교환(Context Switching)



    정의 : 인터럽트나 시스템 호출 등으로 실행중인 프로세스의 제어를 다른 프로세스에             넘겨 실행상태가 되도록 하는 것을 컨택스트 스위칭이라 한다 


    프로세스를 이것저것 우선순위에 따라 변경하기 위해서는 프로세스 데이터를 레지스터와 메모리 사이를 왔다갔다 하며 복사해야 한다. 이런 일련의 과정을 context switching(컨텍스트 스위칭)이라고 한다. 



    <출처: http://www.cs.odu.edu/~cs471w/spring10/lectures/Processes.htm>








    메모리와 레지스터 사이의 데이터 이동도 I/O이다. 즉, 컨텍스트 스위칭 과정에서 I/O가 발생한다. 빈번한 I/O 발생은 overhead를 발생시킨다. 실행되는 process의 수가 많고, 빈번한 컨텍스트 스위칭이 발생한다면, 이는 성능을 떨어뜨린다

    하지만 I/O가 발생할 때, 멍~하게 기다릴 수도 없는 노릇이다. I/O가 발생할 때, CPU를 게속 사용하려면 컨텍스트 스위칭은 피할 수 없다.




    프로세스의 구조


    OS는 프로세스에서 


    생성, 종료, 제거, 중단(suspend), 재시작, 우선순위 변경, 대기, 문맥 교환 등 


    다양한 작업 가능 하다



    프로세스는 부모- 자식 관계를 유지하여 계층적으로 생성한다.



    프로세스의 생성


    1. 프로세스 식별자 할당

    2. 주소공간,PCB공간 같은 구성요소 할당

    3. PCB초기화, 

    4. 링크를 건다(해당 큐에 삽입)



    프로세스가 작업 수행하려면 필요한 자원을 부모 프로세스에게서 얻거나 

    운영체제에서 직접 필요한 자원을 얻어서 사용할수 있다.


    fork명령어 사용 2가지 이유


    1. 부모와 동일한 자식을 복제


    2. 자식 프로세스의 주소공간을 다른 프로그램 주소공간으로 덮어쓰기




    Context Switching 


    이전 프로세스의 상태 레지스터 내용을 보관하고 다른 프로세스의 

    레지스터를 적재하여 프로세스를 교환 하는

     일련의 과정을 문맥교환(Context Switching)이라고 한다























    'Computer Science' 카테고리의 다른 글

    리눅스 Service 등록 하기  (0) 2018.07.17
    리눅스 우분투 사용기  (0) 2018.03.11

    뭔가 억울한데 어디 하소연할수도 없고 진짜 하...


    아니.... 



    Retrofit2 로 구글API에서  자바빈으로 안받고  Json객체로 받으려고 


    @GET("maps/api/place/textsearch/json")
    Call<JSONObject> findDestinationWithRadius(@Query("query")String searchKeyword);


    이렇게 줬는데 계속해서 response.body()가 null이 들어오는 것이다..


    아니 이게 파싱이 안되면 익셉션이라도 떠야되는데 


    계속해서 null이 뜨길래 무슨 문제인지 계속 고민하다가 


    하필이면 비동기 통신이라서 동시성문제 인가 싶어서 Thread.sleep으로 일부로 지연시켜보고 별 짓을 다했는데 




    원인은 이거다




    JSONObject => org.json.JSONObject  객체이고


    JsonObject -> com.google.gson.JsonObject 객체이다 



    레트로핏2 빌드할때 GsonConverter를 줬는데 

    Retrofit retrofit=new Retrofit.Builder()
    .addConverterFactory(GsonConverterFactory.create())
    .client(client)
    .baseUrl(BASE_URI)
    .build();



    파싱 반환값음 org.json의 객체인 JSONObject로 반환 받으니까 


    익셉션이 안뜨고 그냥 null로 비워버리는 문제가 발생했다

    (이거 버그 같은데?)



    반환 값을 JsonObject로 바꾸니까 정상적으로 파싱되었다 



    아 진짜 나도 사수가 있었으면 좋겠다 

    무의미한 오타찾기 삽질기간을 줄이고 싶은데 항상 누구하나 물어볼사람은 없고...



    공부는 항상 외롭다.











    이 문서는 개인적인 목적이나 배포하기 위해서 복사할 수 있다. 출력물이든 디지털 문서든 각 복사본에 어떤 비용도 청구할 수 없고 모든 복사본에는 이 카피라이트 문구가 있어야 한다.

     

     

    22.1 소개

    스프링은 JDBC API를 통합했듯이 JMS API도 사용하기 쉽게 JMS 통합 프레임워크를 제공한다.

    JMS는 기능적으로 대략 두 부분으로 나눌 수 있는데 메시지의 생산(production)과 소비(consumption)이다. JmsTemplate 클래스는 메시지 생산과 동기적인 메시지 수신에 사용한다. Java EE의 메시지주도 빈(bean) 방식과 유사한 비동기적인 수신에 대해서 스프링은 메시지주도 POJO(MDP, Message-Driven POJOs)를 생성하는데 사용하는 다수의 메시지 리스너 컨테이너를 제공한다.

    org.springframework.jms.core 패키지는 JMS 사용에 핵심적인 기능을 제공한다. 이 패키지에 JdbcTemplate가 JDBC에 하듯이 리소스의 생성과 소멸을 다뤄줌으로써 JMS를 간편하게 사용하게 하는 JMS 템플릿 클래스가 있다. 스프링 템플릿 클래스와 공통되는 설계 원리는 더 세련된 사용방법을 위해서 공통되는 작업을 수행하는 헬퍼 메서드를 제공하고 작업을 처리하는 부분을 콜백 인터페이스를 구현한 사용자에게 맡기는 것이다. 이 클래스는 동기적으로 메시지를 보내고 메시지를 소비ㅎ고 JMS 세션와 메시지 생산자(producer)를 사용자에게 노출하는 다양한 편의 메서드를 제공한다.

    org.springframework.jms.support 패키지는 JMSException 변환 기능을 제공한다. 이 변환기능은 체크드 JMSException 계층을 동일한 계층의 언체크드 예외로 변환한다. 프로바이더에 특화된 체크드 javax.jms.JMSException의 하위클래스가 있다면 이 예외는 언체크드 UncategorizedJmsException로 감싸진다.

    org.springframework.jms.support.converter 패키지는 Java 객체와 JMS 메시지간에 변환을 하는 MessageConverter 추상화를 제공한다.

    org.springframework.jms.support.destination 패키지는 JNDI에 저장된 목적지에 대한 서비스 로케이터를 제공하듯이 JMS 목적지를 관리하는 다양한 전략을 제공한다.

    마지막으로 org.springframework.jms.connection 패키지는 독립 어플리케이션에서 사용하는데 적합한 ConnectionFactory의 구현체를 제공한다. 이 패키지에는 JMS를 위한 스프링 PlatformTransactionManager의 구현체도 있다.(이 이름은 JmsTransactionManager이다) 이는 JMS를 트랜잭션 리소스처럼 스프링의 트랜잭션 관리 메카니즘으로 어려움없이 통합할 수 있게 한다.

     

    22.2 스프링 JMS 사용

    22.2.1 JmsTemplate

    JmsTemplate 클래스는 JMS 코어 패키지의 핵심 클래스다. JmsTemplate 클래스는 메시지를 보내거나 동기적으로 메시지를 받을 때 리소르를 생성하고 제거하는 처리를 해주므로 JMS의 사용을 간단하게 해준다.

    JmsTemplate을 사용하는 코드는 고수준의 계약을 명확하게 정의해주는 콜백 인터페이스만 구현하면 된다. MessageCreator 콜백 인터페이스는 JmsTemplate에서 코드를 호출해서 제공한 Session의 메시지를 생성한다. JMS API의 더 복잡한 사용을 위해서 SessionCallback 콜백은 JMS 세션을 가진 사용자와 Session과 MessageProducer 쌍을 노출하는 ProducerCallback 콜백을 노출한다.

    JMS API는 두 종류의 send 메서드를 노출하는데 하나는 전송모드, 중요도, 서비스품질 (QOS, Quality of Service)로 time-to-live를 받고 하나는 QOS 파라미터를 받지 않고 기본값을 사용한다. JmsTemplate에 다수의 send 메서드가 있으므로 QOS 파라미터를 설정하는 것은 다수의 send 메서드의 중복을 피하기 위해 빈 프로퍼티로 노출된다. 비슷하게 동기적인 receive 호출의 타임아웃값은 setReceiveTimeout 프로퍼티로 설정한다.

    일부 JMS 프로바이더는 관리상(administratively) ConnectionFactory의 설정으로 기본 QOS 값을 설정할 수 있게 한다. MessageProducer의 send 메서드 send(Destination destination, Message message)를 호출해서 JMS 명세서에 나온 것과는 다른 QOS 기본값을 사용하게 할 것이다. 일관된 QOS 값의 관리를 위해서 JmsTemplate은 특히 isExplicitQosEnabled 프로퍼티를 true로 설정해서 자신만의 QOS 값을 사용하도록 되어야 한다.

    Note

    JmsTemplate 클래스의 인스턴스는 설정되고 나면 스레드 세이프하다. 이는 하나의 JmsTemplate 인스턴스를 설정해서 공유되는 참조로 여러 협력객체에 안전하게 주입할 수 있다는 의미이므로 중요하다. 좀 더 분명하게 JmsTemplate은 상태를 가지지만(ConnectionFactory에 대한 참조를 유지한다는 점에서) 이 상태는 대화식 상태는 아니다.

     

    22.2.2 연결

    JmsTemplate는 ConnectionFactory에 대한 참조를 필요로 한다. ConnectionFactory는 JMS 명세에 포함되어 있고 JMS와 동작하는 진입점으로 제공된다. 클라이언트 어플리케이션이 ConnectionFactory를 JMS 프로바이더의 연결을 생성하는 팩토리로 사용하고 다양한 설정 파라미터(대부분은 SSL 설정옵션 같은 벤더에 특화된 설정이다.)를 캡슐화한다.

    EJB에서 JMS를 사용하는 경우 벤더가 JMS 인터페이스의 구현체를 제공하므로 구현체가 선언적인 트랜잭션 관리에 참여하고 연결과 세션의 풀링을 수행한다. 이 구현체를 사용하려면 Java EE 컨테이너는 보통 EJB내의 resource-ref로 JMS 커넥션 팩토리나 서블릭 배포 디스크립터를 선언하도록 요구한다. EJB에서 이 기능과 JmsTemplate를 함께 사용하려면 클라이언트 어플리케이션이 ConnectionFactory의 관리된 구현체를 참조한다는 것을 보장해야 한다.

    22.2.2.1 메시징 리소스 캐싱

    표준 API에는 다수의 중간객체의 생성하는 API가 포함되어 있다. 메시지를 보내려면 다음의 'API'가 실행된다.

    C-like

    ConnectionFactory->Connection->Session->MessageProducer->send

    ConnectionFactory와 Send 작업사이에는 생성되고 소멸되는 세개의 중간 객체가 있다. 리소스의 사용을 최적화하고 성능을 높히기 위해 IConnectionFactory의 두 구현체를 제공한다.

    22.2.2.2 SingleConnectionFactory

    스프링은 ConnectionFactory 인터페이스의 구현체로 SingleConnectionFactory를 제공하고 SingleConnectionFactory는 모든 createConnection() 호출에서 같은 Connection을 반환하고 close() 호출은 무시할 것이다. 이는 다수의 트랜잭션이 걸친 여러 JmsTemplate 호출에 같은 연결을 사용할 수 있으므로 테스트와 독립적인 환경에 유용하다. SingleConnectionFactory는 일반적으로 JNDI에서 받은 표준 ConnectionFactory에 대한 참조를 받는다.

    22.2.2.3 CachingConnectionFactory

    CachingConnectionFactory는 SingleConnectionFactory의 기능을 확장하고 Session, MessageProducer, MessageConsumer에 캐싱을 추가한다. 초기 캐시크기는 1이고 캐시되는 세션의 수를 증가시키려면 SessionCacheSize 프로퍼티를 사용해라. 실제 캐시된 세션의 수는 승인 모드(acknowledgment mode)에 기반해서 캐시된 세션의 수보다 많을 것이므로 SessionCacheSize를 1로 설정한 경우(각 AcknowledgementMode마다 1) 캐시된 세션 인스턴스는 4까지 될 수 있다. MessageProducer와 MessageConsumer는 이들이 소유한 세션에 캐시되고 캐싱할 때 생산자(producer)와 소비자(consumer)의 유일한 프로퍼티를 고려한다. MessageProducer는 목적지에 기반해서 캐시된다. MessageConsumer는 목적지, 셀렉터, noLocal deliver 플래그, (durable consumer를 생성한다면)장기 구독 이름(durable subscription name)로 구성된 키에 기반한 캐시된다.

     

    22.2.3 목적지 관리

    ConnectionFactory같은 목적지는 JNDI로 저장하고 획득할 수 있는 JMS가 관리하는 객체다. 스프링 어플리케이션 컨텍스트를 설정할 때 JMS 목적지에 대한 객체의 참조에 의존성 주입을 하기 위해 JNDI 팰토리 클래스 JndiObjectFactoryBean / 를 사용할 수 있다. 하지만 어플리케이션에 아주 많은 목적지가 있거나 JMS 프로바이더에 특화되 고급 목적지 관리기능이 있다면 이 전력을 다루기 어려울 수 있다. 고급 목적지 관리에는 동적 목적지 생성이나 목적지의 계층적 네임스페이스 지원등이 있다. JmsTemplate은 목적지 처리를 JMS 목적지 객체나 DestinationResolver 인터페이스의 구현체에 위임한다. JmsTemplate이 기본 구현체로 DynamicDestinationResolver를 사용하고 동적 목적지를 처리한다. 제공된 JndiDestinationResolver는 JNDI에 있는 목적지의 서비스 로케이터처럼 동작하고 선택적으로 DynamicDestinationResolver의 동작으로 장애 복구를 한다.

    드물기는 하지만 JMS 어플리케이션이 상요하는 목적지를 런타임에서만 알 수 있는 경우에는 어플리케이션을 배포할 때 생성할 수 없다. 이러한 상황은 상호장용하는 시스템 컴포넌트가 잘 알려진 작명관례에 따라 런타임에서 목적지를 생성하고 이 시스템 컴포넌트간에 어플리케이션 로직을 공유하기 때문에 발생한다. 동적 목적지생성이 JMS 명세에 나와있지 않지만 대부분의 벤더는 이 기능을 제공하고 있다. 동적 목적 목적지는 임시 목적지와 구별할 수 있는 사용자가 정의한 이름으로 생성되고 JNDI에 등록되지 않기도 한다. 목적지와 관련된 프로퍼티가 벤더에 특화되어 있으므로 동적 목적지를 생성하는 API는 프로바이더마다 다양하다. 하지만 벤더가 만든 간단한 구현체는 JMS 명세의 경고를 무시하고 TopicSession 메서드 createTopic(String topicName)나 QueueSession 메서드 createQueue(String queueName)를 기본 목적지 프로퍼티로 새로운 목적지를 생성하는데 사용한다. 벤더 구현체에 따라서는 DynamicDestinationResolver가 목적지를 처리하는 것이 아닌 물리적인 목적지를 생성하기도 한다.

    불리언 프로퍼티인 pubSubDomain를 JmsTemplate이 어떤 JMS 도메인을 사용하는지 설정하는데 사용한다. 이 프로퍼티의 기본값은 false로 point-to-point 도메인인 Queue를 사용할 것임을 나타낸다. JmsTemplate이 사용하는 이 프로퍼티는 DestinationResolver 인터페이스의 구현체로 동적 목적지 처리의 동작을 결정한다.

    defaultDestination 프로퍼티를 사용해서 기본 목적지로 JmsTemplate를 설정할 수도 있다. 기본 목적지는 목적지를 명시하지 않은 보내기/받기 작업에 사용할 것인다.

     

    22.2.4 메시지 리스너 컨테이너

    EJB에서 JMS 메시지의 가장 일반적인 경우는 메시지주도 빈(MDB, message-driven beans)를 사용하는 것이다. 스프링은 사용자가 EJB 컨테이너에 의존하지 않는 방법으로 메시지 주도 POJO(MDP, message-driven POJO)를 생성하는 방법을 제공한다. (스프링의 MDP 지원의 자세한 내용은 Section 22.4.2, “비동기 수신 - 메시지 주도 POJO”를 참고해라.)

    메시지 리스너 컨테이너는 JMS 메시지 큐에서 메시지를 받고 큐에 주입할 MessageListener를 생성하는데 사용한다. 리스너 컨테이너는 메시지 접수와 처리할 리스너로 디스패치하는 모든 스레드를 책임진다. 메시지 리스너 컨테이너는 MDP와 메시지 프로바이더 사이의 중개자의 역할을 하고 받은 메시지의 등록, 트랙잭셤 참여, 리소스 획득과 릴리즈, 예외 변환등을 담당한다. 이를 통해서 어플리케이션 개발자는 메시지를 받는(그리고 응답을 해야할 수도 있다) 비즈니스 로직(복잡할 수도 있다.)을 작석할 수 있고 JMS 인프라스트럭처의 보일러플레이트에 대한 걱정을 프레임워크에 위임할 수 있다.

    스프링에는 두개의 표준 JMS 메시지 리스너 컨테이너가 있고 각 컨테이너는 전문화된 기능을 가진다.

    22.2.4.1 SimpleMessageListenerContainer

    이 메시지 리스너 컨테이너는 두 표준보다 간단하다. 구동할 때 고정된 수의 JSM 세션과 컨슈머를 생성하고 표준 JMS MessageConsumer.setMessageListener() 메서드를 사용해서 리스너를 등록하고 JMS 프로바이더나 리스너 콜백을 실행하도록 한다. 이 컨테이너는 동적으로 런타임 요구사항에 맞출 수 없고 외부에서 관리하는 트랜잭션에 참여할 수는 없다. 호환성을 위해서 독립적인 JMS 명세서에 아주 가깝지만 보통 Java EE의 JMS 제약사항에는 호환되지 않는다.

    22.2.4.2 DefaultMessageListenerContainer

    이 메시지 리스너 컨테이너는 가장 많이 사용하는 것 중 하나이다. SimpleMessageListenerContainer와는 달리 런타임 요구사항을 동적으로 맞출 수 있고 외부에서 관리하는 트랜잭션에 참여할 수 있다. JtaTransactionManager를 설정한 경우 받는 각각의 메시지를 XA 트랜잭션에 등록하므로 처리할 때 XA 트랜잭션의 장점을 가질 수 있다. 이 리스너 컨테이너는 JMS 프로바이저의 낮은 요구사항과 트랜잭션 참여같은 고급 기능과 Java EE 환경에 호환성 간의 균형을 잘 맞추고 있다.

     

    22.2.5 Transaction management

    스프링은 단일 JMS ConnectionFactory의 트랜잭션을 관리하는 JmsTransactionManager를 제공한다. JmsTransactionManager는 Chapter 11, 트랜잭션 관리에서 설명한 스프링이 관리하는 트랜잭션 기능을 JMS 어플리케이션이 사용하도록 한다. JmsTransactionManager는 로컬 리소스 트랜잭션을 수행하고 JMS 연결/세션 쌍을 지정한 ConnectionFactory에서 스레드로 바인딩한다. JmsTemplate는 자동으로 이러한 트랜잭션이 가능한 리소스를 탐지해서 적절하게 리소스상에서 작업을 실행한다.

    Java EE 환경에서 ConnectionFactory는 연결과 세션의 풀을 사용하므로 이러한 리소스를 트랜잭션사이에서 효율적으로 재사용한다. 독립적인 환경에서 스프링의 SingleConnectionFactory를 사용하면 공유된 JMS Connection를 사용하게 되고 각 트랜잭션은 자신만의 독립적인 Session을 갖게 된다. 아니면 ActiveMQ의 PooledConnectionFactory 클래스처럼 프로바이더에 특화된 풀링(pooling) 어댑터를 사용하는 것을 고려해 봐라.

    JmsTemplate를 JtaTransactionManager나 분산 트랜잭션을 위해서 XA 기능을 가진 JMS ConnectionFactory와 함께 사용할 수도 있다. 이 경우 XA로 잘 설정한 ConnectionFactory같은 JTA 트랜잭션 관리자를 사용해야 한다! (사용하는 Java EE 서버나 JMS 프로바이더의 문서를 참고해라.)

    Connection에서 Session을 생성하려고 JMS API를 사용하는 경우 관리하는 트랜잭션 환경과 관리하지 않는 트랜잭션 환경사이에서 코드를 재사용하는 것이 혼란스러울 수 있다. 이는 JMS API가 Session을 생성하는 팩토리 메서드를 딱 하나만 가지고 있고 트랜잭션과 승낙(acknowledgement) 모드에 대한 값을 필요로 하기 때문이다. 관리되는 환경에서는 해당 환경의 트랜잭션 인프라가 이러한 값을 설정하므로 JMS 연결을 감싸는 벤더의 랩퍼는 이러한 값을 무시한다. 관리되지 않는 환경에서 JmsTemplate을 사용하는 경우 sessionTransacted와 sessionAcknowledgeMode 프로퍼티를 사용해서 이러한 값을 지정할 수 있다. PlatformTransactionManager와 JmsTemplate를 같이 사용하는 경우 템플릿은 항상 트랜잭션이 가능한 JMS Session을 가질 것이다.

     

    출처: <https://blog.outsider.ne.kr/985



    매우 좋으신분 근데 생각보다 젊으셨음 


    학생이라는 신분이 이럴때는 좋은가보다 .


    학문적으로 순수한 호기심에 현업자들을 찾아 뵙고 이야기 나누는 일은 정말 즐겁다.


    이런 다소 예의 없을수있는 교류는 학생의 신분을 가질때만 가능한 일이지 않을까

     

    Domain Driven Develop 



    도메인 지향 개발 방법론 



    국내에 DDD 관련 책을 다양하게 있는 것도 아니고 



    에릭 에반스 개발자 분의 책은 정말 어렵다 .. 


    번역체 문제 같은 것들이 아니라   내용이 매우 추상적이고   


    개발 경험이 적은 나로써는  그 내용들을 받아들이기 매우 어려웠다.


    DDD start 라는 최범균 개발자님이 쓰신 책으로 DDD를 다시 읽는데 


    역시 소스코드를 직접 보는게 제일 좋은 방법인듯 싶다.




    소스코드 품질 관리 측면에서 DDD는 매우 좋은 방법론이다.


    단순히 비지니스 로직을 작성하는데


    user.changePassword("4321"); 으로 도메인 내부에 로직을 정의하는 것과


    user.setPassword("4321") 로  getter setter로 이렇게 정의 하는 것은 


    직관적인 내용에서 차이가 있다. 

    (비밀번호 변경이라는 로직이 단순히 password 문자열 변경으로 


    끝나지 않는다는 것을 고려한다면 


    로직은 Service 계층이랑은 관련없는 소스코드들로 가득 채워 질수 도 있다.

    사소하다 생각할수 있겠지만 

     

    이러한 사소한 내용들 하나하나가 모여서 소스코드의 품질을 좌우한다

    )




    DDD 는 실무에서 사용할수 있는가?       


    최범균 개발자님께 물어봤다.


    내 친구들은 아무도 최범균 개발자님이 누구인지도 모르고 나만 신났다. 


    이러니까 내가 아싸지......



    내가 느끼는 DDD는 마치 f-32 전투기 같았다.  


    최고의성능을 가진 전투기가 주력전투기가 아니다.

     가성비가 좋은 f-15가 주력 전투기가 되듯이


    DDD는  이것을 모르고 이해하려고 들지도 않는 개발자들과 같이 협업을 했을때 


    나혼자 DDD 한다면 그것은 오히려 소스코드의 통일성을 깰수도 있고


    DDD를  모르는 사람 입장에서 그저 getter setter로 작업할수 있는 내용을 

    2~3 개의 클래스를 더 만들어서 

    더욱 소스코드를 복잡하게 만들었다고 느낄 수있다. 



    10명의 개발자중 3명만 그내용을 몰라서  

    3명의 작업량이 기존 방식대로 작업을 했을때 낼수있는 생산성에 비해 현저히 떨어진다면 

    이것을 과연 우두머리 급들이 좋아 할까?



    특히나 국내 SI 업계 처럼 소스코드의 품질을 무시하는 이러한 분위기에서 DDD는 빛좋은 개살구가 아닐까 


    현업을하면서 나는 


    "아 이렇게 짜면 안되는데 DDD를 써야지 " 라고  불평해서


    다른사람들을 귀찮게 하는  불편한 존재가 되지는 않을까





     








    + Recent posts