팝업을 쓰다보면 이벤트의 반응이 팝업에 즉시 반영되도록 해야하는 경우가 있다

 

 

예를 들면, 위와 같이 필터를 클릭했을 때, 나머지 필터들을 흑백처리해 시각적으로 강조하고 싶을 수 있다

 

팝업을 직접 만들어 사용하면 별 문제 없겠지만, 난 귀찮아서 써본적있는 sweetalert2를 대충 적용했고, 여기서부터 문제가 발생했다. (그때는 spring에 jsp로 프론트를 뿌리고 있었으니까...)

 

Filter를 저장하는 state는 상위 컴포넌트에 있고 Swal.fire로 html을 쏴주면 팝업이 정상적으로 뜨는데, 팝업 내부에서 클릭을 해도 팝업이 변하지 않는다.

그런데 팝업 뒤에서 페이지에는 필터가 적용되고 있었다. 이벤트는 정상적으로 발생했는데 Swal의 팝업만 업데이트가 되지 않는 것이다.

 

대충 알아본 원인은 SweetAlert 팝업 내부는 호출한 상위 React 컴포넌트와 따로 life cycle을 가진다는 것? (부정확할 수 있음)

아무튼 상위 컴포넌트에서 state가 변해도 SweetAlert html 변화에 따른 re-render가 발생하지 않는다는게 문제점이다.

 

그럼 해결법은 간단하다. SweetAlert 내부에도 re-render 이벤트를 만들어버리면 된다

 

https://codesandbox.io/s/fork-sweetalert-react-e6utz0?file=/src/index.js 

 

fork-sweetalert-react - CodeSandbox

fork-sweetalert-react by natonato using react, react-dom, react-scripts, sweetalert2, sweetalert2-react-content

codesandbox.io

 

위 예제 샌드박스를 보면 state를 각각 관리하고 있다 (대충 긁어왔더니 react가 많이 구버전...)

상위 컴포넌트인 App에 count가 하나

this.state = {
  count: 0
};

SweetAlert에 html으로 사용되는 Count 컴포넌트에도 count가 하나

this.state = {
  count: this.props.count
};

그리고 SweetAlert를 사용할 때, Count 컴포넌트에 App의 count와 setCount를 넘겨준다

MySwal.fire({
  title: "react swal",
  html: (
    <Count
      count={this.state.count}
      onChangeValue={(value) => {
        this.setState({ count: value });
      }}
    />
  )
});

Count에선 받은 App의 count로 자기 count를 초기화하고, setState도 자기 state와 받은 App의 함수를 같이 호출해준다

onClick={() => {
  this.setState({ count: this.state.count + 1 });
  this.props.onChangeValue(this.state.count + 1);
}}

 

팝업과 본문 실시간 업데이트

즉, re-render를 위해 Count에도 똑같은 state를 설정하고 상위 App 컴포넌트의 state와 동기화를 맞춰주는 방식이다.

 

솔직히 귀찮다. 필요없는 state와 동기화 로직을 추가해야 하기도 하고, props가 많아질수록 답이 안나오는 작업이 될 것 같다.

 

이미 SweetAlert를 여기저기 static한 팝업에 때려박아서 어떻게든 활용하고자하는 사람이 아니라면, 직접 만들거나 React에 최적화 잘 된 다른 좋은 팝업 패키지를 찾아보는게 어떨까 싶다. 복잡한 팝업일수록 더더욱.

0. 시작 이유

 

전원이랑도 연결해야하고! 랜케이블이랑도 연결해야하고! 모니터! 키보드! 마우스!! 내가 전선에 파묻혀 죽겠다!!

해서 기존 모니터/키보드/마우스를 공유해 사용하려고 시도해 보았습니다

 

  • VNC로 윈도우 PC에서 원격 사용하기
  • KVM 스위치 구매해서 윈도우PC와 같이 물려놓고 스위칭

이렇게 2가지 방법을 생각해봤는데.. 돈 안드는 1번에서 잘 해결 되었습니다

 

+ 전 편의상 모니터/키마 다 연결한채로 시작했습니다. GUI 최고!

터미널로도 같은 동작 가능합니다

 

 

1. vim 설치하기

 

기본적으론 vi만 깔려있고 vim이 없습니다

vi보단 vim이 여러모로 편하므로 깔아주면 좋습니다

sudo apt-get install vim

위 명령어를 통해 vim을 설치, 사용 가능합니다

 

 

2. 라즈베리파이 고정 IP 설정하기

 

네트워크 우클릭하면 나오는 Wireless & Wired Network Settings에 들어갑니다

유선랜은 eth0, 무선은 wlan0이 있습니다

IPv4 Address에 사용하고 싶은 IP주소를,

Router에는 공유기 주소를, (보통 저 주소입니다)

DNS 주소는 원하는 DNS 서버의 주소를 입력합니다 (8.8.8.8은 구글 DNS 주소입니다)

재부팅 후 ifconfig 명령어를 터미널에 입력해보면 다음과 같이 설정된 ip를 확인 가능합니다

만약 변경 후 인터넷 접속이 되지 않는다면, 해당 IP를 이미 선점중인 기기가 있는지 확인해야 합니다

  • 공유기 관리자 화면에서 확인하거나
  • 라즈베리파이 종료 후 해당 IP로 핑을 쳤는데 응답이 돌아온다거나
  • 해당 IP로 접속했는데 관리자 화면(프린터 등)이 뜬다거나...

해당 경우에는 다른 빈 IP로 바꿔주면 됩니다

 

 

3. VNC 설정하기

 

우선 윈도우에 VNC viewer 프로그램을 설치해줘야합니다

 

Download VNC Viewer | VNC® Connect

VNC® Connect consists of VNC® Viewer and VNC® Server Download VNC® Viewer to the device you want to control from, below. Make sure you've installed VNC® Server on the computer you want to control. Frequently asked questions How do I install VNC® View

www.realvnc.com

여기서 윈도우용 뷰어를 설치했습니다

 

그리고 라즈베리파이에서 VNC 설정을 켜줘야합니다

여기서 켜줄수도 있고,

터미널 창에 sudo raspi-config 명령 입력 후

Interface Options - VNC Options - Enable 및

Display Options - VNC Resolution 에서 해상도 선택하면 됩니다

 

두 방법의 차이는 찾아봐도 모르겠네요... 둘 다 해도 잘 됩니다

 

이후 설치했던 VNC viewer에서 File - New connection 후 VNC Server에 라즈베리파이의 IP를 입력, (Name은 마음대로)

생성된 아이콘을 클릭해서 Username, Password 입력하면

이렇게 잘 접속이 됩니다

 

 

4. 보안설정

 

 

18. 라즈베리 파이 보안 설정

라즈베리 파이에 있어서 보안은 중요합니다. 보안에 신경 쓰지 않는 것은, 해커가 당신의 허가 없이 라즈베리 파이를 사용하도록 열어두는 것과 같습니다. 어느 수준의 보안이 ...

wikidocs.net

보안은 위 문서 따라가면서 하면 될 것 같습니다

바로 아래 써있지만 잘 되던 윈도우 PC 접근도 차단하는거 보면 잘 작동하는듯 합니다

 

위 과정 중 신규 유저 생성 후 기본 유저(pi) 삭제가 있는데, SSH의 경우는 신규 유저로 접속 후 삭제하면 되고 GUI로 진행할 경우 

위 사진처럼 로그아웃 - Logout 한 후 다른 계정으로 접속하면 해결됩니다

 

만약 xxx번 프로세스가 실행중이라 pi 계정을 삭제할 수 없다고 하면, 다음 명령어를 입력하면 해결됩니다

// xxx = process number
kill -9 xxx

 

 

5. VNC 포트 방화벽 해제하기

 

위 과정에서 UFW 방화벽을 적용하고나니, 윈도우 PC에서 VNC가 작동하지 않습니다

 

Timed out waiting for a response from the computer

그런데 라즈베리파이는 정상적으로 작동 중이고, putty를 통한 SSH 접속은 잘 됩니다

 

원인을 찾아보니 VNC를 사용하기 위한 포트가 방화벽에 차단된 게 문제였습니다 (참고)

 

sudo ufw allow 5900

위 명령어를 통해 5900 포트를 방화벽 규칙에 등록하면, VNC가 다시 잘 작동됩니다

인터넷 연결도 다시 잘 됩니다

 

부팅 중의 과정 등에선 접속되지 않아 조금 아쉽긴 하지만, 이미 세팅된 키보드/마우스/모니터를 이용해서 라즈베리파이까지 이용할 수 있게 되었습니다!

3.3 -> 5 -> 3.3 순으로 찍었습니다

확실히 소음은 3.3이 훨씬 덜하네요

온도는 뭐 빡센작업 시킬거 아니라..시스템 업데이트중에도 53도정도 유지했습니다 (현재 한겨울인점은 감안)

대충 이것저것 들어있는 중고 라즈베리파이를 구했습니다

빵판이나 GPIO 확장모듈은 일단 필요 없으니 케이스 조립부터 하겠습니다

케이스 구성품은
상판 / 하판 / 팬 모듈 / 나사 12개 / 써멀패드 3개 입니다


먼저 상단 판에 팬 두개를 조립했습니다(나사 8개 사용)
위쪽 핀으로 쉽게 연결될수 있도록 두 팬의 전선부를 가깝게 두었습니다

그 후 써멀패드 3장을 부착했습니다
부착 위치는 상판 뒷면에 튀어나와있는 부분 3곳입니다


상판을 맞춰서 조립해주고,

하판과 상판을 나사로 이어주면 케이스 조립은 끝납니다


대충 구동확인. 잘 돌아갑니다
5V에 연결했더니 팬 소음이 생각보다 심합니다
연장선을 추가해서 3.3V에 연결해볼 생각입니다

 

지금까지 진행된 사항들 (영상참고)

(기존)

  • ID와 메세지를 입력시 자동으로 Favorite 캐릭터와 소환수 정보를 크롤링, 이미지로 생성해준다
  • 데스크탑 / 모바일 각 4종씩 8종류의 배경 제공 (추가 가능)
  • 이미지 다운로드 가능 (웹 상 이미지는 크기 수정된 이미지, 다운로드는 원본)
  • 이미지 + 정보 텍스트를 전용 트위터 계정에 공유 가능

(12.26 추가)

  • Bootstrap 기반 frontend 페이지 작성
  • 일정 시간(하루) 내 동일 ID 중복실행 방지
    • 기존 이미지 반환, twitter 업로드도 1일 1회 제한
  • 검색 기능 구현
    • 트위터 고급 검색 결과 페이지로 redirect
  • error 페이지 구현
    • 세부 에러 처리는.....

 

 

앞으로 진행할? 사항들

 

  • 프론트엔드 페이지 추가 작업
    • alert 창으로 결과 여부 고지
    • 검색 UI 개선
  • chrome의 업데이트에 따른 chromedriver문제 해결 고민하기..
  • 배포하기

 

 

지금까지 진행된 사항들 (영상참고)

 

  • ID와 메세지를 입력시 자동으로 Favorite 캐릭터와 소환수 정보를 크롤링, 이미지로 생성해준다
  • 데스크탑 / 모바일 각 4종씩 8종류의 배경 제공 (추가 가능)
  • 이미지 다운로드 가능 (웹 상 이미지는 크기 수정된 이미지, 다운로드는 원본)
  • 이미지 + 정보 텍스트를 전용 트위터 계정에 공유 가능

 

 

앞으로 진행할? 사항들

 

  • 일정 시간 내 동일 ID 중복실행 방지
    • 변경사항 반영하지 않고 기존 생성된 이미지 반환할 예정
    • Twitter 업로드도 불가능
    • 일정 시간마다 작업한 이미지들 삭제하는것도 가능..한가?
  • 프론트엔드 페이지 좀 꾸미기
    • 하지만 결과는 처참했다!
  • 검색기능 구현
    • 1. 요구사항에 맞게 트위터 업로드 결과 필터링해서 보여주기 (최선)
    • 2. 요구사항에 맞는 트위터 검색 결과 페이지로 redirect (차선)
    • 3. 트위터에 검색할 수 있는 문자열 제공 (최소)
  • error 페이지 구현 및 세부 에러/예외처리
  • chrome의 업데이트에 따른 chromedriver문제 해결 고민하기..

 

사유 : static 폴더에 생성된 이미지는 서버 구동 이후에 자동으로 업데이트되지 않음

Spring devtools를 쓰면 된다고 하지만, intellij에서 추가적인 설정도 필요하고,

init 단계가 반복 호출되면 망가져서 사용 불가

결국 File을 백엔드에서 프론트로 직접 전달(byte[]의 형태로)

 

 

1. File을 byte[]로 변경해 전송하기 (백엔드)

 

@GetMapping("/getImage/{id}")
public ModelAndView getImage(@PathVariable String id,
                                    ModelAndView mav){
    try (InputStream inputStream = new FileInputStream("src/main/resources/static/image/"+id+".jpg")){
        byte[] byteArray = IOUtils.toByteArray(inputStream); // to byte array
        mav.addObject("playerImg",Base64.getEncoder().encodeToString(byteArray)); // base64 encode
        mav.setViewName("playerInfo"); // set html file
        return mav;
    }catch (Exception e){
        mav.setViewName("redirect:/error");
        return mav;
	}
}
  • File을 받아온 후, byte[]로 변경해서 사용, common-io의 IOUtils를 사용하였다 (링크)
  • 원활한 사용을 위해 base64로 인코딩하였다
  • try-with-resources를 이용, close문은 생략 가능

 

 

2. 전송받은 byte[] 표시 및 다운로드 제공 (프론트)

 

<img th:src="'data:image/jpeg;base64,'+${playerImg}">
<a download="Profile.jpg" th:href="'data:image/jpeg;base64,'+${playerImg}">다운로드!</a>
  • download 속성 값을 변경해 다운로드 파일 이름 변경 가능
  • JSP나 기타 방식으로도 문법만 일치시키면 동일하게 사용 가능하다

 

 

3. 적용 결과

 

결과 화면

  • 좌측 웹 사이트에서 이미지 정상 출력
  • 우측 다운로드 이미지 정상 출력

[이전글]

 

 

대충 취업준비 스터디 이런저런사정 등등으로 바빠서 한동안 작업하기도 힘들었고... 글로 정리하기도 힘들었습니다

 

일단 현재 시점까지 작업한 내용으론

 

 

1. Spring boot기반으로 변경

  • 외부 lib 매번 파일로 넣고 설정해주기 귀찮다...
  • Maven/Gradle 최고!
  • properties 관리도 최고!!
  • @Autowired랑 자동 싱글톤도 최고!!!

 

 

2. 이미지 생성 수정

<<이전                     현재>>

  • 이름, 랭크 등 출력 (ID 추가 예정)
  • 소환석 정보 속성에 맞춰 배치 및 레벨/이름 출력
  • 최대 3줄까지 메세지 입력받아 이미지에 출력
  • 계정의 favorite 캐릭터를 받아와서 배경에 함께 출력 (기본 : 루리아)

 

 

3. 트위터 업로드 기능 구현

  • ID / 이름 / 소환석 정보를 포함
  • 생성된 이미지 포함 자동 업로드
  • Twitter4j는 Java 11에서 잘 작동하지 않나..? 8로 내리니까 많은 문제가 해결됬다

+ Recent posts