728x90
반응형

🧭 1. VisualVM 소개

VisualVM은 JDK에 포함된 jvisualvm 또는 독립 실행형 형태로 제공되는 JVM 모니터링 및 분석 도구입니다.
다음과 같은 기능을 제공합니다.

🔹 주요 기능

기능설명
CPU / 메모리 모니터링 힙(Heap) / PermGen(Metaspace) 사용량, GC(Garbage Collection) 횟수 확인
스레드 상태 추적 실행 중 스레드, 데드락, Runnable/Waiting 상태 추적
프로파일링(Profiling) CPU, 메서드 호출 빈도, 메모리 할당 추적
Heap Dump 분석 힙 덤프를 시각적으로 분석하여 메모리 누수 탐지
원격 모니터링(Remote Monitoring) 원격 서버의 톰캣 프로세스 모니터링 가능 (JMX 또는 jstatd 사용)

⚙️ 2. Tomcat 연동 방법

(1) 로컬 톰캣

  • 같은 PC에서 톰캣 실행 시 자동으로 VisualVM이 JVM 프로세스를 탐지합니다.
  • 그냥 jvisualvm 실행 → “Local” 탭에서 org.apache.catalina.startup.Bootstrap 프로세스 선택하면 됩니다.

(2) 원격 톰캣

  1. 톰캣 실행 옵션에 JMX 포트 설정
  2.  
    CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
  3. 톰캣 재시작 후 VisualVM에서 원격 호스트 추가
    • VisualVM → Add Remote Host
    • “JMX Connection”으로 hostname:9090 입력
  4. 원격 연결 시 방화벽 9090 포트 허용 필요합니다.

⚠️ 3. 운영 시 주의점

구분주의사항설명
성능 부하 ⚠️ 실시간 프로파일링(Profiling) 시 CPU 점유율 상승 운영 서버에서는 “모니터링”만, 프로파일링은 테스트 환경에서만 수행
보안 ⚠️ JMX 인증 미설정 시 누구나 접근 가능 운영 환경에서는 jmxremote.access / jmxremote.password 파일로 인증 필수
메모리 사용량 증가 VisualVM 연결 시 JVM의 Metaspace와 Heap 사용량 소폭 증가 일시적인 영향이므로 큰 문제는 없으나, 여유 메모리 확보 권장
방화벽 설정 ⚠️ JMX 포트 외부 노출 금지 내부망에서만 접근하거나 SSH 터널링을 사용
Heap Dump 크기 대형 서비스는 Heap Dump 시 수백 MB~수 GB 발생 가능 운영 중에는 Heap Dump 남발 금지 — 스냅샷은 트래픽 저하 유발 가능

🧩 4. 권장 운영 방식

목적방법
개발·테스트 환경 VisualVM을 이용해 GC 튜닝, 스레드 분석, 메모리 누수 점검
운영 환경 기본 JMX 연결만 유지하고, 필요할 때만 접속
장기 모니터링 VisualVM 대신 Prometheus + Grafana 또는 JMX Exporter를 통해 안정적 시각화 추천

💡 팁

  • 플러그인 설치로 기능 확장 가능 (Visual GC, Thread Inspector 등)
  • JDK 버전별 호환성 주의 — JDK 17 이상에서는 최신 VisualVM (2.x 이상) 사용
  • SSH 터널링을 이용하면 JMX 포트를 외부로 열지 않고도 원격 모니터링 가능:
  •  
    ssh -L 9090:localhost:9090 user@your-server

📈 5. VisualVM 실무 팁

  • Visual GC 플러그인 설치 → GC 동작 시각화
    → Tools > Plugins > Available Plugins > Visual GC
  • Heap Dump는 꼭 트래픽 낮은 시간에 수행
  • 자동 모니터링은 VisualVM 대신 Prometheus + JMX Exporter 연동 추천

728x90
반응형
728x90
반응형

리액트는 수정시에 웹소켓으로 React Hot Reload로 웹페이지를 새로 리로드 시켜준다.

그러나 proxy 설정으로 해당 에러 발생시 React 설정

 

React webSocket connection to 'wss://주소:3000/ws' failed

#에러
React webSocket connection to 'wss://주소:3000/ws' failed
#구성

[사용자 브라우저]
   ⇅ HTTPS (443)
[Caddy 서버]
   ⇅ (localhost:3000 으로 프록시)
[SSH 터널링으로 연결된 3000포트]
   ⇅
[docker-compose codeserver에 React 3000]
#caddy 설정 
URL주소 {
    reverse_proxy localhost:3000
    tls mail@mail.com
    log {
        output discard
    }
}
#docker-compose 설정
services:
  code-server:
    image: lscr.io/linuxserver/code-server:latest
    container_name: code-server
    restart: always
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Seoul
      - PASSWORD=
      - SUDO_PASSWORD=
      - PROXY_DOMAIN= URL 주소
      - DEFAULT_WORKSPACE=/config/workspace
    volumes:
      - D:\codeserver/config:/config
    ports:
      - 8085:8443
      - 3000:3000
#해결 .env 설정
React root에 .env 파일 생성


#WebSocket 설정
WDS_SOCKET_PORT=0        <-------------해당 설정만 넣으면 해결가능
#WDS_SOCKET_HOST=url 주소
#WDS_SOCKET_PORT=443
#WDS_SOCKET_PATH=/ws
#HTTPS=true

# 폴링 설정
CHOKIDAR_USEPOLLING=true
WATCHPACK_POLLING=true

 

나는 라즈베리파이로 낮은 성능이라 caddy로 proxy설정하였는데

Nginx Proxy Manager로 proxy 설정시에도 동일할로 예상합니다.

728x90
반응형

'Programming > React' 카테고리의 다른 글

React & Spring Boot  (0) 2024.02.17
slack clon coding  (0) 2023.03.29
728x90
반응형

# node 다운로드

https://nodejs.org/download/release/latest-v20.x/node-v20.11.1-win-x64.zip

 

# C:\dev 폴더생성

 

# node 

C:\dev\node-v20.11.1-win-x64 에 압축풀기

 

# yarn 설치

C:\dev\node-v20.11.1-win-x64\npm install yarn --global

아래 에러 발생시

C:\dev\Veltrix_React_v5.1.0\Admin>C:\dev\node-v20.11.1-win-x64\yarn install
yarn install v1.22.21
[1/4] Resolving packages...
warning Lockfile has incorrect entry for "moment@^2.29.4". Ignoring it.
error Error: certificate has expired
    at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
    at TLSSocket.emit (node:events:518:28)
    at TLSSocket._finishInit (node:_tls_wrap:1085:8)
    at ssl.onhandshakedone (node:_tls_wrap:871:12)
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

 

ssl/tls 인증서가 만료 https 경고 해제 후 다시 설치

npm config set strict-ssl false
npm install -save react-scripts
npm install -g react-scripts

npm install yarn --global

 

ssl/tls 인증서가 만료 https 경고 해제 후 다시 설치

yarn config set strict-ssl false

 

# React 테마 Veltrix_React_v5.1.0 (유료)

구매한 테마가 있어서 그냥 사용. 다른 테마 사용 등 선택사항

https://themeforest.net/item/veltrix-react-js-admin-dashboard-template/32471505

 

Veltrix - React Js Admin & Dashboard Template

Veltrix is a fully featured premium admin dashboard template built in React Redux Saga with firebase / fake-backend authentication and multi-language supports with developer-friendly code...

themeforest.net

React 테마 Veltrix_React_v5.1.0 아래경로에 복사

C:\dev\Veltrix_React_v5.1.0

 

#React install

CMD로 cd C:\dev\Veltrix_React_v5.1.0\Admin 이동

C:\dev\Veltrix_React_v5.1.0\Admin>C:\dev\node-v20.11.1-win-x64\yarn install

 

#React start

C:\dev\Veltrix_React_v5.1.0\Admin>C:\dev\node-v20.11.1-win-x64\yarn start

 

#http://localhost:3000/

 

리액스 테마 샘플구동 까지 작성...

계속 업데이트 예정...

 

#vscode 설치

https://code.visualstudio.com/Download

 

Download Visual Studio Code - Mac, Linux, Windows

Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Download Visual Studio Code to experience a redefined code editor, optimized for building and debugging modern web and cloud applications.

code.visualstudio.com

설치파일이아닌 zip파일로 받음 (선택사항)

 

압축을 풀어준뒤 실행하면 된다.

 

 

#vscode spring-boot 플러그인 설치

Extension Pack for Java

Spring Boot extension pack

Lombok Annotations Support for VS Code

 

#자바 17버전 다운로드 및 설정

https://jdk.java.net/archive/

 

Archived OpenJDK GA Releases

Archived OpenJDK General-Availability Releases This page is an archive of previously released builds of the JDK licensed under the GNU General Public License, version 2, with Classpath Exception. WARNING: These older versions of the JDK are provided to he

jdk.java.net

 

#자바 HOME 설정

file > Preferences > Settings

 

java:home > Edit in settings.json

 

 

#Spring Boot 프로젝트 생성

[Ctrl] + [Shift] + [P]

Spring Initializr  엔터

 

 

#vscode 테마변경

Ctrl + K, T

 

#vscode node 터미널 새창에서 실행이 아닌 기본창에서 실행 설정

 

#vscode 패키지 구조가 아닌 폴더구조로 보기 

(단축키: Ctrl + ,) Compact Folders 검색 >  Explorer: Compact Folders 해제

 

#vscode 폴더 아이콘 표시

 

파일 아이콘 테마 설정 

폴더별 아이콘이 직관적으로 표시 된다.

 

#rest api 호출을 위한 Thunder Client 설치 (postMan 대신)

 

#Database manager

#Open in browser (alt + b)

728x90
반응형

'Programming > React' 카테고리의 다른 글

React webSocket connection to 'wss://주소:3000/ws' failed  (0) 2025.09.02
slack clon coding  (0) 2023.03.29
728x90
반응형

Json String to VO

 

@RequestMapping(value="/smp/grd/gridSample02Save.do")
    public @ResponseBody String gridsave(@RequestParam String list, HttpServletRequest request ) throws Exception{        
		
		////////////////////////////////
		//Json형태 String to List<VO>
		////////////////////////////////
		Map<String, List<GridVO>> map = new ObjectMapper().readValue(list, new TypeReference<Map<String, List<GridVO>>>(){});
		
		List<GridVO> updateList = map.get("updateList");
		List<GridVO> addList = map.get("addList");
		List<GridVO> deleteList = map.get("deleteList");
		
		for(GridVO gridVO : updateList){
			System.out.println(gridVO.getBoardName());
		}

		for(GridVO gridVO : addList){
			System.out.println(gridVO.getBoardName());
		}

		for(GridVO gridVO : deleteList){
			System.out.println(gridVO.getBoardName());
		}
		
		////////////////////////////////
		//Json형태 String to List<Map> 
		////////////////////////////////
		Map<String, List<Map>> map01 = new ObjectMapper().readValue(list, new TypeReference<Map<String, List<Map>>>(){});

		List<Map> updateList01 = map01.get("updateList");
		List<Map> addList01 = map01.get("addList");
		List<Map> deleteList01 = map01.get("deleteList");
		
		for(Map mapData : updateList01){
			System.out.println(mapData.get("boardName"));
		}

		for(Map mapData : addList01){
			System.out.println(mapData.get("boardName"));
		}

		for(Map mapData : deleteList01){
			System.out.println(mapData.get("boardName"));
		}
		
        return list;
    }
728x90
반응형
728x90
반응형

이클립스 화면설계 플러그인

 

https://wireframesketcher.com/download.html

 

Download WireframeSketcher - WireframeSketcher

Try WireframeSketcher for free before you buy it. The software is fully functional for 14 days. After the evaluation period is over, you’ll need a license key in order to save your work. System requirements 64-Bit Operating System: Windows 7, Windows 8,

wireframesketcher.com

 

728x90
반응형

'Programming > JAVA' 카테고리의 다른 글

자바 JVM 모니터링  (0) 2025.10.30
Json String to VO  (0) 2023.04.01
WEB 크롤링 - Selenium  (0) 2023.03.29
WIN10 ipconfig wsl ip tunneling  (0) 2023.03.29
Windows에서 JNA를 사용하여 Java에서 메모리를 조작하는 방법  (0) 2023.03.29
728x90
반응형

파이썬 간단한 파일 공유

공유할 폴더로 이동후에

 

python3 -m http.server 8000

 

서버아이피:8000으로 접속하면 파일목록이 보인다.

 

728x90
반응형
728x90
반응형

Selenium

 

 

이번 프로젝트에서 기존 사이트의 게시판 글을 모두 마이그레이션 해달라는 요청있었다.

처음에는 DB로 데이터를 받을 수있는지 협의해봤는데 DB는 줄수 없다고 답변을 받았다.

그래서 크롤링으로 모두 마이그레이션 하려고 Selenium을 이용하였다.

 

Selenium은 실제 브라우저랑 연동이되어 크롤링 하지 못하는게 없는 강력한 소프트웨어이다.

 

C#, Ruby, Java, Python, JavaScript를 지원한다.

 

난 여기서 내가 쉽게 할 수 있는 Java를 택했다.

 

소스를 코딩한뒤에 실행하면 설정한 브라우저(크롬)이 하나 실행되고 그 브라우저를 바탕으로 크롤링이 된다.

해당 소스를 코딩뒤에 마이그레이션을 빌미로 잘 놀았던것 같다. ^^

 

아래는 내가 구현한 소스이며 더 디테이하게 구현가능하나 간단하게 필요한 부분만 끌거오게 구현하고 프로그램을 돌렸다. 

일회성이라 특별한 기능은 없다.

package board;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.dataloader.Try;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.openqa.selenium.By;
import org.openqa.selenium.Pdf;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.print.PrintOptions;
import org.openqa.selenium.remote.RemoteWebDriver;

import board.service.MyBatisService;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Paths;

import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter;

public class SeleniumTest {

    public static void main(String[] args) {

    	try {

    		MyBatisService service = new MyBatisService();
    		List<Map<String,Object>> list = service.select();
    		for (Map<String,Object> dept : list) {
    			System.out.println(dept);
    		}



        SeleniumTest selTest = new SeleniumTest();
        //selTest.crawl();
        selTest.crawl2();

    	} catch (Exception e) {
			e.printStackTrace();
		}
    }


    //WebDriver
    private WebDriver driver;

    //Properties
    public static final String WEB_DRIVER_ID = "webdriver.chrome.driver";
    public static final String WEB_DRIVER_PATH = "D:\\mig\\chromedriver_win32\\chromedriver.exe";

    //크롤링 할 URL
    private String base_url;

    public SeleniumTest() {
        super();

        //System Property SetUp
        System.setProperty(WEB_DRIVER_ID, WEB_DRIVER_PATH);

        //Driver SetUp
        ChromeOptions options = new ChromeOptions();
        //options.addArguments("headless");
        //driver = new ChromeDriver();

        //options.setHeadless(true);


        driver = new ChromeDriver(options);
        //base_url = "https://www.naver.com";
        //base_url = "https://www.ppomppu.co.kr/zboard/zboard.php?id=ppomppu";
        base_url = "크롤링할 기본 url";


    }

    public void crawl2() throws IOException {

        try {
            //get page (= 브라우저에서 url을 주소창에 넣은 후 request 한 것과 같다)
            driver.get(base_url);
            try {Thread.sleep(30000);} catch (InterruptedException e) {}


            driver.get("file:///C:/Users/ksmro/Desktop/img.html");

            List<WebElement> els =  driver.findElements(By.xpath("/html/body/a"));


            int i = 0;
            for(WebElement el : els) {
            	System.out.println(i++);
            	el.click();






            	try {Thread.sleep(1000);} catch (InterruptedException e) {}
            }



        }catch (Exception e) {
			e.printStackTrace();
		}

    }

    public void crawl() throws IOException {

    	InputStream in = null;
		OutputStream  out = null;

        try {
            //get page (= 브라우저에서 url을 주소창에 넣은 후 request 한 것과 같다)
            driver.get(base_url);
            try {Thread.sleep(10000);} catch (InterruptedException e) {}



        	int start = 1;
        	int end = 1;
        	String gubun = "구분";
        	String category = "카테고리";
        	String url = "크로링할 URL";

        	Map<String,Object> paramMap = new HashMap<String, Object>();


        	for(int i=start ; i <= end; i++) {
        		driver.get(url + i);
        		//String xpath = "//*[@id=\"53f2b5ad-c15f-482c-8380-75591d206874-a81109f3-bc61-4a8e-8f78-4074ed88811d\"]/tbody/tr";
                //List<WebElement> els = driver.findElements(By.xpath(listXpath));
        		List<WebElement> els = driver.findElements(By.className("ms-itmhover"));


                System.out.println(els.size());

                //List<WebElement> els = driver.findElements(By.xpath("//*[@id=\"d5a214f5-f73f-403a-b4af-f17a8da580c4-0a2feff5-66d5-4555-8fac-935a012105de\"]/tbody/tr"));


                ArrayList<Map<String,Object>> urlList = new ArrayList<Map<String,Object>>();

                if(els.size() == 0) {
                	break;
                }

                var mainImgIdx = 0;

                for(WebElement el : els) {

                	System.out.println(el.getAttribute("innerHTML"));

                	Map<String,Object> map = new HashMap<String, Object>();


                	//WebElement elImg= el.findElement(By.xpath("//span[@class = 'img_box ui-data-thumbnail']"));
                	//String main_img = elImg.findElement(By.tagName("img")).getAttribute("src");

                	//String main_img = el.findElements(By.tagName("img")).get(el.findElements(By.tagName("img")).size()-2).getAttribute("src");
                	String main_img = null;
                	//String main_img = el.findElement(By.xpath("/td/table/tbody/tr/td[2]/div/div["+(++i)+"]/span/img")).getAttribute("src");
                	//String main_img = el.findElement(By.className("img_thumbnail")).findElement(By.tagName("img")).getAttribute("src");


                	//category = null;
                	//try{
                	//	category = el.findElements(By.className("ms-vb2")).get(1).getText();
                	//}catch (Exception e) {
					//	e.printStackTrace();
					//}

                	//news
                	//String link = el.findElement(By.tagName("a")).getAttribute("href");
                	//code
                	String link = null;
                	try{
                		link = el.findElement(By.className("ui-anchor")).getAttribute("href");
                	}catch (Exception e) {
                		e.printStackTrace();
					}



                	System.out.println("link : " + link);

                	if(link != null) {
                		System.out.println(link);
                		//urlList.add(link);
                		map.put("main_img", main_img);
                		map.put("link", link);
                		map.put("category", category);
                		urlList.add(map);
                	}


                	//driver.get(link);
                	//WebElement title = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[1]/div/p"));
                	//System.out.println(title);
                	//WebElement body = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div"));
                	//System.out.println(body);
                }

                for(Map<String,Object> urlMap : urlList) {

                	String urlStr = (String)urlMap.get("link");
                	String main_img = (String)urlMap.get("main_img");
                	//String category = (String)urlMap.get("category");

                	//if("".equals(category)) {
                	//	continue;
                	//}

                	//String uuid = urlStr.replace(idXpath, "");
                	String uuid = null;
                	System.out.println("id : " + uuid);

                	driver.get(urlStr);
                	WebElement webElementTitle = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[1]/div/p"));
                	String title = webElementTitle.getText();
                	System.out.println("제목 : " + title);

                	//WebElement webElementBody = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div"));
                	WebElement webElementBody = null;
                	String body = null;

                	try {
                		webElementBody = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div/div"));
                		body = webElementBody.getAttribute("innerHTML");
                	}catch (Exception e) {
                		e.printStackTrace();
                		body = "";
                	}

                	//String body = webElementBody.getAttribute("innerHTML");
                	System.out.println("내용 : " + body);

                	WebElement webElementCreateDate = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[1]/div/ul/li[2]/span"));
                	String create_date = webElementCreateDate.getText();
                	System.out.println("작성일 : " + create_date);


                	WebElement webElementUser = driver.findElement(By.xpath("//*[@id=\"ctl00_PlaceHolderMain_UFAuthor_Iink_Userlink\"]"));
                	String user_nm = webElementUser.getText();
                	String user_id = webElementUser.getAttribute("href").replace("javascript:fnUserInfo('", "").replace("');", "");
                	System.out.println("작성자 : " + user_nm);
                	System.out.println("user_id : " + user_id);


                	//Document doc = Jsoup.parse(body.getAttribute("innerHTML"));
                	//System.out.println(doc.html());


                	//image down

                	paramMap.put("uuid", uuid);
                	paramMap.put("title", title);
                	paramMap.put("user_id", user_id);
                	paramMap.put("user_nm", user_nm);
                	paramMap.put("create_date", create_date);
                	paramMap.put("body", body);
                	paramMap.put("main_img", main_img);
                	paramMap.put("category", category);

                	paramMap.put("gubun", gubun);

                	MyBatisService service = new MyBatisService();

                	System.out.println("paramMap : " + paramMap);
            		service.insertTmpBoard(paramMap);



                	//*[@id="{DC565DD2-0037-496B-87F2-0A3BA50535D0}"]
                	//*[@id="idAttachmentsTable"]/tbody//a
                	List<WebElement> files = driver.findElements(By.xpath("//*[@id=\"idAttachmentsTable\"]/tbody//a"));
                	for(WebElement file : files) {
                		String fileUrl = file.getAttribute("href");
                		String fileNm = file.getText();
                		System.out.println("file_url : " + fileUrl);
                		System.out.println("file_name : " + fileNm);
                		paramMap.put("file_url", fileUrl);
                		paramMap.put("file_nm", fileNm);

                		service.insertTmpFile(paramMap);
                	}

                	//*[@id="part1"]/div[3]/div[2]/div[1]/div/div/div/img
                	//List<WebElement> imgs = driver.findElements(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div/div/table/tbody/tr[2]//img"));
                	List<WebElement> imgs = driver.findElements(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div/div//img"));

                	for(WebElement img : imgs) {

                		String imgUrl = img.getAttribute("src");

                		System.out.println("imgUrl : " + imgUrl);

                		paramMap.put("img_url", imgUrl);
                		service.insertTmpImg(paramMap);

                		//driver.get(imgUrl);

                		 //URL urlImage = new URL(img.getAttribute("src"));
        				//String fileName = Paths.get(urlImage.getPath()).getFileName().toString();

        				//BufferedImage saveImage = ImageIO.read(urlImage);

                        //download image to the workspace where the project is, save picture as picture.png (can be changed)
        				//ImageIO.write(saveImage, "jpg", new File("D:/mig/img/"+ fileName + ".jpg"));




        				//String USER = users.get(i).replace(".", "_");

        				//File dir = new File("D:/mig/img/" + id);
        				//if ( !dir.exists() ) {
        				//	dir.mkdir();
        				//}
                        //
        				//in = urlImage.openStream();
        				//out = new FileOutputStream("D:/mig/img/" + id + "/" + fileName); //저장경로
                        //
        	            //while(true){
        	            //    //이미지를 읽어온다.
        	            //    int data = in.read();
        	            //    if(data == -1){
        	            //        break;
        	            //    }
        	            //    //이미지를 쓴다.
        	            //    out.write(data);
                        //
        	            //}
                        //
        	            //in.close();
        	            //out.close();

        			}

                }
        	}


        } catch (Exception e) {

            e.printStackTrace();

        } finally {

        	 if(in != null){in.close();}
             if(out != null){out.close();}
        }

    }

}

chromedriver_win32.zip
6.78MB
selenium.z01
17.00MB
selenium.zip
10.09MB

728x90
반응형
728x90
반응형

안드로이드 폰에 Nextcloud 설치

 

사용하지 않는 폰이 있는데 어떻게 활용할까 찾던 중 안드로이드 폰에 Nextcloud가 설치가 가능하다는 것을 찾았다.

Nextcloud란 개인 파일이나 사진 이메일을 사용할 수 있는 어플리케이션이다.

Clone code using MGit (optional, you can also just use the terminal)
Set "root storage location for repos" to something like /storage/emulated/0
Clone with: Remote URL https://github.com/nextcloud/server.git, Local Path nextcloud (doesn’t support 2FA – if you use that get an app token and log in with that)
Clone the 3rdparty submodule too, local path nextcloud/3rdparty
Install (and optionally clone as well) with Termux
First install some dependencies pkg install php php-fpm sqlite coreutils openssl-tool
Allow Termux to access storage outside of own folder termux-setup-storage
(If you want to clone with Termux: cd /storage/emulated/0/ && git clone https://github.com/nextcloud/server.git nextcloud)
Get the Nextcloud submodules cd /storage/emulated/0/nextcloud/ && git submodule update --init
Start the server php -S 0.0.0.0:8080 -t /storage/emulated/0/nextcloud/
Finish setup in Firefox
Go to http://0.0.0.0:8080
Set an admin username and password in the
(SQLite will be used as database)

실제로 가이드대로 안쓰는 구글픽셀 원에 실행해보니 정상적으로 사용이 가능했다.

오래전에 설치해봐서 현재 설치 사진은 없다.

 

https://github.com/jancborchardt/nextcloud-scripts/blob/master/nextcloud-on-android.md

 

GitHub - jancborchardt/nextcloud-scripts: ☁️ Scripts to easier set up & update Nextcloud

☁️ Scripts to easier set up & update Nextcloud. Contribute to jancborchardt/nextcloud-scripts development by creating an account on GitHub.

github.com

 

728x90
반응형

+ Recent posts