추가: ssh는 기존 pem파일 로그인, sftp는 비번 로그인으로 설정하는 법. /etc/ssh/sshd_config 파일 에 추가. 

# 공개 키 인증을 기본으로 사용
PasswordAuthentication no
PubkeyAuthentication yes

# SFTP만 비밀번호로 허용
Match Group sftpusers  (이건 맞는 그룹으로 변경필요) 
    PasswordAuthentication yes
    PubkeyAuthentication no
    ForceCommand internal-sftp

$sudo systemctl restart sshd

 

 

SFTP(Secure File Transfer Protocol)를 사용하기 위해서는 현재 설정된 vsftpd를 변경할 필요는 없습니다. SFTP는 SSH(Secure Shell) 서비스로 작동하기 때문입니다. CentOS 7에서 SFTP를 사용하도록 설정하는 방법은 다음과 같습니다:

1. SSH 설치 및 실행 확인

SFTP는 SSH를 통해 작동하므로, SSH 서버(sshd)가 설치되고 실행 중인지 확인해야 합니다.

 
sudo yum install openssh-server sudo systemctl start sshd sudo systemctl enable sshd

2. SFTP 사용자 설정

이미 cncity라는 사용자가 있습니다. 이 사용자가 유효한 쉘(예: /bin/bash)을 가지고 있고 올바른 홈 디렉토리를 가지고 있는지 확인합니다:

bash
 
sudo usermod -s /bin/bash cncity

사용자의 홈 디렉토리가 존재하고 올바른 권한을 가지고 있는지 확인하세요:

bash
 
sudo mkdir -p /home/centos/nfs/cncity sudo chown cncity:cncity /home/centos/nfs/cncity

3. SFTP만 허용하도록 사용자 제한 (선택 사항)

만약 SFTP만 허용하고 전체 SSH 접근을 제한하려면, SFTP를 위한 제한된 쉘을 설정할 수 있습니다:

SSH 설정 파일 편집:

bash
코드 복사
sudo vi /etc/ssh/sshd_config
cncity 사용자에 대한 SFTP 제한 설정 추가:

plaintext
코드 복사
Match User cncity
    ForceCommand internal-sftp
    ChrootDirectory /home/centos/nfs
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
ForceCommand internal-sftp는 사용자가 SFTP만 사용하도록 강제합니다.
ChrootDirectory /home/centos/nfs는 사용자를 지정된 디렉토리(/home/centos/nfs)로만 제한합니다.
ChrootDirectory는 root가 소유하고 사용자에게 쓰기 권한이 없어야 합니다.
Chroot 디렉토리의 권한 설정:

bash
코드 복사
sudo chown root:root /home/centos/nfs
sudo chmod 755 /home/centos/nfs
SSH 서비스 재시작:

bash
코드 복사
sudo systemctl restart sshd

 

 

4. 기본적으로는 id/비번만으로 동작함. but 키 인증기반으로 변경할 수도 있음.

1. 기본 설정 (암호 인증)
클라이언트에게 제공할 것: 사용자 이름과 비밀번호
설명: SFTP 접속 시 클라이언트는 서버의 IP 주소, 사용자 이름, 비밀번호만으로 접속할 수 있습니다. 추가적인 인증 키나 인증서는 필요하지 않습니다.
보안 수준: 기본적인 암호 인증은 충분히 안전하지만, 키 기반 인증보다 상대적으로 보안이 낮을 수 있습니다.
2. 키 기반 인증 (더 안전한 방법)
클라이언트에게 제공할 것: 개인 SSH 키 (Private Key)

설정 방법:

서버에서 SSH 키 쌍을 생성 (클라이언트가 생성할 수도 있음):

bash
코드 복사
ssh-keygen -t rsa -b 2048
이 명령을 실행하면 id_rsa(개인 키)와 id_rsa.pub(공개 키)라는 두 개의 파일이 생성됩니다.

클라이언트의 공개 키를 서버에 복사:

공개 키 파일(id_rsa.pub)을 서버의 사용자의 홈 디렉토리에 있는 ~/.ssh/authorized_keys 파일에 추가합니다:

bash
코드 복사
cat id_rsa.pub >> /home/cncity/.ssh/authorized_keys
SSH 설정 파일에서 키 인증 사용 (이미 기본적으로 활성화되어 있을 수 있음):

/etc/ssh/sshd_config 파일을 열고 PubkeyAuthentication이 yes로 설정되어 있는지 확인합니다:

plaintext
코드 복사
PubkeyAuthentication yes
SSH 서비스 재시작:

bash
코드 복사
sudo systemctl restart sshd
클라이언트 측: 클라이언트는 개인 키(id_rsa)를 SFTP 접속 시 사용해야 합니다. SFTP 클라이언트에서 개인 키를 설정하거나, 명령줄에서 다음과 같이 사용할 수 있습니다:

bash
코드 복사
sftp -i /path/to/private_key cncity@your_server_ip
보안 수준: 키 기반 인증은 암호 기반 인증보다 안전합니다. 개인 키를 분실하지 않도록 주의해야 하며, 개인 키는 암호로 보호하는 것이 좋습니다.
Posted by yongary
,

vsftpd for CentOS7

IT 2024. 9. 4. 16:44

기본 설치 방법.

sudo yum install vsftpd

sudo systemctl start vsftpd
sudo systemctl enable vsftpd

 

 

 

sudo vi /etc/vsftpd/vsftpd.conf 기본설정 항목. 

# 익명 사용자 접속 금지
anonymous_enable=NO

# 로컬 사용자 접속 허용
local_enable=YES

# 업로드 권한 부여
write_enable=YES

# 사용자 홈 디렉토리를 루트 디렉토리로 설정
chroot_local_user=YES

# FTP에 허용할 사용자 목록을 지정하는 설정
userlist_enable=YES
userlist_file=/etc/vsftpd/user_list
userlist_deny=NO

 

sudo vi /etc/vsftpd/user_list 에는
cncity
라는 유저명 한줄만 있으면 됨. 

 

 

 

FTP 루트 디렉토리를 홈 디렉토리로 설정하는 chroot_local_user=YES가 이미 활성화된지 확인합니다. 이 설정은 사용자가 자신의 홈 디렉토리(지금은 /home/centos/nfs/cncity)로만 접근하도록 제한하는 역할을 합니다.

$sudo vi /etc/vsftpd/vsftpd.conf

# 로컬 사용자 홈 디렉토리를 루트 디렉토리로 설정
chroot_local_user=YES

# 일부 사용자만 chroot 제한을 적용하려면
# chroot_list_enable=YES
# chroot_list_file=/etc/vsftpd/chroot_list
Posted by yongary
,
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 10초 동안 팝업이 나타날 때까지 기다림
try:
    popup_element = WebDriverWait(self.driver, 10).until(
        EC.presence_of_element_located((By.ID, "popup_element_id"))  # 여기서 ID는 팝업의 요소 ID
    )
    # 팝업이 나타났을 때 수행할 동작
except TimeoutException:
    print("팝업이 나타나지 않았습니다.")
Posted by yongary
,

이렇게 하면 file이 업로드 되었을때, 이벤트도 받을 수 있다.

 

<dependency>
    <groupId>org.apache.ftpserver</groupId>
    <artifactId>ftpserver-core</artifactId>
    <version>1.1.1</version>
</dependency>

 

import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.FtpletContext;
import org.apache.ftpserver.ftplet.FtpletResult;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
public class EmbeddedFtpServer {

    @PostConstruct
    public void startFtpServer() {
        FtpServerFactory serverFactory = new FtpServerFactory();
        ListenerFactory factory = new ListenerFactory();
        
        // Set the port of the listener
        factory.setPort(2221);
        serverFactory.addListener("default", factory.createListener());

        // Setup user manager
        PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
        userManagerFactory.setFile(new File("users.properties"));
        userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
        serverFactory.setUserManager(userManagerFactory.createUserManager());

        // Add Ftplet to handle FTP events
        Map<String, Ftplet> ftplets = new HashMap<>();
        ftplets.put("eventListenerFtplet", new EventListenerFtplet());
        serverFactory.setFtplets(ftplets);

        // Start the server
        FtpServer server = serverFactory.createServer();
        try {
            server.start();
            System.out.println("Embedded FTP server started.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

이벤트 수신

import org.apache.ftpserver.ftplet.*;

import java.io.IOException;

public class EventListenerFtplet extends DefaultFtplet {

    @Override
    public FtpletResult onUploadStart(FtpSession session, FtpRequest request) throws FtpException, IOException {
        System.out.println("Start uploading file: " + request.getArgument());
        return FtpletResult.DEFAULT;
    }

    @Override
    public FtpletResult onUploadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
        System.out.println("Finished uploading file: " + request.getArgument());
        return FtpletResult.DEFAULT;
    }

    @Override
    public FtpletResult onConnect(FtpSession session) throws FtpException, IOException {
        System.out.println("User connected: " + session.getUser().getName());
        return FtpletResult.DEFAULT;
    }

    @Override
    public FtpletResult onDisconnect(FtpSession session) throws FtpException, IOException {
        System.out.println("User disconnected: " + session.getUser().getName());
        return FtpletResult.DEFAULT;
    }
}

 

사용자까지 설정한 예제는:

import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.SaltedPasswordEncryptor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;

@Component
public class EmbeddedFtpServer {

    @PostConstruct
    public void startFtpServer() {
        FtpServerFactory serverFactory = new FtpServerFactory();
        ListenerFactory factory = new ListenerFactory();
        
        // Set the port of the listener
        factory.setPort(2221);
        serverFactory.addListener("default", factory.createListener());

        // Setup user manager
        PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
        userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
        var userManager = userManagerFactory.createUserManager();

        // Create a new user
        BaseUser user = new BaseUser();
        user.setName("user1");
        user.setPassword("pass1");
        user.setHomeDirectory("/path/to/root/folder1");
        user.setEnabled(true);

        // Set permissions if needed (e.g., write permission)
        userManager.save(user);

        serverFactory.setUserManager(userManager);

        // Start the server
        FtpServer server = serverFactory.createServer();
        try {
            server.start();
            System.out.println("Embedded FTP server started.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Posted by yongary
,

Entity class에 @Document 어노테이션을 추가하고,

특정필드에 @Indexed를 추가하면 자동으로 인덱스가 생성된다.

만약에 잘 안되면, 원인분석을 해야겠지만,

임시로 코드로 하는 방법이있는데, 다음과 같다.

1.  잘 동작함 - MongoConfig 수정 방식

    //AUTO INDEX CREATION안되서 추가: 참고- https://github.com/spring-projects/spring-boot/issues/28478#issuecomment-954627106
    @Override
    protected boolean autoIndexCreation() {
        return true;
    }

    @Bean
    @Primary
    public MongoMappingContext mongoMappingContext(MongoCustomConversions conversions, MongoManagedTypes managedTypes) {
        MongoMappingContext mappingContext = super.mongoMappingContext(conversions, managedTypes);
        mappingContext.setAutoIndexCreation(true);
        return mappingContext;
    }



 

 

 

2. not TESTED. - post Construct방식

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

@Service
public class IndexCreatorService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @PostConstruct
    public void initIndexes() {
        IndexOperations indexOps = mongoTemplate.indexOps(ExampleEntity.class);
        indexOps.ensureIndex(new Index().on("fieldToIndex", org.springframework.data.domain.Sort.Direction.ASC));
    }
}
Posted by yongary
,

 

1. 스왑 파일 생성

먼저, 원하는 크기의 스왑 파일을 생성합니다. 여기서는 2GB 크기의 스왑 파일을 예로 들겠습니다.

bash
코드 복사
sudo fallocate -l 4G /swapfile

만약 fallocate 명령이 지원되지 않는 경우, dd 명령을 사용할 수도 있습니다:

bash
코드 복사
sudo dd if=/dev/zero of=/swapfile bs=1M count=4096

2. 스왑 파일에 적절한 권한 설정

스왑 파일에 올바른 권한을 설정하여 루트 사용자만 접근할 수 있도록 합니다.

bash
코드 복사
sudo chmod 600 /swapfile

3. 스왑 파일 형식 지정

스왑 파일을 스왑 공간으로 초기화합니다.

bash
코드 복사
sudo mkswap /swapfile

4. 스왑 파일 활성화

스왑 파일을 활성화하여 사용합니다.

bash
코드 복사
sudo swapon /swapfile

5. 스왑 공간 확인

스왑 공간이 제대로 활성화되었는지 확인합니다.

bash
코드 복사
sudo swapon --show

또는:

bash
코드 복사
free -h

6. 스왑 파일을 영구적으로 추가

재부팅 후에도 스왑 파일이 자동으로 활성화되도록 /etc/fstab 파일에 항목을 추가합니다.

bash
코드 복사
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Posted by yongary
,

 

spreadJs의 디자이너를 통해 .sjs파일을 만들어 포매팅에 이용할 수 있다.

import React, { useEffect, useRef, useState } from 'react';
import Head from 'next/head';
import GC from '@mescius/spread-sheets'; // 또는 '@grapecity/spread-sheets'
import '@mescius/spread-sheets-resources-ko';
import '@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css';

const HomePage = () => {
  const containerRef = useRef(null);
  const [spread, setSpread] = useState(null);

  useEffect(() => {
    if (containerRef.current && !spread) {
      const newSpread = new GC.Spread.Sheets.Workbook(containerRef.current, { sheetCount: 1 });
      setSpread(newSpread);
      console.log('Spread initialized:', newSpread);

      // .sjs 파일 로드
      fetch('/data/spreadsheet.sjs')
        .then(response => response.json())
        .then(json => {
          newSpread.fromJSON(json);
          console.log('Spread loaded from .sjs file:', json);
        })
        .catch(error => console.error('Error loading .sjs file:', error));
    }
  }, [containerRef, spread]);

  useEffect(() => {
    return () => {
      if (spread) {
        spread.destroy();
      }
    };
  }, [spread]);

  return (
    <div>
      <Head>
        <link rel="stylesheet" href="/scripts/gc.spread.sheets.17.0.7.css" />
      </Head>
      <h1>SpreadJS Example</h1>
      <div ref={containerRef} className="spreadContainer" style={{ top: '240px', bottom: '10px', position: 'relative', height: '500px' }}>
        {/* SpreadJS 워크북이 여기에 표시됩니다 */}
      </div>
    </div>
  );
};

export default HomePage;
Posted by yongary
,

EC2 2대(이상) 중에 리더를 선출하는 방법은 다음과 같다.

 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.Instant;
import java.util.Optional;

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public String instanceId(RestTemplate restTemplate) {
        String instanceId = restTemplate.getForObject("http://169.254.169.254/latest/meta-data/instance-id", String.class);
        System.out.println("Instance ID: " + instanceId);
        return instanceId;
    }
}

@Service
public class LeaderElectionService {
    private static final String LEADER_ID = "current_leader";

    @Autowired
    private LeaderRepository leaderRepository;

    @Autowired
    private String instanceId;

    @Scheduled(fixedRate = 30000)  // 30초마다 실행
    public void electLeader() {
        Instant now = Instant.now();
        Optional<Leader> leader = leaderRepository.findById(LEADER_ID);

        if (leader.isEmpty() || leader.get().getTimestamp().isBefore(now.minusSeconds(60))) {
            Leader newLeader = new Leader();
            newLeader.setId(LEADER_ID);
            newLeader.setInstanceId(instanceId);
            newLeader.setTimestamp(now);
            leaderRepository.save(newLeader);
            System.out.println("Instance " + instanceId + " is the leader.");
        } else if (leader.get().getInstanceId().equals(instanceId)) {
            // 자신이 리더인 경우 주기적으로 timestamp 갱신
            leader.get().setTimestamp(now);
            leaderRepository.save(leader.get());
            System.out.println("Instance " + instanceId + " is still the leader.");
        } else {
            System.out.println("Instance " + instanceId + " is not the leader.");
        }
    }
}

 

리더를 저장하는 mongoDB 컬렉션은 아래와 같이 정의한다.

 

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

import java.time.Instant;

@Document(collection = "leaderElection")
public class Leader {
    @Id
    private String id;
    private String instanceId;
    @Indexed(expireAfterSeconds = 60)
    private Instant timestamp;

    // getters and setters
}

 

 

 

그리고 main에  @EnableScheduling 이 필요하다.

@SpringBootApplication
@EnableScheduling
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

Posted by yongary
,

엑셀 매크로 관련

기타 2024. 5. 23. 15:20

엑셀에서 매크로 사용전에 체크사항: 

 

  • 보안 설정: 매크로 실행을 위해서는 엑셀의 매크로 보안 설정을 적절히 조정해야 할 수도 있습니다. 파일 > 옵션 > 보안 센터 > 보안 센터 설정 > 매크로 설정에서 매크로를 활성화할 수 있습니다.
  • 참조 설정: HTTP 요청을 처리하기 위해 Microsoft XML, v6.0 참조를 추가해야 할 수도 있습니다. VBA 편집기에서 도구 > 참조를 선택한 후, 해당 항목을 체크합니다.

개발도구 리본 보이기:
 파일->옵션->리본설정 

 

 

엑셀매크로에서 이미지 전송 예제: 이미지뷰어 필수

Sub SendImageToKakaoTalk()
    Dim imgPath As String
    Dim wsShell As Object

    ' 이미지 파일 경로 설정
    imgPath = "C:\Path\To\Your\Image.jpg"

    ' Shell 객체 생성
    Set wsShell = CreateObject("WScript.Shell")

    ' 이미지 파일 열기
    wsShell.Run Chr(34) & imgPath & Chr(34)
    Application.Wait (Now + TimeValue("0:00:02")) ' 이미지 파일이 열리기를 기다립니다.

    ' 이미지 파일을 복사합니다.
    wsShell.SendKeys "^a", True ' 전체 선택 (Ctrl + A)
    Application.Wait (Now + TimeValue("0:00:01"))
    wsShell.SendKeys "^c", True ' 복사 (Ctrl + C)
    Application.Wait (Now + TimeValue("0:00:01"))

    ' 카카오톡 창 활성화
    AppActivate "카카오톡"
    Application.Wait (Now + TimeValue("0:00:01"))

    ' 카카오톡 대화창으로 이동 (여기서는 예시로 첫 번째 채팅방)
    wsShell.SendKeys "^l", True ' 채팅방 리스트로 이동 (Ctrl + L)
    Application.Wait (Now + TimeValue("0:00:01"))
    wsShell.SendKeys "{TAB}", True ' 첫 번째 채팅방으로 이동
    Application.Wait (Now + TimeValue("0:00:01"))
    wsShell.SendKeys "~", True ' 채팅방 열기 (Enter)
    Application.Wait (Now + TimeValue("0:00:01"))

    ' 이미지 붙여넣기 및 전송
    wsShell.SendKeys "^v", True ' 붙여넣기 (Ctrl + V)
    Application.Wait (Now + TimeValue("0:00:01"))
    wsShell.SendKeys "~", True ' 전송 (Enter)

    ' 다시 엑셀로 포커스 이동
    AppActivate Application.Caption
End Sub

 

 

엑셀매크로에서 Rest API

Sub GetRequestExample()
    Dim xmlhttp As Object
    Dim url As String
    Dim response As String

    ' MSXML2.XMLHTTP 객체 생성
    Set xmlhttp = CreateObject("MSXML2.XMLHTTP")
    
    ' API URL 설정
    url = "https://api.example.com/data"

    ' GET 요청 초기화
    xmlhttp.Open "GET", url, False
    ' 요청 헤더 설정 (필요한 경우)
    xmlhttp.setRequestHeader "Content-Type", "application/json"
    
    ' 요청 보내기
    xmlhttp.send
    
    ' 응답 받기
    response = xmlhttp.responseText
    
    ' 응답 출력
    MsgBox response
    
    ' 객체 해제
    Set xmlhttp = Nothing
End Sub



Sub PostRequestExample()
    Dim xmlhttp As Object
    Dim url As String
    Dim postData As String
    Dim response As String

    ' MSXML2.XMLHTTP 객체 생성
    Set xmlhttp = CreateObject("MSXML2.XMLHTTP")
    
    ' API URL 설정
    url = "https://api.example.com/data"
    
    ' POST 데이터 설정 (JSON 형식 예시)
    postData = "{""name"":""John"",""age"":30}"

    ' POST 요청 초기화
    xmlhttp.Open "POST", url, False
    ' 요청 헤더 설정
    xmlhttp.setRequestHeader "Content-Type", "application/json"
    
    ' 요청 보내기
    xmlhttp.send postData
    
    ' 응답 받기
    response = xmlhttp.responseText
    
    ' 응답 출력
    MsgBox response
    
    ' 객체 해제
    Set xmlhttp = Nothing
End Sub

 

 

다운로드 이미지 예제

Sub DownloadFile()
    Dim http As Object
    Dim url As String
    Dim localFilePath As String
    Dim binaryStream As Object

    ' 다운로드할 파일의 URL
    url = "http://localhost:8080/download/file"

    ' 저장할 파일 경로
    localFilePath = "C:\path\to\save\downloadedfile.ext"

    ' Create XMLHTTP object
    Set http = CreateObject("MSXML2.XMLHTTP")
    http.Open "GET", url, False
    http.send

    If http.Status = 200 Then
        If Not IsNull(http.responseBody) And LenB(http.responseBody) > 0 Then
            ' Create binary stream object
            Set binaryStream = CreateObject("ADODB.Stream")
            binaryStream.Type = 1 ' Binary
            binaryStream.Open
            binaryStream.Write http.responseBody
            binaryStream.SaveToFile localFilePath, 2 ' Save binary data to file
            binaryStream.Close
            MsgBox "File downloaded successfully!"
        Else
            MsgBox "The server returned null or empty response."
        End If
    Else
        MsgBox "Failed to download file. Status: " & http.Status
    End If

    ' Clean up
    Set http = Nothing
    Set binaryStream = Nothing
End Sub
Posted by yongary
,

react lazy 로딩

React.js 2024. 5. 9. 09:19

lazy로딩은 별도로 사용할 수도 있으나 아래와 같이 라우터와 함께 사용될 때 더욱 효과적이다.

(예시 코드)

import React, { Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Home = React.lazy(() => import('./Home'));
const About = React.lazy(() => import('./About'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

export default App;

 

 

Posted by yongary
,