일반 html 

<img src="/img/..." onerror="imgError(this)"/>


// javascript
function imgError(imgTag){
imgTag.onerror="";
    imgTag.src="/img/noname.jpg";
    return true;
}

 

 

Vue 

1. <img> Tag

  <img
    v-if="item.imgSrc != null"
    :src="item.imgSrc"
    :alt="item.imgAlt"
    @error="$event.target.src=require('@/assets/img/no-Img.jpg')"
  />
  <img
    v-else
    :src="require('@/assets/img/no-Img.jpg')"
    :alt="item.imgAlt"
  />

 @error="$event.target.src=require('@/assets/img/no-Img.jpg')"

 

 

2. CSS background-image

<div 
   :style="{
          'background-image': 'url(' + item.imgSrc + '),url('+require(`@/assets/img/no-Img.jpg`) +')',
        }"
>
</div>

background-image:url(이미지),url(에러이미지) 로 설정할 수있다. 

'개발자 > FRONT' 카테고리의 다른 글

[Vue.js] Style 관련 img url 적용 정리  (0) 2021.04.22
[인프런] TDD 수업 정리  (0) 2019.09.10

QueryDsl 에서 다중 In 조건을 사용하여 개발

 

1
2
3
4
5
6
7
8
9
10
11
12
13
List<Tuple> list = from(member)
            .where(
                    Expressions.list(member.agtNm, member.sessId).in(
                            JPAExpressions
                                    .select(Expressions.list(member.agtNm, member.sessId))
                                    .from(member)
                                    .where(member.regYmd.between(stDate, edDate))
                                    .groupBy(member.agtNm,member.sessId)
                                    .having(member.sessId.count().gt(1))
                    )
            )
            .groupBy(member.agtNm)
        .select(member.agtNm, member.count()).fetch();
cs

 

  • querydsl 에서 다중 in 조건을 사용하려면 Expressions.list 를 사용해야한다.
  • querydsl은 select, where 에서만 서브쿼리를 지원하고 있다. 
  • (select절 서브쿼리 : 스칼라서브쿼리, From절 서브쿼리 : 인라인뷰 서브쿼리, where절 서브쿼리 : 중첩서브쿼리)
  • JPAExpressions를 통해 서브쿼리를 생성한다.
  • select 에서는 ExpressionUtils.as( JPAExpressions.select(
  • where 절의 서브쿼리에서는 그냥 JPAExpressions 만 사용하면 된다.

 

 

 

참고

[Querydsl] 서브쿼리 사용하기

https://jojoldu.tistory.com/379

QueryDSL multiple subselect - (a,b) in (select c,d)

https://kic1.tistory.com/102

[ Oracle ] SQL 서브쿼리 SELECT, FROM, WHERE

https://mjn5027.tistory.com/51

https://mozi.tistory.com/233

 

1. Node Express 서버에 oracle DB를 사용하기 위해 oracledb 설치

npm install --save oracledb

 

설치 확인

 

 

2. C++을 지원하는 C 컴파일러 설치

Visual Studio 2019 Version 설치

경로 : support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0

Visual Studio Installer 설치하면서 C/C++ 데스크탑 개발을 추가로 선택해서 설치한다.

 

 

 

3. Python 설치

node-oracledb를 컴파일 하기 위해 필요함.

경로 : https://www.python.org/downloads/

 

 

 

4. Oracle Instant Client 설치

설치를 안했을경우 윈도우에서 아래와 같은 에러 발생.

cx_Oracle error. DPI-1047: Cannot locate a 64-bit Oracle Client library

윈도우에서 실행 시 발생한 에러 

 

설치경로 : www.oracle.com/database/technologies/instant-client/downloads.html

 

컴퓨터 환경에 맞는 client 로 설치 한다. 

zip 파일을 받고 C 드라이브 아래 위치시킨다.

내 PC 환경변수 > Path 에 C:\dev\instantclient_19_10  등록한다.

 

 

 

설치, path 설정 완료 후 Visual Studio Code 로 프로젝트를 다시 오픈 하면 

TedisPool 정보가 나타나며 서버 실행이 된다.

 

 

 

 

참고

stackoverflow.com/questions/56119490/cx-oracle-error-dpi-1047-cannot-locate-a-64-bit-oracle-client-library

 

cx_Oracle error. DPI-1047: Cannot locate a 64-bit Oracle Client library

I installed the library and when trying to access SQL in jupyter notebook with my credentials the following error appears: DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "The

stackoverflow.com

willbesoon.tistory.com/120

 

style을 적용할때 image url이 css파일쪽에 위치하는지 인라인 방식인가에 따라 asset의 경로가 달라집니다.

 

 

 

1. img 태그 사용. src로 호출

<div class="item"><img src="../assets/img/help/01.jpg" alt="화면 1"></div>
<div class="item"><img src="../assets/img/help/02.jpg" alt="화면 2"></div>
<div class="item"><img src="../assets/img/help/03.jpg" alt="화면 3"></div>

RequestURL : http://localhost:8081/dist/assets/images/01.jpg?

자동으로 dist 하위로 수정되어 요청됩니다

 

 

 

 

2. div의 인라인(Inline style) 방식으로 backgroundImage 호출하기

- 인라인 방식 : 태그에 직접 사용하는 방식이며 style 속성을 함께 사용합니다

<div
   class="item"
   v-bind:style="{
     backgroundImage:
        'url(' + require('../assets/img/help/01.jpg') + ')',
         backgroundRepeat: 'no-repeat',
         backgroundPosition: 'center center',
         backgroundSize: 'contain',
     }"
>
  <span class="bg_clip">이미지</span>
</div>


//background:url("../assets/img/help/01.jpg") no-repeat center center;background-size:contain;

RequestURL : http://localhost:8081/dist/assets/images/01.jpg?

 

* vue에서 인라인 방식을 사용하기 위해서는 v-bind 로 style 을 적용해야하며 사용하고자하는 css의 style 명칭 확인하고 적용해야합니다

* url 호출을 위해 require 적용해야합니다

 

 

 

 

3. CSS 파일에서 적용할때 

.img1 {background:url(../img/help/01.jpg) no-repeat center center;background-size:contain; }
.img2 {background:url(../img/help/02.jpg) no-repeat center center;background-size:contain; }
.img3 {background:url(../img/help/03.jpg) no-repeat center center;background-size:contain; }

RequestURL : http://localhost:8081/dist/assets/images/01.jpg?

css폴더와 img 폴더의 경로가 /assets 하위일 경우

 

 

 

 

4. Vue파일의 <style> 로 적용할때

<style scoped>
.img1 {background:url("../assets/img/help/01.jpg") no-repeat center center;background-size:contain; }
.img2 {background:url("../assets/img/help/02.jpg") no-repeat center center;background-size:contain; }
.img3 {background:url("../assets/img/help/03.jpg") no-repeat center center;background-size:contain; }
</style>

RequestURL : http://localhost:8081/dist/assets/images/01.jpg?

 

 

 

기타

stackoverflow.com/questions/35242272/vue-js-data-bind-style-backgroundimage-not-working#

'개발자 > FRONT' 카테고리의 다른 글

[Vue] img 에러 처리방식 정리  (0) 2022.03.29
[인프런] TDD 수업 정리  (0) 2019.09.10

socket.io 를 사용하여 실시간 양방향 통신 작업을 하며 공부한 내용에 대하여 정리했습니다.

 

1. 웹 브라이저에서의 양방향 통신

 

기존 웹 페이지에서 사용하는 http 프로토콜은 무상태 프로토콜으로 요청/응답 패러다임으로 이루어져 있어 이전 요청과도 무관한 각각의 요청을 독립적인 트랜잭션으로 취급하며 클라이언트에서 요청을 보내야만 응답을 받을 수 있는 통신 프로토콜입니다. 하지만 동적인 기능이 많이 요구되면서 요청을 보내지 않아도 서버에서 클라이언트 쪽으로 데이터를 보내야 하는 경우가 많아졌습니다. 그래서 Polling, Long Polling, Streaming 방식을 이용하여 비슷한 효과를 구현하였습니다.

 

 

● Polling

  • 클라이언트에서 일정 주기마다 요청을 보내고 서버는 현재 상태를 바로 응답하는 방식입니다.
  • 이 방식은 실시간으로 반영되는 것이 중요한 서비스에는 별로 좋지 않고 서버에서 변화가 없더라도 매 요청마다 응답을 내려주기 때문에 불필요한 트래픽이 발생하게 됩니다.

 

 

Long Polling

  • 클라이언트에서 요청을 보내고 서버에서는 이벤트가 발생했을 때 응답을 내려주고 클라이언트가 응답을 받았을때 다시 다음 응답을 기다리는 요청을 보내는 방식입니다.

 

  • 실시간 반응이 가능하고 polling에 비해서 불필요한 트래픽은 유발하지는 않지만 오히려 이벤트가 잦다면 순간적으로 과부하가 걸리게 됩니다.

 

 

● Streaming

  • 이벤트가 발생했을때 응답을 내려주는데 응답을 완료시키지 않고 계속 연결을 유지하는 방식입니다.

 

  • Long Polling에 비해 응답마다 다시 요청을 하지 않아도 되므로 효율적이지만, 연결 시간이 길어질수록 연결의 유효성 관리의 부담이 발생합니다.

위와 같은 방법들을 이용하여 양방향 통신을 구현할 수도 있지만 이제는 HTML5에서 소켓 연결을 하는 websocket이 표준으로 등록되어 이를 이용하여 서버-클라이언트간의 동적인 양방향 통신을 구현할 수도 있게 되었습니다.

 

 

 

websocket

websocket이란 웹 서버와 웹 브라우저간 실시간 양방향 통신환경을 제공해주는 실시간 통신 기술입니다. 위의 Polling 방식(요청-응답방식)과 다르게 양방향으로 원할때 요청을 보낼 수 있으며 stateless한 HTTP에 비해 오버헤드가 적으므로 유용하게 사용할 수 있습니다.

 

socket.io

HTML5 WebSocket은 오래된 브라우저의 경우 지원하지 않는 경우가 있습니다. 브라우저 간 호환을 고려하여 Node.js를 위한 강력한 Cross-platform WebSocket API인 Socket.io를 사용하는것을 권장하고 있습니다. 

Socket.io란 위에서 설명한 WebSocket과 같이 클라이언트와 서버의 양방향 통신을 가능하게 해주는 모듈입니다.

socket.io는 통신을 시작할 때, 각 브라우저에 대해서 websocket, pooling, streaming, flash socket 등에서 가장 적절한 방법을 찾아 메시지를 보내줍니다. 그 덕분에 socket.io를 통해 개발을 하면 websocket이 지원이 되지 않는 브라우저에서도 메시지를 양방향으로 주고 받을 수 있습니다.

 

 

 

2. Socket 사용방법

 

Server side 환경 (node.js)

- express : 4.15.4

- socket.io : 2.3.0

 

io.on(‘connection’, callback) 과 같이 연결되었을 때의 이벤트를 정의하고 각 소켓에 대해서 on(‘event’, callback) 과 같이 원하는 이벤트를 작성할 수 있습니다.

 

index.ts

// index.ts
import {socket} from "./socket/socket";
import * as socketIO from "socket.io";
 
// create express app
const app = express();
const http = require('http').Server(app);
const io = socketIO(http);
  
// socket
socket(io.of('/chat'),pool);

URL의 경로 이름으로 지정된 네임스페이스에 대해 새 Socket 인스턴스가 반환됩니다.

기본값은 '/' 인데 위에서는 '/chat' 으로 정했습니다.

 

socket.ts

// socket.ts
export function socket(chat, pool) {
    chat.on('connection', async (socket: any) => {

        socket.on('sendMessage', async (data) => {
            console.log(socket.id + " : sendMessage");
            chat.to(data.user_id + data.create_dt).emit('sendMessage', data);
        });

        socket.on('join', async (data) => {
            console.log(socket.id + " : join");
            socket.join(data.user_id + data.create_dt);
            chat.to(data.user_id + data.create_dt).emit('join', data);
        });

        socket.on('out', (data) => {
            console.log(`out ${data}`);
            socket.leave(data.user_id + data.create_dt);
            chat.to(data.user_id + data.create_dt).emit('out', data);
        });

        socket.on('disconnect',async (reason) =>{
            console.log(socket.id + " : disconnected");
        });
    });
}

 

 

Client side 환경

- Vue : 3.x

- socket.io-client : 2.4.0

 

클라이언트 부분에서는 socket.io-client 모듈을 이용하여 쉽게 서버와 연동할 수 있습니다.

그리고 서버에서와 마찬가지로 on, off로 이벤트 리스너를 켜고 끌 수 있으며 emit함수로 서버의 이벤트를 발생시킬 수 있습니다.

 

  var socketIO = require("socket.io-client");
  
  // 소캣 생성
  this.socket = socketIO.connect(`${BASE_URL_SOCKET}/chat`, {
        path: '/someapi/socket.io',
        transports: ['websocket'],
        rejectUnauthorized: false
  });
  
  
  // 소캣 이벤트 작성
  this.socket.off("join");
  this.socket.off("sendMessage");
  this.socket.off("out");

 // socket on join
 this.socket.on("join", (data) => {
 	console.log("socket:on:::join", data);
 });

// socket on sendMessage
this.socket.on("sendMessage", (data) => {
	console.log("socket:on:::sendMessage", data);
});

// socket on out
this.socket.on("out", (data) => {
	console.log("socket:on:::out", data);
});

 

소캣으로 대화를 시작할때 시점

네트워크 환경에 따라 소캣 연결 시간이 다르기 때문에 대화를 시작하는 이벤트를 따로 추가했습니다.

  this.socket.on("connect", () => {
      console.log("socket:on:connect");
      this.createRoom(); // 대화시작
 });

 

소캣연결 에러 감지

this.socket.on("connect_error", (reason) => {
   console.log("socket:on:connect_error", reason);
   alert("채팅연결이 불안정합니다. ::" + reason);
   this.createdSocket(); // 소캣 socketIO.connect() 재시도
});

- 소캣 커넥션이 좋지않다면 재시도를 해보고 연결이 아예 안되는경우는 일반 api를 사용하게 작업했습니다.

 

 

 

Options

- path : '/someapi/socket.io'  를 사용하면 redirect 할 수 있습니다. 기본값 url 로 요청되던 socket.io이 url+특정우회주소 로 요청됩니다. 

예를들어 base_url_socket이  tistory.com/ 라면, path를 추가하면 tistory.com/someapi/  방식으로 소켓 커넥션이 요청됩니다. tistory.com/someapi 로 /someapi가 가리키는 포트로 redirect 되어 커넥션이 설정되고, /chat에 대한 Socket.io-client 연결이 생성됩니다.   

자세한 설명은 아래 참고의 docs에서 확인하실 수 있습니다.

 

- forceNew (Boolean) 기존 connection 재사용 여부

    

 

 

참고

 

socket.io 서버 api 

https://socket.io/docs/server-api/ 

 

Redirecting...

 

socket.io

socket.io-client 서버 api

socket.io/docs/client-api/

 

Redirecting...

 

socket.io

stackoverflow.com/questions/9729308/socket-io-connection-url

 

Socket.io connection url?

I have the current setup: Nodejs Proxy (running http-reverse-proxy) running on port 80. Rails server running on port 3000 Nodejs web server running on port 8888 So any request starting with /...

stackoverflow.com

 

+ Recent posts