[헤놀로지] duckdns 인증서 발급

헤놀로지/헤놀로지|2025. 1. 29. 04:15

저처럼 삽질을 안하길 바래서 글을 작성해봅니다...

먼저 제 환경은 7.2.2 헤놀로지입니다!

 

https://www.duckdns.org/

 

Duck DNS

Duck DNS free dynamic DNS hosted on AWS news: login with Reddit is no more - legal request support us: become a Patreon

www.duckdns.org

위 duckdns에서 *.duckdns.org 를 발급받은 후

 

 

헤놀로지 → 제어판 → 보안 → 인증서 로 이동
새 인증서 추가

- Let's Encrypt에서 인증서 받기
-기본 인증서로 설정

duckdns 및 이메일 입력

 

이렇게 후 완료 를 눌렀음 에도 아래와 같이 에러가 발생

 

1. 헤놀로지 → 제어판 → 보안   방화벽 활성화 해지 → 재부팅 → 다시 시도

2. 방화벽 또는 공유기의 `국가별 접속 제한`이 걸려있다면 해제

 

npm, container manager, ssh 등 수많은 글을 참조하였지만 전부 되지 않아

포기하려던 참에 공유기의 `국가 차단`을 잠시 해제 후 해결하였습니다 ㅠㅠ...

댓글()

[JS] 클로저

STUDY/JavaScript|2025. 1. 12. 14:28
클로저(Closer)

: 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 종료된 외부 함수의 변수를 참조할 수 있는 것

 

const x = 1;

function outer()
{
    const x = 10;
    const inner = function() { console.log(x); };
    return inner;
}

const innerFunc = outer();
innerFunc();
  • outer 종료 시 inner를 반환하고 종료된다.
  • 하지만 마지막 줄 innerFunc() 에서는 반환된 x의 값이 출력된다.
  • 반환된 중첩 함수 inner가 클로저 로써 외부 함수의 x를 참조하여 사용된다.
    -> 자바스크립트의 모든 함수는 자신의 상위 스코프를 기억하고 있기에 가능
    -> 그러하여 outer의 실행 컨텍스트는 종료되어 삭제되었지만 렉시컬 환경까지 제거되지 않아
    inner에서 outer 참조가 가능

 

클로저의 활용

: 상태를 안전하게 변경(은닉)하고 특정 함수에게만 상태 변경을 허용시킬 수 있음

 

const counter = (function () {
    let num = 0;

    return {
        increase() {
            return ++num;
        },
        decrease() {
            return 0 < num ? --num : 0;
        }
    };
}());

console.log(counter.increase()); //1
console.log(counter.increase()); //2
console.log(counter.increase()); //3

 

MSN 공식 문서

https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures

'STUDY > JavaScript' 카테고리의 다른 글

[JS] 실행 컨텍스트  (0) 2025.01.12
[JS] VSCode 확장프로그램  (0) 2025.01.12

댓글()

[JS] 실행 컨텍스트

STUDY/JavaScript|2025. 1. 12. 13:49
실행 컨텍스트는 자바스크립트의 동작 원리를 담고 있는 핵심

: 자바스크립트가 스코프를 기반으로 식별자와 바인딩 값을 관리하는 방식 및 호이스팅, 클로저 등의 동작 방식 이해가 가능하다.

 

  • 소스코드의 타입
전역 코드(global code) 전역에 존재하는 코드. 전역에 정의된 함수, 클래스 등의 내부 코드는 포함되지 않음
함수 코드(function code) 함수 내부에 존재하는 코드. 함수 내부에 중첩된 내부 코드는 포함되지 않음
eval 코드(eval code) 빌트인 전역 함수인 eval 함수(strict mode 스코프)에 인수로 전달되어 실행되는 코드
모듈 코드(module code) 모듈 내부에 존재하는 소스코드. 모듈 내부의 함수, 클래스 등의 내부 코드는 포함되지 않음

 

  • 실행 컨텍스트의 실행 순서(스택)

1. 전역 코드 평가

2. 전역 코드 실행

3. 함수 코드 평가

4. 함수 코드 실행

const x = 1;

function foo()
{
	const y = 2;
    console.log('foo');
    
    function bar()
    {
    	const z = 3;
        console.log('bar');
    }
    bar();
}

foo();

 

위 코드를 기준으로 실행 컨텍스트 스택은 다음과 같다.

 

1. 전역 실행 컨텍스트

: x, foo() 등록 및 foo 호출

 

2. 전역 실행 컨텍스트 -> foo 함수 실행 컨텍스트

: foo 함수 실행 및 전역 실행 중지

-> 지역변수 y와 중첩함수 bar()가 foo() 함수 실행 컨텍스트에 등록

-> y값 할당, console.log 호출 후 bar() 호출

 

3. 전역 실행 컨텍스트 -> foo 함수 실행 컨텍스트 -> bar 함수 실행 컨텍스트

: bar 호출 및 foo 함수 실행 중지

-> z가 bar 함수 실행 컨텍스트에 등록

-> z 할당, console.log 호출

 

4. 전역 실행 컨텍스트 -> foo 함수 실행 컨텍스트

: bar() 종료 . 후다시 foo()로 제어권 이동

 

5. 전역 실행 컨텍스트

: foo() 종료, 전역 실행 컨텍스트로 제어권 이동

 

6. end

'STUDY > JavaScript' 카테고리의 다른 글

[JS] 클로저  (0) 2025.01.12
[JS] VSCode 확장프로그램  (0) 2025.01.12

댓글()

[JS] VSCode 확장프로그램

STUDY/JavaScript|2025. 1. 12. 13:26

사용관련


터미널 여는 법

Control + `(₩)

Js Build (확장 프로그램 Code Runner 필요)

Window: Control + Alt + N

Mac: Control + Option + N


확장 프로그램

Code Runner

: 자바 스크립트 뿐만이 아니라 여러 프로그래밍 언어를 실행 할 수 있게 도와줌

VSCode Setting에서 'Save File Before Run' 클릭하여 빌드 시 자동 저장 설정가능

 

Live Server

: Web API가 포함된 자바스크립트 실행 시 브라우저에서 실행이 필요함
빌드 시 브라우저에 자동으로 반영 및 실행이 되어 편리함

 

Auto Rename Tag

태그 작성 시 자동으로 닫힘 태그 작성

 

Import Cost

import 하려는 모듈의 크기를 알아볼 수 있는 익스텐션으로

우측 용량이 표기됨

'STUDY > JavaScript' 카테고리의 다른 글

[JS] 클로저  (0) 2025.01.12
[JS] 실행 컨텍스트  (0) 2025.01.12

댓글()

[C++]Single LinkedList 구현

STUDY/알고리즘|2024. 7. 14. 23:08
LinkedList란
단어 그대로 다음 데이터의 위치가 연결되어 선형으로 저장하는 방식이다.
각 요소는 노드(Node)라고 불르며 노드는 데이터와 다음 위치를 가르키는 포인터 로 구성되어 있다.

 

 

연결 리스트는 3종류가 존재한다.

  • 단일 연결 리스트 (Singly Linked List)
  • 이중 연결 리스트 (Doubly Linked List)
  • 원형 연결 리스트 (Circular Linked List)

이번 구현은 Singly Linked List로 다음 위치만 가리키는 단일 연결 리스트 이다.

먼저 헤더에 Node 구조체와 각 리스트를 관리할 함수들을 구현했다.

#pragma once
#include <iostream>

using namespace std;

struct Node
{
    int data_;
    Node* nextNode_;
};

먼저 노드는 데이터를 담고 있는 data_와 다음 주소를 가리키는 Node* 를 담고 있다.

 

헤더의 구현부는 다음과 같으며 제일 앞 노드를 항상 가리키는 head_를 선언하여

리스트의 첫노드를 항상 가리키게 만들어준다.

class LinkedList
{
private:
    Node* head_;

public:
    LinkedList() { head_ = nullptr; }

    void AddFrontNode(int data);
    void AddLastNode(int data);
    void InsertNode(int num, int data);
    void DeleteNode(int num);

    Node* GetHead() { return head_; }
    void Print();
};

 

다음은 노드를 제일 앞에 추가하는 코드이다.

void LinkedList::AddFrontNode(int data)
{
    Node* tempNode = new Node;

    tempNode->data_ = data;
    tempNode->nextNode_ = head_;
    head_ = tempNode;
}
  • 새로운 노드를 생성
  • 새로운 노드에 데이터를 삽입
  • 제일 앞에 추가하는 것이기 때문에 새로운 노드가 가리키는 다음 노드를 현재 Head로 넣어준다
  • head를 제일 앞 노드를 가리키게 변경

전체 구현부는 아래에 추가

더보기
#pragma once
#include <iostream>

using namespace std;

struct Node
{
    int data_;
    Node* nextNode_;
};

class LinkedList
{
private:
    Node* head_;

public:
    LinkedList() { head_ = nullptr; }

    void AddFrontNode(int data);
    void AddLastNode(int data);
    void InsertNode(int num, int data);
    void DeleteNode(int num);

    Node* GetHead() { return head_; }
    void Print();
};

void LinkedList::AddFrontNode(int data)
{
    Node* tempNode = new Node;

    tempNode->data_ = data;
    tempNode->nextNode_ = head_;
    head_ = tempNode;
}

void LinkedList::AddLastNode(int data)
{
    Node* tempNode = new Node;

    tempNode->data_ = data;
    tempNode->nextNode_ = nullptr;

    if (head_ == nullptr)
    {
        head_ = tempNode;
    }
    else
    {
        Node* temp = head_;
        while (temp->nextNode_) {
            temp = temp->nextNode_;
        }
        temp->nextNode_ = tempNode;
    }
}

void LinkedList::InsertNode(int num, int data)
{
    if (num == 0)
    {
        AddFrontNode(data);
    }
    else
    {
        Node* newNode = new Node;
        newNode->data_ = data;

        Node* targetNode = head_;
        for (int i = 0; i < num - 1 && targetNode; ++i)
        {
            targetNode = targetNode->nextNode_;
        }

        if (targetNode == nullptr)
        {
            cout << "Out Of Range" << endl;
            delete targetNode;
        }
        else
        {
            newNode->nextNode_ = targetNode->nextNode_;
            targetNode->nextNode_ = newNode;
        }
    }
}

void LinkedList::DeleteNode(int num)
{
    if (head_ == nullptr)
    {
        cout << "No Header" << endl;
        return;
    }

    if (num == 0)
    {
        Node* currentNode = head_;
        head_ = head_->nextNode_;
        delete currentNode;
    }
    else
    {
        Node* currentNode = head_;

        for (int i = 0; i < num - 1 && currentNode; ++i)
        {
            currentNode = currentNode->nextNode_;
        }

        if (currentNode == NULL)
        {
            cout << "Out of Range" << endl;
        }
        else
        {
            Node* temp = currentNode->nextNode_;

            if (temp)
            {
                currentNode->nextNode_ = currentNode->nextNode_->nextNode_;
                delete temp;
            }
            else
            {
                cout << "No Header" << endl;
                return;
            }
        }
    }
}

void LinkedList::Print()
{
    Node* temp = head_;
    while (temp) {
        cout << temp->data_ << " -> ";
        temp = temp->nextNode_;
    }
    cout << "null" << endl;
}

 

추가로 테스트를 진행한 C++코드도 첨부하였다.

더보기
#include <iostream>
#include "LinkedList.h"
using namespace std;

int main()
{
	LinkedList* list = new LinkedList();

	int input = 0;
	while (0 <= input)
	{
		cout << "==================================================" << endl;
		list->Print();
		cout << "==================================================" << endl;
		cout << "1.맨 앞 추가, 2.맨 뒤 추가, 3.삽입, 4.삭제, 5.종료, 0.화면 클리어" << endl;
		cin >> input;

		switch (input)
		{
		default:
		{
			cout << "잘못입력했습니다." << endl;
		}
		break;

		case 0:
		{
			std::system("cls");
		}
		break;

		case 1:
		{
			cout << "추가할 값을 입력해주세요." << endl;
			int AddData = 0;
			cin >> AddData;

			list->AddFrontNode(AddData);
			cout << "추가 완료되었습니다." << endl;
		}

		break;

		case 2:
		{
			cout << "추가할 값을 입력해주세요." << endl;
			int AddData = 0;
			cin >> AddData;

			list->AddLastNode(AddData);
			cout << "추가 완료되었습니다." << endl;
		}

		break;

		case 3:
		{
			cout << "추가할 순서 및 데이터를 입력해주세요." << endl;
			int insertNum = 0;
			int data = 0;
			cin >> insertNum >> data;

			list->InsertNode(insertNum, data);
		}

		break;

		case 4:
		{
			cout << "삭제할 번호를 입력해주세요." << endl;
			int deleteNum = 0;
			cin >> deleteNum;

			list->DeleteNode(deleteNum);
		}
		break;

		case 5:
		{
			cout << "프로그램을 종료합니다." << endl;
			input = -1;
		}
		break;
		cout << "==================================================" << endl;
		}
	}

	delete list;
}

댓글()

특정 키워드 모음

STUDY/C#|2024. 7. 7. 23:22
  • Abstarct

추상 클래스나 추상 메서드를 정의할 때 사용되며 구현이 없는 메서드로, 이를 상속하는 클래스에서 부족한 구현을 반드시 수행해야한다. 추상 멤버 또한 반드시 구현되어야 하며 직접 인스턴스화될 수 없다.

  • Virtual

virtual 키워드는 메서드, 속성, 인덱서를 재정의할 수 있다.

virtual로 선언된 멤버는 파생 클래스에서 override 키워드를 사용하여 필요에 따라 재정의 할 수 있다.

  • Record

record 키워드는 C# 9.0에서 도입된 새로운 타입으로, 불변 객체(내부를 변경할 수 없는)를 말한다.

기본적으로 불변 객체를 생성하며, with 키워드를 사용하여 일부 속성만 변경된 새 인스턴스를 쉽게 만들 수 있다.

주로 데이터 복사와 비교가 많이 이루어진다.

Person person3 = person1 with { LastName = "Smith" };
Console.WriteLine(person3);

// Output: Person { FirstName = John, LastName = Smith }
  • Event

event 키워드는 이벤트를 선언할 때 사용되며 특정 작업이 발생할 때 알림을 받기 위한 메커니즘으로, 주로 델리게이트와 함께 사용된다.

delegate void EventHandler(string message);

class
{
	public event EventHandler SomethingHappened;
------------------------------------------------

'STUDY > C#' 카테고리의 다른 글

대리자(Delegate)  (0) 2024.07.07
메소드(Method)  (0) 2024.07.07
Null 조건부, 병합 연산자  (0) 2023.02.20
C# Nullable Type  (0) 2023.02.20
c# winform 드래그앤드롭  (0) 2022.07.25

댓글()

대리자(Delegate)

STUDY/C#|2024. 7. 7. 21:40
콜백을 맡아 실행하는 일을 담당
c++의 함수 포인터와 유사

 

한정자 delegate 반환_형식 대리자_이름( 매개변수_목록 );

 

예시

delegate int MyDelegate( int a, int b);

 

대리자는 왜 사용하는 것일까?

대리자를 사용하는 것은 매개변수로 함수를 넘기거나 '대리자 체인'을 통하여 일련의 과정을 연달아 호출할 수 있다.

 

대리자 체인은 여러 개의 콜백을 차례로 호출이 필요할 때 사용할 수 있다.

delegate void dMethodChain(string str);

void chain1(string str) { Console.WriteLine("1"); }
void chain2(string str) { Console.WriteLine("2"); }
void chain3(string str) { Console.WriteLine("3"); }

---------------------------------------------------

dMethodChain chain = new dMethodChain(chain1);
chain += new dMethodChain(chain2);
chain += new dMethodChain(chain3);

결과는 1, 2, 3 전부 출력이 된다.

 

대리자에 += 연산자를 통하여 추가가 되지만 -= 연산자를 통하여 체인을 끊을 수 있다.

이와 관련해서는 Delegate.Combine, Delegate.Remove 또한 존재한다.

 

대리자에는 익명 메서드와 연결하면 더욱 편리하게 사용이 가능하다.

Calc = delegate( int a, int b ) { return a + b };

Console.WriteLine( $" 1 + 2 = {Calc(1, 2)}");

 

'STUDY > C#' 카테고리의 다른 글

특정 키워드 모음  (0) 2024.07.07
메소드(Method)  (0) 2024.07.07
Null 조건부, 병합 연산자  (0) 2023.02.20
C# Nullable Type  (0) 2023.02.20
c# winform 드래그앤드롭  (0) 2022.07.25

댓글()

메소드(Method)

STUDY/C#|2024. 7. 7. 19:20
메소드(Method)란 객체지향 프로그래밍 언어에서 사용하는 용어
언어에 따라 함수(Function), 프로시저(Procedure), 서브루틴(Subroutine), 서브 프로그램(Subprogram)으로 불림

 

메소드는 클래스 안에 선언되며 여러 응용이 가능하다.

(한정자) (반환_형식) (메소드_이름) (매개변수_목록)
{
  //코드
}

 

한정자에는 public, internal, protected, private, internal 등이 존재하며 각 한정자마다 접근이 제한된다.

접근 한정자 설명
public 클래스 내/외부 접근 가능
protected 클래스 외부 접근 X, 파생 클래스(상속) 접근 가능
private 클래스 내부 O, 외부 X
internal 같은 어셈블리 코드에서만 public 접근 가능, 쉽게 말해 같은 프로젝트에서 접근 O
protected internal 같은 어셈블리에 코드 수준에서 protected 수준으로 접근 가능, 다른 프로젝트 private
private protected 같은 어셈블리에 있는 ㅅ클래스에서 상속받은 클래스 내부에서만 접근 O

 

반환형식에는 함수가 끝나고 반환하고자 하는 타입을 작성하며 반드시 return을 사용하여 해당 한정자의 타입으로 결과를 출력해야한다.

 

하나의 메소드 안에서 같은 메소드를 호출하는 것을 '재귀 호출'이라 부르며 코드를 줄일 수 있으나 무한 반복이 될 수 있어 주의해서 사용해야 한다.

private int Fibonacci(int n)
{
    if (n < 2)
    	reutrn n;
    else
    	return Fibonacci(n - 1) + Fibonacci(n - 2);
}

 

매개변수는 기본적으로 '값에 의한 전달(pass by value)가 이루어진다.

그러므로 매개변수로 값을 전달한 것은 메소드 안에서 어떠한 형태로든 값이 변경되어도 메소드 외부에는 영향을 주지 않는다. 하지만 매개변수를 참조(C++ &, C# ref, out) 형태로 전달 시에는 메소드 내부에서 변경된 값이 '참조의 의한 전달(pass by reference)가 이루어지며 메소드에 넘겨진 원본 변수에 영향을 끼치게 된다.

 

메소드의 이름은 같으나 매개변수를 다르게 선언하는 것을 메소드 오버로딩 이라 한다. 메소드 오버로딩은 컴파일 타임에 이루어지므로 성능 저하의 걱정은 하지 않아도 된다.

 

매개변수에 여러 변수를 넣고자 할때는 param 키워드를 사용하면 된다.

public int Sum(params int[] args)
{
    int sum = 0;
    for (int i = 0; i < args.Length; ++i)
    {
    	sum +- args[i];
    }
    
    return sum;
}

'메소드 오버로딩'을 같은 변수로 해야하는 상황이 있다면 param 키워드를 사용하여 짜는 것이 효율적일 수 있다.

 

만약 매개변수에 인자가 있을 때도 있고 없을 때도 있다면 선택적 인수를 사용하는 방법이 있다.

void Sum (int a, int b, int c = 0)
{
    sum += a + b + c;
}

다음과 같이 매개변수에 값을 미리 지정하여 사용이 가능하다.

 

'STUDY > C#' 카테고리의 다른 글

특정 키워드 모음  (0) 2024.07.07
대리자(Delegate)  (0) 2024.07.07
Null 조건부, 병합 연산자  (0) 2023.02.20
C# Nullable Type  (0) 2023.02.20
c# winform 드래그앤드롭  (0) 2022.07.25

댓글()