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
,

 

PostgreSQL의 psql은 PostgreSQL 데이터베이스와 상호작용하기 위한 커맨드 라인 툴입니다. psql 내에서는 \로 시작하는 다양한 명령어가 있으며, 이를 메타 명령이라고 부릅니다. 여기 몇 가지 유용한 예제를 소개합니다:

  1. \c [database_name]
    데이터베이스 연결을 변경합니다. 예를 들어, 다른 데이터베이스로 전환하고 싶을 때 사용합니다.
  2. \d [table_name]
    특정 테이블의 스키마를 보여줍니다. 테이블 이름을 생략하면 모든 테이블, 뷰, 인덱스 등의 목록을 보여줍니다.
     
     
  3. \dt
    데이터베이스 내의 모든 테이블을 보여줍니다.
  4. \l
    사용 가능한 모든 데이터베이스의 목록을 보여줍니다.
    \l
  5. \i [filename]
    지정된 파일에서 SQL 명령을 읽어서 실행합니다.
    \i setup.sql
  6. \s [filename]
    psql 세션에서 실행한 명령어의 기록을 파일로 저장하거나 보여줍니다.
    \s commands.log
  7. \e
    기본 텍스트 에디터에서 마지막으로 실행한 SQL 명령을 편집할 수 있습니다. 에디터는 환경변수 EDITOR로 설정됩니다.
  8. \x
    쿼리 결과를 확장된 형식으로 보여줍니다. 컬럼이 많은 경우에 유용합니다.
     
  9. \conninfo
    현재 데이터베이스 연결 정보를 보여줍니다.
     
     
  10. \q
    psql에서 나갑니다.
Posted by yongary
,



CREATE USER otheruser WITH PASSWORD 'password';


GRANT INSERT, UPDATE, DELETE ON othertable TO otheruser;

이렇게만 하면, 기존 사용자는 그대로 crud가 가능한 상태에서,
새로운 특정사용자에게 othertable 특정테이블만  권한을 주게된다. 


(확인)

SELECT grantee, privilege_type
FROM information_schema.table_privileges
WHERE table_name='mytable';

 

 

///실 사용예제.

$ psql -h dbURL -U postgres -d postgres
> \c testdb
> CREATE USER otheruser WITH PASSWORD 'test';
> GRANT INSERT, UPDATE, DELETE, SELECT ON monthlydata TO otheruser;

> \c testdb otheruser
> SELECT grantee, privilege_type
FROM information_schema.table_privileges
WHERE table_name='monthlydata'

Posted by yongary
,

. 특정 컬렉션에 대한 접근 제한 설정

MongoDB에서는 특정 컬렉션에 직접적으로 접근을 제한하는 내장 기능을 제공하지 않습니다. 하지만, 역할 기반의 접근 제어(Role-Based Access Control, RBAC)를 사용하여 사용자 정의 역할을 생성하고, 이 역할을 통해 특정 컬렉션에 대한 접근을 제어할 수 있습니다.

먼저, mydatabase 데이터베이스에서 사용자 정의 역할을 생성합니다.

 

use mydatabase
db.createRole({
  role: "collectionReadWrite",
  privileges: [
    { resource: { db: "mydatabase", collection: "mycollection" }, actions: ["find", "update", "insert", "remove"] }
  ],
  roles: []
})

 

그런 다음, 이 역할을 사용자에게 할당합니다

 

db.updateUser("myUser", {
  roles: [
    { role: "collectionReadWrite", db: "mydatabase" }
  ]
})

 

 

======== 사전에 mongoDB에 사용자가 설정되지 않았다면 다음스텝 필요==========

1. MongoDB 인증 활성화

먼저 MongoDB 서버에서 인증을 활성화해야 합니다. 이는 위에서 설명한

 

mongod.conf 파일을 편집하여 security.authorization 옵션을 enabled로 설정함으로써 이루어집니다. 서버 재시작 후 인증이 필요하게 됩니다.

 

security:
  authorization: enabled

 

2. 관리자 생성

$ mongo

> use admin
> db.createUser({
  user: "admin",
  pwd: "password",
  roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
})

 

==> 모든 db에 비번에 필요할듯함. 

 

 

2.1 위에서 설명한 사용자 생성.

3. Spring Boot 애플리케이션 설정 변경

기존에 인증 없이 연결하던 Spring Boot 애플리케이션의 MongoDB 연결 설정을 업데이트하여 사용자 이름과 비밀번호를 포함하도록 해야 합니다. application.properties 또는 application.yml 파일에서 MongoDB 연결 URI를 다음과 같이 수정합니다:

 

# application.properties
spring.data.mongodb.uri=mongodb://username:password@host:port/database

Posted by yongary
,

동영상 녹화

Mac 2024. 4. 29. 17:39

 

1. QuickTime Player를 수행한다.  혹시 파일선택 팝업이 뜨면 취소를 누른다.

 

2. C-C-N 키를 누르면  우측에  "영역선택/전체화면" 을 선택해서 "기록"을 누르면 시작된다.
  (Command-control-N)

3. C-C-Esc 키를 누르면 녹화가 취소된다. 
(Command-control-ESC )

Posted by yongary
,

 

mongoDB의 CSFLE라고 불리는 필드암호화는 mongoDB 4.2이상에서 지원된다.

(단, mongoDB enterprise에서만 지원된다)

 

스텝별로 살펴보면 다음과 같다.

 

1. KMS 서비스를 통해 key 생성. (아래는 AWS KMS이용 예제이지만,  azure의 keyVault나 Google Cloud KMS도 가능)

 

AWS Management Console에 로그인하여 KMS 서비스로 이동합니다.
새로운 키 생성을 선택하고, 키 유형으로 "대칭"을 선택합니다.
키에 이름을 부여하고, 필요한 권한을 설정합니다.
IAM 정책 설정:

키 사용 권한을 가진 IAM 사용자 또는 역할을 생성합니다.
생성된 KMS 키에 대한 액세스 권한을 해당 IAM 사용자 또는 역할에 부여합니다.

 

2. MongoDB 설정에 ClientEncryptions  설정.

@Bean
public MongoClient mongoClient() {
    Map<String, Object> awsKmsProvider = Map.of(
        "accessKeyId", "<AWS_ACCESS_KEY_ID>",
        "secretAccessKey", "<AWS_SECRET_ACCESS_KEY>"
    );

    Map<String, Map<String, Object>> kmsProviders = Map.of("aws", awsKmsProvider);

    AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder()
            .keyVaultNamespace("admin.dataKeys")
            .kmsProviders(kmsProviders)
            .build();

    MongoClientSettings settings = MongoClientSettings.builder()
            .applyConnectionString(new ConnectionString(uri))
            .autoEncryptionSettings(autoEncryptionSettings)
            .build();
    return MongoClients.create(settings);
}

@Bean
public MongoTemplate mongoTemplate() throws Exception {
    return new MongoTemplate(mongoClient(), dbName);
}

 

3. entity class의 필드에 @Encrypted 적용 

 

@Document
public class User {
    @Encrypted
    private String sensitiveData;
    
    private String generalData;
}
Posted by yongary
,