728x90
반응형

문제

https://www.acmicpc.net/problem/1920

 

1920번: 수 찾기

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들

www.acmicpc.net

 


 

접근 방식

  • 정렬 후 이진탐색 구현 매개변수로 정렬된 벡터 전달 -> 10% 시간 초과
  • 입출력 속도 개선 -> 10% 시간 초과
  • 정렬된 벡터를 전역 변수로 접근(매개변수로 전달하는 과정에서 시간이 많이 걸릴 수 있다고 함) -> 통과

 

코드

#include <iostream>
#include <vector>
#include <algorithm> 
#include <cmath> 

using namespace std;

vector<int> func_1920_An;

int func_1920_isExist(int find_value) {
    int res = 0;
    int start_index = 0, end_index = func_1920_An.size();
    int index = (int)floor((start_index + end_index) / 2);

    while(start_index < end_index) {
        if (find_value == func_1920_An.at(index)) {
            res = 1;
            break;
        }

        if (start_index == index){
            break;
        }

        if (find_value > func_1920_An.at(index)) {
            start_index = index;
        }

        if (find_value < func_1920_An.at(index)) {
            end_index = index;
        }

        index = (int)floor((start_index + end_index) / 2);
    }

    return res;
}


int main() {
    int n, m, tmp;
    vector<int> Am;

    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> tmp;
        func_1920_An.push_back(tmp);
    }

    sort(func_1920_An.begin(), func_1920_An.end());

    cin >> m;
    for (int i = 0; i < m; i++) {
        cin >> tmp;
        Am.push_back(tmp);
    }

    for (auto m_tmp : Am) {
        cout << func_1920_isExist(m_tmp) << "\n";
    }
    
    return 0;
}

 

결과

 

728x90
반응형
728x90
반응형

문제

https://www.acmicpc.net/problem/1463

 

1463번: 1로 만들기

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

www.acmicpc.net

 


 

접근 방식

  • 다이나믹 프로그래밍 분류에 있는 문제이므로 점화식을 찾아 DP로 구현
1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
2. X가 2로 나누어 떨어지면, 2로 나눈다.
3. 1을 뺀다.

 

위 규칙을 기반으로 점화식을 찾아보자.

가능한 연산과 규칙을 나열해보면 최종적으로 dp[n] = 1 + min(dp[n-1], dp[n/2], dp[n/3]) 이라는 점화식을 찾을 수 있다. 점화식의 의미는 현재 수에 대한 연산 횟수 증가(1) + 가능한 이전 연산 중 최소 값 ( min(...) ) 이다.

 


 

코드

#include <iostream>
#include <cstring>

using namespace std;

int main() {
    int min, num;

    cin >> num;

    int* dp = new int[num+2];
    memset(dp, 0, sizeof(int) * (num+2));
    
    for (int i = 2; i <= num; i++) {
        dp[i]++;
        min = 0;

        if (min > dp[i - 1] || min == 0)
            min = dp[i - 1];

        if (i % 2 == 0) {
            if (min > dp[i / 2])
                min = dp[i / 2];
        }

        if (i % 3 == 0) {
            if (min > dp[i / 3])
                min = dp[i / 3];
        }

        dp[i] += min;
    }

    cout << dp[num] << "\n";
    
    return 0;
}

 

결과

 

 

728x90
반응형
728x90
반응형

문제

https://www.acmicpc.net/problem/10026

 

10026번: 적록색약

적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다. 크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록)

www.acmicpc.net

 


 

접근 방식

  • 기본 Map과 색약 Map을 만들어 BFS로 구역을 나눠줌
  • 틀렸습니다. 코드와 정답 코드 차이
// 틀린 코드
if (map_visit[i][j] == 0) {
	q.push({i, j});
    visit_value++;
}

// 정답 코드
if (map_visit[i][j] == 0) {
	q.push({i, j});
	map_visit[i][j] = ++visit_value;
}

 

코드

#include <iostream>
#include <cstring>
#include <utility> 
#include <queue> 

using namespace std;

void func_10026_bfs(queue<pair<int, int>> q, char **_map, int **visited, int visit_value, int n) {
    pair<int, int> tmp_coord;
    int _x, _y;
    char tmp_color;
    int direct[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };

    while (!q.empty()) {
        tmp_coord = q.front();
        tmp_color = _map[tmp_coord.first][tmp_coord.second];
        q.pop();

        for (int i = 0; i < 4; i++) {
            _x = tmp_coord.first + direct[i][0];
            _y = tmp_coord.second + direct[i][1];

            if (_x >= n || _x < 0)
                continue;
            
            if (_y >= n || _y < 0)
                continue;

            if (visited[_x][_y] != 0)
                continue;

            if (_map[_x][_y] != tmp_color)
                continue;

            visited[_x][_y] = visit_value;
            q.push({_x, _y});
        }
    }
}

int main() {
    queue<pair<int, int>> q;
    int visit_value, map_max, map_rg_max;
    
    int n;
    cin >> n;

    char** map_origin = new char* [n];
    char** map_rg = new char* [n];
    int** map_visit = new int* [n];
    int** map_rg_visit = new int* [n];

    for (int i = 0; i < n; i++) {
        map_origin[i] = new char[n];
        map_rg[i] = new char[n];
        map_visit[i] = new int[n];
        map_rg_visit[i] = new int[n];

        memset(map_visit[i], 0, sizeof(int) * n);
        memset(map_rg_visit[i], 0, sizeof(int) * n);
    }

    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++) {
            cin >> map_origin[i][j];
            
            if (map_origin[i][j] == 'R')
                map_rg[i][j] = 'G';
            else
                map_rg[i][j] = map_origin[i][j];
        }
    }

    visit_value = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (map_visit[i][j] == 0) {
                q.push({i, j});
                map_visit[i][j] = ++visit_value;
            }

            func_10026_bfs(q, map_origin, map_visit, visit_value, n);
        }
    }


    while (!q.empty()) {
        q.pop();
    }

    visit_value = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (map_rg_visit[i][j] == 0) {
                q.push({ i, j });
                map_rg_visit[i][j] = ++visit_value;
            }

            func_10026_bfs(q, map_rg, map_rg_visit, visit_value, n);
        }
    }

    map_max = 0;
    map_rg_max = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (map_max < map_visit[i][j]) {
                map_max = map_visit[i][j];
            }

            if (map_rg_max < map_rg_visit[i][j]) {
                map_rg_max = map_rg_visit[i][j];
            }
        }
    }
    
    cout << map_max << " " << map_rg_max << "\n";
    
    return 0;
}

 

결과

728x90
반응형
728x90
반응형

글 목적

아래 내용은 docker 설치와 이미지를 run한 이후 내부 컨테이너에서 apt-get update하는 부분부터 에러가 발생하여 해결하기 위해 삽질한 과정이다.

환경을 설치하고 Django web 페이지를 띄울 때까지 오류 상황들을 순서대로 적은 글이고 중간에 돌아가는 과정이 있기 때문에 빠른 결론을 원하면 아래 apt-get update 성공 부분부터 읽으면 될 듯 하다.

만약 이 글과 비슷한 상황이라면 순서대로 읽는 것 보단 필요한 부분만 찾아서 시도해보길 바란다. 

 

도커 이미지는 아래 명령어로 run하였고, 컨테이너 이름은 test이다.

$ sudo docker run -it --name=test ubuntu:20.04 /bin/bash

 

docker 설치나 사용에 관한 내용은 아래 링크 참조.

https://hwan001.tistory.com/180

 

[Docker] Ubuntu에 Docker 설치하기

Docker ? 리눅스 컨테이너화 기술로 사용자가 리눅스 컨테이너를 만들고 사용할 수 있도록 지원한다. 도커는 가상화 기술이 아닌 격리 기술이지만 가상 머신과 비슷한 느낌으로 사용한다. 컨테이

hwan001.co.kr


 

apt-get update 에러

 Ubuntu:20.04 컨테이너를 실행하고 가장 먼저 apt-get update 명령어를 사용했지만, Err 메시지가 뜨면서 모든 저장소에 연결되지 않았다. 또한 ip, vi, ping, route 등의 기본 명령어들도 제공되지 않아 원인 파악도 제한된다.

검색해보니 docker의 보안으로 인해 최초에 해당 기능들이 제공되지 않기 때문에 만약 필요하면 apt-get install로 각각을 설치해서 사용하라고 하는데, 문제는 apt-get 저장소 연결 자체가 안되는 상황이다. 

 

원인을 검색해봤더니 DNS 연결 문제로 저장소 URL을 찾을 수 없어 발생하는 에러기 때문에 해당 주소를 잘 변경해주면 연결이 된다고 한다. DNS 주소를 수정하는 방법은 아래 링크를 참고했다.

https://askubuntu.com/questions/1167080/unable-to-update-ubuntu-docker-container-using-apt-get-update

 

unable to update ubuntu Docker container using apt-get update

when I run ubuntu as Docker container and when I run apt-get update command it gives error and fails to update the repos. Here is what error I'm getting : root@df167e514b29:/# sudo bash: sudo: c...

askubuntu.com

검색을 통해 /etc/resolv.conf 등 필요한 파일들을 수정해줬고, DNS (8.8.8.8) 주소도 잘 설정되어 있다.

하지만 여전히 update가 안되었기 때문에 결국 필요한 패키지들을 수동으로 설치하기로 했다.


 

apt-get download

보통 필요한 패키지들은 apt-get install로 시스템에 바로 설치하지만 현재는 원인을 알 수 없는 이유로 저장소 연결이 제한된다. 패키지의 수동 설치를 위해서 먼저 docker 컨테이너를 빠져나가 apt-get이 잘 작동되는 os에서 필요한 패키지들을 다운로드 받는다.

 

$ sudo apt-get download vim net-tools iproute2 iputil-ping

 

apt-get download 명령어는 현재 디렉토리에 .deb 형태로 필요한 패키지를 다운로드 받는다.

aaa라는 임시 폴더를 만들어 내부에 필요한 deb 들을 설치했다.

 

이제 이 파일들을 도커 내부의 ubuntu:20.04로 전달하여 수동으로 설치하면 된다.


 

docker cp

도커는 도커 외부와 내부 컨테이너 간의 파일 공유가 가능하며 docker cp 명령어로 해당 기능을 제공한다.

위에서 내려받은 deb 파일을 ubuntu:20.04 컨테이너에 넣어준다.

$ sudo docker cp ../aaa/ test:/aaa/

잘 전달되었다.

이제 전달된 deb를 설치해주자.


 

apt install ./

apt install 명령어를 사용하면 패키지를 설치할 수 있다.

여기서 주의할 점이 있는데, install 뒤에 패키지 명을 그냥 입력하면 저장소에서 해당 패키지를 찾기 때문에

./을 붙여 현재 디렉토리 내부의 파일이라고 명시해 주어야 한다.

 

하나씩 설치해보겠다.

$ apt install ./net-tools_1.60+git20180626.aebd88e-1ubuntu1_amd64.deb

net-tools

 

$ apt install ./iputils-ping_3%3a20190709-3_amd64.deb

iputils-ping 에러

 

iputil-ping 패키지를 설치하던 중 의존성과 관련된 에러가 발생했다.

libcap2 와 libcap2-bin이 설치되지 않아 발생한 에러이다.

docker 외부에서 다운받은 뒤 같이 설치해주자.

$ apt-get download libcap2 libcap2-bin

 

설치할땐 libcap2-bin의 의존성 때문에 libcap2를 먼저 설치해줘야 한다. 

 

iputils-ping을 설치해보자.

 

드디어 iputils-ping의 설치가 끝났다.

다른 패키지들도 비슷한 방식으로 설치하면 되지만 사실 중요한건 패키지 설치가 아니라 환경 구축이다.

더 이상 설치하지 말고 ping을 사용해서 저장소와 연결 상태를 먼저 확인해보자.


 

Ping

DNS로 먼저 날려봤지만 당연하다는 듯 패킷이 나가지 않는다.

 

게이트 웨이로도 연결이 안된다..

 

여기서 추론 가능한 연결 실패 원인은 크게 2가지인 것 같다.

방화벽에서 패킷이 drop 당하거나, 이중 NAT로 인한 route 문제.

 

방화벽은 없으니 홈 서버를 구성하면서 뭔가 문제가 생긴 듯 하다.


 

docker network

좀 더 찾아보니 도커는 docker network 명령어로 네트워크 생성, 설정 등의 작업을 지원한다.

원래 해당 명령어는 컨테이너들 간의 통신을 가상 네트워크 장비를 통해 지원해주는게 주 역할이지만 내 문제해결에도 큰 도움이 됐다. 

이 글에서 한번에 작성하기엔 범위가 크고 주제도 맞지 않기 때문에 명령어 설명은 생략하겠다.

 

기본적으로 컨테이너를 생성하면 브릿지 형태의 네트워크로 설정된다. 

컨테이너 밖에서 ifconfig 해보면 docker0라는 가상 네트워크 인터페이스가 생긴걸 알 수 있다.

컨테이너 외부의 가상 인터페이스 ip는 D클래스가 1번으로 지정되어 있고, 내부에서 ifconfig 설치 후 확인해보면

172.17.0.2를 갖는걸 볼 수 있다.

 

위에선 생략했지만 ping으로 컨테이너 내부에서 172.17.0.1 주소에 패킷을 날려보면 응답이 온다.

 

문제가 거의 해결된 것 같다. 정확하진 않지만 NAT 환경과 관련된 문제인것 같다.

해결 방법은 여러가지가 있겠지만, 제일 간단한 해결 방법은 컨테이너를 브릿지가 아닌 호스트 방식으로 run하는 것이다.

 

기존에 만든 test 이미지를 과감하게 지우고 host 네트워크로 다시 만들어보겠다.


 

apt-get update 성공

아래 명령어로 test를 삭제하고 네트워크를 host로 지정해서 다시 만들어보자.

$ sudo docker rm test
$ sudo docker run -it --name=test --network=host ubuntu:20.04 /bin/bash

 

쉘이 바뀌었는데 기존처럼 랜덤한 컨테이너 ID가 아니라 host와 같은 내용의 root 쉘이 되었다.

이제 업데이트를 해보자.

$ apt-get update

 

업데이트가 잘 된다. 추가로 필요한 패키지는 apt-get install로 설치하면 될 듯 하다.

해결 방법은 docker run할때 --network=host 라는 옵션을 하나 추가한 것 밖에 없지만 과정은 생각보다 길었던 것 같다.

 

이제 만들어진 ubuntu:20.04 컨테이너에 파이썬과 Django 프레임워크를 설치해서 간단한 웹사이트를 띄워보자.


 

Django 

설치 과정은 https://hwan001.tistory.com/186 글과 같지만 몇 가지 명령어가 다른 점이 있다.

달라진 명령어는 아래 내용에 적어두었다.

 

먼저 apt repository를 국내에서 제공하는 서버로 바꿔주자.

이 글에선 컨테이너 외부의 우분투에 미리 설정되어 있기 때문에 해당 파일을 도커 내부 같은 경로에 cp 명령어로 덮어씌워 줬다.

아래는 /etc/apt/source.list의 내용이고 기존 파일에 kakao 서버 주소만 추가해 주었다.

필요하다면 그대로 사용해도 좋고 다른 국내 서버 주소를 찾아서 추가해줘도 좋다.

 

$ vi /etc/apt/source.list
# deb cdrom:[Ubuntu 20.04.4 LTS _Focal Fossa_ - Release amd64 (20220223)]/ focal main restricted

# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb http://kr.archive.ubuntu.com/ubuntu/ focal main restricted
# deb-src http://kr.archive.ubuntu.com/ubuntu/ focal main restricted


## Major bug fix updates produced after the final release of the
## distribution.
deb http://kr.archive.ubuntu.com/ubuntu/ focal-updates main restricted
# deb-src http://kr.archive.ubuntu.com/ubuntu/ focal-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
deb http://kr.archive.ubuntu.com/ubuntu/ focal universe
# deb-src http://kr.archive.ubuntu.com/ubuntu/ focal universe
deb http://kr.archive.ubuntu.com/ubuntu/ focal-updates universe
# deb-src http://kr.archive.ubuntu.com/ubuntu/ focal-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
deb http://kr.archive.ubuntu.com/ubuntu/ focal multiverse
# deb-src http://kr.archive.ubuntu.com/ubuntu/ focal multiverse
deb http://kr.archive.ubuntu.com/ubuntu/ focal-updates multiverse
# deb-src http://kr.archive.ubuntu.com/ubuntu/ focal-updates multiverse

## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb http://kr.archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse
# deb-src http://kr.archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse

## Uncomment the following two lines to add software from Canonical's
## 'partner' repository.
## This software is not part of Ubuntu, but is offered by Canonical and the
## respective vendors as a service to Ubuntu users.
# deb http://archive.canonical.com/ubuntu focal partner
# deb-src http://archive.canonical.com/ubuntu focal partner

deb http://security.ubuntu.com/ubuntu focal-security main restricted
# deb-src http://security.ubuntu.com/ubuntu focal-security main restricted
deb http://security.ubuntu.com/ubuntu focal-security universe
# deb-src http://security.ubuntu.com/ubuntu focal-security universe
deb http://security.ubuntu.com/ubuntu focal-security multiverse
# deb-src http://security.ubuntu.com/ubuntu focal-security multiverse

# This system was installed using small removable media
# (e.g. netinst, live or single CD). The matching "deb cdrom"
# entries were disabled at the end of the installation process.
# For information about how to configure apt package sources,
# see the sources.list(5) manual.


# kakao
deb http://ftp.daumkakao.com/ubuntu/ bionic main restricted
deb http://ftp.daumkakao.com/ubuntu/ bionic-updates main restricted
deb http://ftp.daumkakao.com/ubuntu/ bionic universe
deb http://ftp.daumkakao.com/ubuntu/ bionic-updates universe
deb http://ftp.daumkakao.com/ubuntu/ bionic multiverse
deb http://ftp.daumkakao.com/ubuntu/ bionic-updates multiverse
deb http://ftp.daumkakao.com/ubuntu/ bionic-backorts main restricted universe multiverse

 

파일을 덮어씌우고 update와 upgrade를 한번씩 더 해줬다.

 

이제 python3, pip3, vim, venv를 apt-get install로 설치한다.

$ apt-get install -y python3 python3-pip python3-venv vim

 

이후 과정은 위 링크와 동일하다.

 

 

 

728x90
반응형
728x90
반응형

기본 Django 개발도구 설치 및 설정

Django가 설치된 환경은 Ubuntu 20.04 LTS 이다. python과 pip등 개발에 필요한 도구들을 설치해준다.

$ sudo apt-get install python3 pip3 venv vim

 

설치 후엔 좀 더 편하게 도구들을 사용하기 위해 .bashrc에 alias를 등록해준다.

각 사용자 계정에 위치한 .bashrc 파일을 열어 ll, la 등의 기본 alias 내용이 있는 곳에 같이 입력해주면 된다.

이 과정은 필수는 아니지만 개인적으로 해두면 편해서 만들어 줬다.

alias python='python3'
alias pip='pip3'
alias vi='vim'

 

입력 후엔 source .bashrc 명령어를 입력해준다.

$ source .bashrc

 


Venv 가상환경에 Django 패키지 설치하기

개발을 시작하기 전에 위에서 같이 설치해준 venv를 사용해서 파이썬 가상환경을 만들어준다.

가상환경을 만들면 프로젝트 단위로 패키지에 대한 관리가 자유롭다.

$ python -m venv test

 

test 라는 이름의 가상환경을 사용자 계정의 기본 경로 (/home/username/)에 만들어 줬다.

환경이 만들어지면 이미지처럼 기본적인 구조가 자동을 만들어진다.

하지만 아직 가상환경의 내부로 들어온 건 아니기 때문에 아래 명령어를 추가로 입력해 줘야 한다.

$ source bin/activate

 

bin 폴더 내부의 activate 스크립트를 실행하면 가상환경에 진입한다.

이제부터 pip로 원하는 패키지를 설치하면 해당 환경 내에서만 설치가된다.

django 설치가 완료되면 bin 폴더에 django-admin이 설치된걸 볼 수 있다.

$ pip install django

 


Django 프로젝트 생성 후 서버 실행

pip를 사용해서 장고를 설치하면 Django-admin이라는 툴이 같이 설치된 걸 볼 수 있다.

이 툴을 사용해 Django 프로젝트를 생성한다.

$ django-admin startproject project_name

 

projcet_name이라는 이름의 프로젝트가 잘 생성되었다.

 

웹서버를 실행해보자.

$ ./manage.py runserver 0:12345

 

빨간색 박스 부분에 migrate 경고가 뜬걸 볼 수 있는데, 실행은 되었기 때문에 다른 PC의 브라우저로 접속해보았다.

참고로 현재 서버는 다른 PC와 같은 공유기 밑에서 같은 c클래스 사설 아이피를 사용한다.

 

서버의 아이피와 포트를 입력해서 접속했지만 ALLOWED_HOSTS에 서버 IP를 추가하라는 경고 문구만 나온다.

위에서 만들어진 project_name/project_name 디렉토리 내부의 settings.py를 열어보면 아래 이미지와 같은 부분이 있다. ALLOWED_HOST =[] 에서 []사이에 서버 접속 시 사용할 주소를 'xxx.xxx.xxx.xxx' 형태로 넣어주면 된다. 

$ vi project_name/settings.py

 

서버를 실행할때 나왔던 경고도 없애주자.

아래 명령어로 migrate하면 된다.

$ ./manage.py makemigrations
$ ./manage.py migrate

 

서버를 실행해주고 다시 브라우저로 접속해보면 아래 이미지처럼 환영한다는 문구와 로켓 그림이 나온다.

 


 

 

728x90
반응형
728x90
반응형

 

Docker Hub 와 Docker Repository

 도커는 깃 허브와 비슷한 구조로 만들어졌다.

사용자들은 여러 명령어를 활용해 Docker를 설치하고 이미지를 내려받아 필요한 환경을 구축한 후 이미지를 다시 빌드하여 허브에 업로드할 수 있고, 업로드된 이미지는 (인터넷이 가능하고 Docker가 설치되었다면) 언제든 다시 내려받아 사용할 수 있게된다. 

 

 이런 과정들을 가능하게 하려면 먼저 Docker Hub에 계정을 만들고, 이미지를 배포하고 관리할 Repository를 생성해야 한다. Repository의 이름은 배포할 이미지의 이름과 같아야 한다. (태그는 보통 버전관리를 위해 사용)

 

 아래 링크에서 가입이 가능하다. 

 https://hub.docker.com/

 

Docker Hub Container Image Library | App Containerization

We and third parties use cookies or similar technologies ("Cookies") as described below to collect and process personal data, such as your IP address or browser information. You can learn more about how this site uses Cookies by reading our privacy policy

hub.docker.com


 

Docker Commit

 도커 허브에 만들어둔 Repository에 이미지를 업로드하려면, 먼저 이미지를 만들어야한다.

아래 명령어에서 -a 옵션은 commit할 이미지의 작성자명이고, -m 옵션은 주석이다.

commit 하고 싶은 이미지의 Container ID를 docker image로 확인하고 이미지네임과 태그를 추가로 입력해준다.

이 때 이미지네임과 태그는 도커 허브에 만들어둔 레포지토리 명과 동일해야한다.

혹시 다르게 생성했다면 아래 Tag 명령어를 사용해 commit 전에 변경이 가능하다.

 

$ sudo docker commit -a "hwan001" -m "commit message" 컨테이너id 이미지네임/태그

 

Docker Tag

 도커 저장소에 이미지를 push 하려면 도커의 저장소 이름과 이미지가 서로 같은 이름을 가지고 있어야 한다.

위에서 만들어진 이미지의 이름과 tag를 아래 명령어로 변경해주자.

$ sudo docker tag 원래이름:태그 hwan001/django_webserver_test:0.1

 

Docker Push

 태그까지 맞췄다면 아래 명령어로 허브에 업로드 할 수 있다.

$ sudo docker push hwan001/django_webserver_test:0.1

 

업로드 확인

허브의 레포지토리에 잘 업로드 되었다.

728x90
반응형
728x90
반응형

Docker

이전 글 : Ubuntu에 Docker 설치하기 (1)

https://hwan001.tistory.com/180

 

[서버] Ubuntu에 Docker 설치하기

Docker ? 리눅스 컨테이너화 기술로 사용자가 리눅스 컨테이너를 만들고 사용할 수 있도록 지원한다. 도커는 가상화 기술이 아닌 격리 기술이지만 가상 머신과 비슷한 느낌으로 사용한다. 컨테이

hwan001.tistory.com


Docker에서 Ubuntu 20.04 LTS 최신 버전 공식 이미지 내려받기

 Docker를 설치하면 도커 허브에 공유된 공식 이미지 또는 개인이 업로드한 이미지와 직접 제작한 이미지 등을 다운로드하여 원하는 환경을 쉽게 구성할 수 있다.

 

먼저 아래 명령어를 사용하면 도커 허브에 공유되고 있는 이미지 목록을 가져온다.

$ sudo docker search {image_name}

 

아래 명령어는 이미지를 도커 허브로부터 다운로드 받는다.

태그를 통해 해당 이미지의 특정 버전을 다운받아오거나 :latest 태그를 활용하여 최신 버전 이미지를 받아올 수 있다.

$ sudo docker pull ubuntu:latest

 

이미지를 내려받은 후 실행 까지 하려면 docker run 명령어를 실행하면 된다.

$ sudo docker run -i -t ubuntu:20.04 /bin/bash

이미지를 내려받은 뒤 컨테이너에 접속하여 bash 쉘을 실행 시켰다.

참고로 이미지가 있는 상태에서 run하게 되면 새로운 컨테이너가 생긴다.


컨테이너 접속

Exit 후 아래 명령어로 확인해보면 이미지의 빨간색 박스 부분처럼 도커가 임의로 컨테이너의 이름을 정해준 것을 알 수 있다.

$ sudo docker ps -a

 

docker start 명령어로 도커가 임의로 정한 컨테이너의 이름을 입력하고,

docker ps를 입력하면 현재 도커 내부에서 실행 중인 이미지가 보이지만 쉘의 형태는 변하지 않는다.

해당 컨테이너는 정상적으로 실행되었지만 아직 내부로 들어가진 않았다.

$ sudo docker start hungry_williamson
$ docker ps

 

컨테이너에 접속하여 쉘을 실행하기 위해선 추가적인 과정이 필요하다.

$ sudo docker attach hungry_williamson

 

docker attach 명령어로 실행 중인 컨테이너에 접속했다.


이미지, 컨테이너 삭제

만약 이미지와 컨테이너를 삭제하고 싶다면 아래 명령어를 사용한다.

$ sudo docker rm {컨테이너 이름}

$ sudo docker rmi ubuntu

 

728x90
반응형
728x90
반응형

SSH 포트 변경이 필요한 이유

SSH 서비스의 기본 포트는 22번이다.

하지만 인터넷에 서버를 공개하게 되면 네트워크 공간에 떠돌고 있는 수많은 자동 프로그램들이 로그인 시도를 한다.

이때 기본 포트를 사용하면 보안에 취약하기 때문에 포트를 변경해주는 것이 좋다.

(물론 nmap 등의 툴을 통해 포트 스캔하면 다 나온다.)

 

아래 사진은 최근 Django 웹서버 구축을 위해 잠시 열어둔 서버를 누군가 접속 시도한 기록이다.

ssh로 root 로그인 금지해야하는 이유

 

초 단위로 여러 아이피에서 root로 로그인 시도한 걸 볼 수 있다.

만약 방금 설치한 서버에서 별다른 조치없이 ssh 서비스부터 열었다면, 서버는 순식간에 특정 국가 해커들의 채굴 도구나 C&C 서버 역할을 할 것이다.

 

로그인 시도 기록을 보려면 아래 명령어를 사용한다.

'접속 시도 기록'
$ cat /var/log/auth.log

'로그인 기록'
$ last

SSH 포트 변경 방법

 

포트 변경 방법은 간단하다.

$ vi /etc/ssh/sshd_config

/etc/ssh/sshd_config 파일을 열어 주석처리된 #PORT 22 부분을 해제하고 원하는 포트를 입력하면된다.

 

이후 ssh 데몬을 재실행한다.

$ service sshd restart

공유기 포트 포워딩

도메인을 구입하거나 클라우드 서비스를 이용한다면 모르겠지만 집에서 iptime 공유기가 제공하는 무료 도메인을 사용한다면 포트 포워딩을 해줘야 한다.

대부분 정보를 가려두었지만, 원하는 포트를 바인딩해준다.

 

예시)
규칙 이름 : 서버_ssh_서비스
내부 IP 1.1.1.1 (서버 주소)
프로토콜 : TCP 
외부 포트 : 1234~1234 
내부 포트 : 1234~1234

변경된 포트로 접속하는 방법

접속 방법은 ssh 설치된 환경에서 아래 명령어를 사용한 뒤 로그인한다.

ssh user_name@server_url -p 1234

 

 

728x90
반응형

'Computer Science > Server & Network' 카테고리의 다른 글

[프로토콜] TCP  (0) 2022.03.19
[서버] scp 명령어 사용  (0) 2022.03.19
[서버] Django 홈 서버 구축하기  (0) 2022.03.17
[프로토콜] FTP  (0) 2022.03.11
[서버] MariaDB 서버 구축 - 작성 중  (0) 2022.03.09
[서버] Cent OS-7 설치 및 초기 설정  (0) 2022.03.03
728x90
반응형

Docker

 

Docker

  • 리눅스 컨테이너화 기술로 사용자가 리눅스 컨테이너를 만들고 사용할 수 있도록 지원한다.
  • 도커는 가상화 기술이 아닌 격리 기술이지만 가상 머신과 비슷한 느낌으로 사용한다.
  • 컨테이너를 구축, 배포, 복사하며 환경의 이전이 자유롭기 때문에 AWS 등 클라우드 서비스에 최적화되었다.
  • 처음엔 리눅스의 LXC 기술(기존의 컨테이너)을 활용하였으나 현재는 자체 개발된 기술 활용한다.
  • 도커는 단일 컨테이너 관리에 적합하게 만들어져 있다. (다수의 컨테이너를 다루려면 쿠버네티스 활용)
  • https://www.docker.com/
 

Home - Docker

A Community like No Other Community is at the heart of what Docker does. From our Docker Captains sharing their insight and expertise, to hundreds of MeetUps around the world, to our Slack and Discourse forums for peer-to-peer support, there’s someone el

www.docker.com


 

Docker 설치

 도커는 실제 Linux 서버에 설치 후 공식 매뉴얼 (https://docs.docker.com/engine/install/ubuntu/) 을 참고하여 작성했고, 다른 운영체제에서의 설치가 필요하다면 공식 매뉴얼을 참고하기 바란다.

아래 내용은 Ubuntu 20.04 LTS 기반이며, 서버는 미리 설치 후 설정까지 되어 있다고 가정하고 진행하겠다.

 

** 서버 OS 요구사항이 존재함 설치 전 참고

도커 설치를 위한 서버 요구사항

 

 

서버가 준비되었다면 도커 설치를 위해 가장 먼저 OS에 존재하는 이전 버전 docker (docker, docker.io, docker-engine)를 제거해야되고, 아래 명령어를 통해 제거가 가능하다.

$ sudo apt-get remove docker docker-engine docker.io containerd runc

 

 

제거가 완료되었다면 apt-get를 업데이트하고 curl과 기타 패키지를 설치한다.

 $ sudo apt-get update
 $ sudo apt-get install ca-certificates curl gnupg lsb-release

 

 

이후 curl로 도커의 공식적인 gpg 키를 가져온 뒤 gpg 명령어로 추가한다.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

 

 

위에서 가져온 키를 사용하여 도커 이미지를 다운받아올 deb 명령어 만들어 /etc/apt/sources.list.d/docker.list 에 추가한 뒤 결과를 출력해준다.

 $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg]\
 https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"\
 | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

$(dpkg --print-architecture) 는 현재 서버의 아키텍쳐를 가져오고, $(lsb_release -cs) stable은 우분투 배포판의 버전을 가져온다. 여기서 stable은 docker 이미지의 버전으로 nightly 또는 test 입력이 가능하다.

 

관련 내용은 아래 링크 내용의 nightly와 test 항목 참조.

https://docs.docker.com/engine/install/

 

Install Docker Engine

 

docs.docker.com

 

명령어 실행 후 vi로 /etc/apt/sources.list.d/docker.list 파일을 열어보면 출력된 결과가 파일 내에 작성되어진 걸 볼 수 있다.

 

 

아래 명령어로 도커 엔진의 가장 최신 버전과 index 패키지를 다운로드한다.

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

 

** 도커 엔진의 특정 버전이 필요하다면 아래 이미지 또는 공식 매뉴얼 참조

다른 버전 설치 방법

 

 

도커의 다운로드와 설치가 끝났다.

아래 명령어로 기본 도커와 같이 설치되는 Hello-world 이미지를 run 한다.

$ sudo docker run hello-world


 

 

728x90
반응형
728x90
반응형

파이썬의 데코레이터란?

먼저 Decorate는 '장식하다' 라는 의미가 있고, 따라서 직역하면 '장식자'라는 의미가 된다. (구글 번역기에서는 a person who decorates something. 로 정의되어 있다.)

파이썬에서도 원래 뜻과 비슷한 의미로 사용되는데 @ 기호로 표현 할 수 있으며, 클래스나 메소드를 정의할 때 많이 사용되어 진다.

데코레이터는 직접 정의하여 사용하거나 미리 정의된 내용을 가져와 사용이 가능하다.

(정의된 데코레이터는 @property, @classmethod, @staticmethod 등이 있다.)

 

데코레이터를 작성하면 원본 메소드의 내용을 수정하지 않고 여러 기능을 추가할 수 있게 된다.

  • 메소드(함수)의 실행시간 측정
  • 실행과 종료에 로그 기능 추가
  • ...

메소드 데코레이터 정의하기

데코레이터는 크게 클래스 데코레이터메소드 데코레이터로 나눠진다.

메소드 데코레이터는 메소드를 장식하기 위한 데코레이터로 기본적인 형태는 아래 코드를 따르게 되며,

def decorator_1(func):
	def wrapped_func():
		func() 
    return wrapped_func()

 

만들어진 데코레이터의 사용은 아래 코드와 같다.

# 메소드 데코레이터 정의
def decorator_1(func):
	def wrapped_func():
		print("start")
		func() 
		print("end")

	return wrapped_func

# 사용
@ decorator_1
def test_func():
	print("logic")

test_func()

 

 

위 사진은 데코레이터를 사용한 결과인데 내용을 보면 가장 마지막 줄에 test_func()을 호출했지만 decorator_1에 내부에 정의된 wrapped_func의 기능이 수행된 것을 볼 수있다.

 

하지만 데코레이터를 사용하는 함수의 매개변수를 바꾸고 실행하면 TypeError가 발생한다.

정상적으로 메소드에 인수를 받아 사용하려면 데코레이터의 수정이 조금 필요하다.

 

아래 코드를 보면 wrapped_func에 *args가 매개변수로 추가되었다.

*을 사용하여 non-keworded arguments 형식으로 인수를 받을 수 있는데 이렇게 사용하면, 키워드가 없는 가변 인수가 되어 여러개의 인수를 받는 것이 가능해진다. (만약 메소드에 키워드가 필요하다면 **(keworded arguments)를 사용) 

def decorator_1(func):
	def wrapped_func(*args):
		print("start - ", func.__name__)
		func(*args) 
		print("end - ", func.__name__)

	return wrapped_func


@ decorator_1
def test_func(str_var, int_tmp, a, b, c):
	print(str_var,  int_tmp, a, b, c)


test_func("test", 12, 1, 2, 3,)

 

위 코드에서 매개변수를 받아 출력을 했지만, test_func 함수의 결과 값은 받아볼 수 없다.

wrapped_func 내부에서 func의 결과 값을 받아 return 해줬다.

def decorator_1(func):
	def wrapped_func(*args):
		print("start - ", func.__name__)
		ret= func(*args) 
		print("end - ", func.__name__)
		return ret
	return wrapped_func


@ decorator_1
def test_func(str_var, int_tmp, a, b, c):
	print(str_var,  int_tmp, a, b, c)
    return a + b


print(test_func("test", 12, 1, 2, 3,))

클래스 데코레이터

 

위에서 작성한 데코레이터를 클래스 내에 넣어 작성해보았다.

메소드 데코레이터와 동일한 기능을 수행하는 것을 볼 수 있다.

class myClass:
	def myClass_LoggingDecorator(func):
		def wrapped_func(*args):
			print("start - ", func.__name__)
			func(*args) 
			print("end - ", func.__name__)
		return wrapped_func

	@ myClass_LoggingDecorator
	def test_func(str_var, int_tmp, a, b, c):
		print(str_var,  int_tmp, a, b, c)


myClass.test_func("test", 12, 1, 2, 3,)


클래스 데코레이터 - 활용

import time
import datetime

class myClass:
	def myClass_RunningtimeDecorator(func):
		def wrap(*args):
			start_r = time.perf_counter()
			start_p = time.process_time()

			ret = func(*args)

			end_r = time.perf_counter()
			end_p = time.process_time()
            
			elapsed_r = end_r - start_r
			elapsed_p = end_p - start_p

			print(f'{func.__name__} : {elapsed_r:.6f}sec (Perf_Counter) / {elapsed_p:.6f}sec (Process Time)')
			return ret
		return wrap

	def myClass_LoggingDecorator(func):
		def wrapped_func(*args):
			file_name = f"log_{datetime.datetime.today().strftime('%Y-%m-%d')}.txt"

			File = open(file_name, "w")
			File.write(f"start - {func.__name__}, DateTime : {datetime.datetime.now()}\n")

			ret = func(*args) 
			
			File.write(f"end - {func.__name__}, DateTime : {datetime.datetime.now()}\n")
			File.close()

			return ret
		return wrapped_func

	#@ myClass_RunningtimeDecorator
	@ myClass_LoggingDecorator
	def test_sum(str_var, a, b):
		print(str_var, a + b)
		return a + b
        

print ("res2 :", myClass.test_sum("res1 :", 1, 2))

LoggingDecorator / RunningtimeDecorator
log file

 

728x90
반응형

'프로그래밍 > Python' 카테고리의 다른 글

[python] JWT 모듈  (0) 2022.09.13
[Python] Yahoo_fin 모듈  (0) 2022.09.11
[Python] Paramiko 모듈  (0) 2022.07.07
[Python] min, max 함수  (0) 2022.03.10
[python] lambda 표현식  (0) 2022.01.07
[python] 실행 시 필요한 패키지 자동 설치  (0) 2022.01.01
728x90
반응형

 

포스팅 이유

최근에 IT 직군으로 취업을 준비하면서 기술면접에 대한 질문 내용을 찾던 중 설로인이라는 회사에서 공개한 질문 목록을 찾았다.
꽤 넓은 분야에 관련된 좋은 질문들이 있어서 작성했다.

먼저 원본 질문의 링크이다.
https://github.com/sirloin-dev/meatplatform/blob/master/job-description/interview-questions.adoc
 

GitHub - sirloin-dev/meatplatform: 설로인의 육류 플랫폼 서비스를 소개합니다!

설로인의 육류 플랫폼 서비스를 소개합니다! Contribute to sirloin-dev/meatplatform development by creating an account on GitHub.

github.com

 

 

목차

  • 경력 관리 및 협업
  • 운영체제 / 논리회로 일반
  • 네트워크
  • 데이터 베이스
  • 자료 구조 및 알고리즘
  • 디자인 및 테스트
  • Java / JVM
  • Kotlin
  • Python
  • NodeJS
  • Android
  • ios
  • Web

 

경력 관리 및 협업

  • 설로인 입사 이후, 3년 뒤 후보자의 모습, 10년 뒤 후보자의 모습에 대해 말씀해주세요.
  • 수습 기간동안 어떻게 본인의 능력을 팀에게 증명해 보이시겠습니까?
  • 일을 하던 중에, 다른 업무 요청이 들어온다면 어떻게 상황을 조율하시겠습니까?
  • 제일 재미있게 들었던 학교 수업, 또는 최근 흥미가 있거나 재미있었던 개발 관련 소식 / 또는 해본 일중 기뻤거나 슬픈 일
  • 후보자님께서 소프트웨어 엔지니어의 길을 걷기로 결심한 이유에 대해 말씀해 주세요.
  • 납득가지 않는 일을 떠 맡게 되었다면, 갈등을 어떻게 해결하시겠습니까?
  • 코드 리뷰에서 동료 코드의 어떤 점을 가장 중요하게 체크하시나요?
  • 코드의 품질을 정의하는 후보자님만의 기준이 있습니까?
  • Continuous Integration 의 중요성에 대해 설명해주세요.
  • OpenJDK 는 GNU GPL 라이선스로 배포됩니다. GNU GPL 이 뭔가요?
  • 정규표현식을 유용하게 사용한 경험이 있습니까? 또는 불편한 적은 없었나요?
  • 저희 회사는 후보자님이 자신있어 하시는 XX 기술을 쓰지 않고 있습니다. 그 기술을 반드시 도입해야 한다고, 면접관을 어떻게 설득하시겠습니까?
  • 업무 스케쥴링 하실 때, 시간 비용은 어떻게 산정하시나요?
  • Agile 이 대세라고 하는데, Agile 개발 방법론에 대한 본인의 생각을 말씀해 주세요. Agile 의 단점은 없습니까?

 

운영체제/ 논리회로 일반

  • 컴퓨터는 10진수를 2진수로 바꿔서 계산합니다. 10진수를 2진수로 바꾸는 방법과, 그 반대 방법에 대해 설명해 주시기 바랍니다.
  • 컴퓨터는 소숫점 계산을 잘 못합니다. 그 이유가 무엇일까요? 어떻게 문제를 해결할 수 있을까요? 직접 구현한다면 어떻게 하시겠습니까?
  • Thread 간의 데이터 공유와 Process 간의 데이터 공유의 공통점과 차이점을 설명해주세요.
  • 컴퓨터가 기계어를 읽고, 실행하는 과정에 대해 설명해 주실 수 있나요?
  • 운영체제가 여러 프로그램을 동시에 실행하는 원리에 대해 설명해주세요.
  • 컴파일러와 인터프리터는 어떤 차이가 있을까요?
  • Garbage Collection 이란 무엇일까요? Garbage Collection 방식 중 제일 잘 알고 계시는 GC를 아무거나 하나만 설명해주세요.
  • Garbage collection 이 있는 언어를 원자력 발전소, 자동차 동력 제어, 인공위성, 국가 전력망 제어시스템 같은 곳에 쓸 수 있을까요? 후보자님의 생각을 말씀해 주세요.
  • 지금 이용하시는 기술/언어에서 제일 마음에 드는점과 불만인 점 한가지를 말씀해주세요.
  • System call 이 뭔가요? System call 에 대해 설명해주세요.
  • 바이트코드와 기계어의 차이에 대해 설명해주세요.
  • Thread safety 란 뭔가요? 어떻게 구현해야 Thread safe 한 코드를 만들 수 있나요?
  • bytecode 기반 언어는 디컴파일에 특히 취약하다는 문제가 있는데, 언어를 바꾸지 않고 이를 해결할 방법이 없을까요?
  • 파이프(|) 란 무엇이고, 어떻게 동작하는지 설명해주세요.

네트워크

  • Socket 으로 바로 통신하는 것 대비 HTTP 는 비효율적인데도 왜 많은 앱들은 HTTP 를 쓰는 걸까요?
  • OSI Layer 7 또는 TCP Model 에 대해 설명해주세요.
  • 차세대 프로토콜로 논의중인 HTTP/3 은 UDP 기반의 QUIC 이라는 기술로 구현되어 있습니다. UDP 는 TCP 대비 안
  • 정성이 떨어지는 프로토콜이라고 하는데, 그럼에도 왜 UDP 를 채택한 걸까요?
  • SSL (또는 TLS) 가 어떻게 동작하는지 말씀해주세요.
  • HTTP 는 Stateless (상태가 없는) 통신 프로토콜이라고 합니다. 따라서, 상태가 없다면 가령 HTTP 를 쓰는 서비스는 매번 로그인을 해 줘야 하거나 사용자 정보를 저장하는 일이 불가능합니다. 그런데 실제론 그렇지 않죠. 어떻게 이런 불편함을 해소했을까요?
  • 웹 브라우저에 https://www.google.com URL 을 입력 후 enter 를 쳤을 때 일어나는 과정을 최대한 상세하게 설명해주세요.
  • HTTP(s) 프로토콜에서 바이너리 데이터를 전송하는 방식에 대해 설명해주세요.
  • Socket 으로 웹 페이지를 크롤링하는 HTTP 클라이언트를 직접 구현해야 한다면, 어떻게 하시겠습니까?

 

데이터 베이스

  • noSQL 과 RDB 의 특징, 차이에 대해 말씀해주세요. 어느 상황에 어떤 데이터베이스를 쓰는게 좋겠습니까?
  • 데이터베이스가 자료를 빠르게 검색하기 위해 어떤 일을 할까요? 최대한 상세하게 설명해주세요.
  • RDBMS 의 여러 JOIN 중 아무거나 하나 골라서, 그림으로 설명해 주실 수 있습니까?
  • 데이터베이스 샤딩 / 파티셔닝에 대해 설명해주세요.
  • 데이터베이스가 Index 를 이용해 자료를 빠르게 검색하는 과정을, 우리 할머니도 알아들을 수 있도록 설명해 주시겠어요?
  • Stored procedure 를 이용한 시스템을 어떻게 유지보수 할 수 있습니까? Stored procedure 의 장점과 단점에 대해 말씀해 주세요.
  • Optimistic Locking(낙관적 락) 과 Pessimistic Locking(비관적 락) 에 대해 설명해주세요. 각각의 락을 사용할 상황 또는 제품 사례를 말씀해주세요.
  • 어떤 서비스의 이용자 테이블이 있다고 가정합시다. 이용자 id 를 여러 테이블에서 FK 로 참조하고 있습니다. 그런데 이용자 테이블에 환경설정, 개인정보 등 정보를 한데 저장하다보니 Column 이 40개가 넘게 있는 상태입니다. 문제를 진단해 주시고, 해결 방안도 제시해 주시기 바랍니다.
  • Slow query 를 발견하고, 수정한 경험에 대해 말씀해 주세요.
  • 저희는 도축장에서 전달받은 원육을 소매점에 도매하는 서비스를 운영하고 있습니다. 여기서, 원육과 소매점을 어떻게 테이블로 모델링 하시겠습니까?
  • 어플리케이션의 문자열(String) 을 데이터베이스에 저장하기 위해 고려해야 할 사항에는 어떤 점이 있을까요?
  • Big data 를 다루려면 RDBMS 보다 NoSQL 이 더 좋다는 말이 많습니다. 그렇다면 large data set 에는 항상 NoSQL 만 써야 할까요? 반드시 RDBMS 만을 이용해 large data set 을 다루려면 어떻게 해야 할까요?
  • 실 서비스의 데이터를 조작하고, 또 조회해야 하는 Admin app 을 만들어야 한다면, 어떻게 구현하시겠습니까?
  • 데이터 마이그레이션 기간 동안 서비스 순단을 최소한으로 하고 싶습니다. 이런 요구사항에 맞는 테이블을 어떻게 설계하시겠습니까?
  • (JPA 경험자 한정) JPA 를 이용할 때, JPQL 을 쓰는 경우가 종종 있는데, JPQL 을 쓰시며 좋았던 점과 불편했던 점을 말씀해 주세요.
  • (JPA 경험자 한정) JPA 의 @Entity 란 뭔가요? 도메인 객체와 Entity 객체를 각각 어떻게 정의하시겠습니까?
  • (JVM 경험자 한정) 배열과 ArrayList, LinkedList 의 차이점은 무엇인가요?

 

자료 구조 및 알고리즘

  • 지금 사용하시는 스마트폰의 화면을 캡쳐하는 프로그램을 만들어야 한다면 어떻게 하시겠습니까?
  • 전화번호와 같은 민감한 정보를 어떻게 저장하는게 좋을까요? 관리자조차 모르게 저장하고 싶다면?
  • 암호화란 무엇일까요? 알고 계신 암호화 방식 아무거나 하나만 설명해주세요.
  • 어떤 알고리즘을 도입하기 전에, 성능을 판별해 보고자 합니다. 어떤 방법을 활용해, 어떤 기준으로 알고리즘의 효율을 판단하시겠습니까?
  • 공개 키 암호화와 비밀 키 암호화에 대해 설명해주세요.
  • 캡슐화에 대해 설명해주세요.
  • 캐시란 뭐고, 어떤 목적으로 쓰는 건가요?
  • List 와 Set 의 차이에 대해 설명해주세요.
  • 이진 탐색의 최선 / 최악의 경우에 대해 말씀해주세요.
  • 손실 압축과 무손실 압축의 차이에 대해 설명해주세요.
  • RSA 로 공개 키를 만들 때, 키 길이를 정하는 기준이 있습니까? 키 길이를 길게 하면 암호화 문제를 완벽 해결할 수 있나요?
  • 순환 Queue 를 만드려면 어떻게 하시겠습니까? 그리고 어떤 Queue 또는 Graph 가 무한 순환 구조라는 것을 어떻게 판단하시겠습니까?
  • 압축 알고리즘을 설계하라는 요구사항이 들어왔다면, 어떻게 구현하시겠습니까?
  • 전화번호부 앱을 만든다고 가정하겠습니다. 1명당 1KiB의 정보를 갖도록 모델을 설계했습니다. 앱이 온전히 사용할 수 있는 메모리가 4메가인 기기에서, 10000명(총 10메가)의 이용자 정보를 검색할 수 있도록 구현해야 합니다. 어떻게 하시겠습니까?
  • (JVM 경험자 한정) 배열과 ArrayList, LinkedList 의 차이점은 무엇인가요?

디자인 및 테스트

  • Singleton pattern 이란 무엇이고, 어떤 장점과 단점이 있을까요?
  • 싱글턴 코드는 테스트를 어렵게 만드는 문제가 있습니다. 왜 그럴까요? 싱글턴이 좋지 않다는데 왜 스프링 프레임워크 같은 녀석들은 별다른 규칙이 없을 때 기본으로 Singleton bean 을 만들까요?
  • 좋은 Test 라고 평가할 수 있는 가장 중요한 요소를 말씀해주세요. 후보자님은 어떤 Test 를 좋은 Test 라고 정의하십니까?
  • Callback function(또는 Closure) 이 뭔가요? 주의할 점이 있을까요?
  • Mutable, Immutable 이란 뭔가요? 각각은 어떤 특징이 있을까요?
  • Acceptance, Smoke, End-to-End, Integration, Unit test 같은 용어들을 본인만의 방법으로 구분짓는 기준이 있습니까?
  • 메소드의 파라미터로 전달한 객체를 메소드 내에서 마음대로 바꾸지 못 하게 하려면 어떻게 코딩하는게 좋을까요?
  • 왜 메소드가 파라미터를 조작하는 것이 문제가 될까요? 문제가 아닐 수도 있지 않을까요?
  • 음료수 자판기에 탑재한 소프트웨어를 제작했다고 가정해 보겠습니다. 작성하신 소프트웨어의 통합 테스트 시나리오를 어떻게 작성하시겠습니까? 생각나는대로 말씀해 주세요.
  • 현재 다루시는 플랫폼에서의 테스트 자동화를 어떻게 구축 하시겠습니까?
  • test code 를 작성하는 본인만의 기준이 있습니까? test 실행 속도를 높이려면 어떤 방법이 좋을까요?
  • blackbox testing, whitebox testing 의 차이에 대해 설명해주세요. 어떤 상황에서 어떤 테스트 방법을 사용하시겠습니까?
  • 상속의 이점 중 "코드의 중복을 줄여준다" 는 말이 있습니다. 그런데 코드 중복을 줄이기 위해서 상속을 쓰는 것은 매우 좋지 않은 코딩 방식이라고 저희는 생각합니다. 이에 대한 후보자님의 의견을 듣고 싶습니다.
  • Java 의 Marker interface (아무 메소드도 없이 타입만 있는) 에 대해 어떻게 생각하시나요?
  • 코드 응집성(cohesion)이란 말을 어떻게 설명하실 수 있습니까? 응집도가 낮은 코드와 높은 코드를 예를 들어 설명해 주세요.
  • NodeJS 로 실행하는 서버와 통신하는 Spring 또는 Python 서버를 구현할 때, 어떻게 하시겠습니까? HTTP 외의 방법을 쓰고 싶다면 어떻게 해야 할까요?
  • 네이버 같은 서비스에서 IP 주소가 바뀔 경우 접속 경고 등의 오류를 발생시킨다. 어떻게 구현하시겠습니까?
  • 서비스의 memory leak 을 어떻게 판단하고, 해결하시겠습니까?
  • 우리 서비스가 대 성공해서 이용자가 4000만이 되었다고 가정합니다. 이용자 4천만 돌파 기념으로 선착순으로 접속한 사용자에게 보너스 포인트를 주는 이벤트를 운영하려 합니다. 모든 이용자들에게 공평하게, 플랫폼이 제공하는 Push 를 보내려 하는데요. 이 경우, 어떤 점들을 고려해야 할까요?
  • MSA vs Monolithic 을 선택하는 기준이 있습니까?
  • M 인프라 시스템이 A 시스템 대비 가격이 많이 싸졌다고 가정해 보겠습니다. 우리의 인프라 시스템을 A 에서 M 으로 최대한 빨리 바꾸려면 어떤 점을 고려해야 할까요?
  • 우리 앱의 어떤 페이지(또는 특정 view) 의 로딩이 매우 늦다면 어떻게 개선할 수 있을까요?
  • 우리가 사용하는 앱들의 API 는 예고없이 바뀌기도 합니다. 외부 API 가 마구 변경되는 상황에서도 우리 앱이 크래시 나지 않게 하려면 어떻게 해야 할까요?
  • 제작한 애플리케이션이 얼마나 사용자 친화적인지를 측정할 수 있는 방법이 있을까요?

 

Java / JVM

  • JVM 에서의 autoboxing 이란 어떤 현상을 말하는 걸까요?
  • interface default implementation 이란? abstract class 를 상속받는 것과 기본 구현을 들고 있는 interface 를 implements 하는것은 어떤 차이가 있나요?
  • Java stream method 중 map 과 flatMap 의 차이에 대해 설명해주세요.
  • 메소드에서 리스트 타입의 파라미터를 받을 때, ArrayList - List - Collection - Iterable 처럼 구체 타입 뿐 아니라 상위 타입도 받을 수 있습니다. 컬렉션을 받는 어떤 API 를 구현하실 때 구체 타입의 API 디자인을 선호하는지, 추상 타입의 API 디자인을 선호하는지를 설명해 주세요. 왜 그런 선택을 하시나요?
  • Java 의 equals 와 == 의 차이에 대해 설명해주세요. Kotlin 의 == 와 === 는 어떤 차이가 있나요?
  • 스프링의 @Autowired 를 가급적 쓰지 말라는 이야기가 종종 들리는데 원인이 뭘까요?
  • final 키워드를 변수, 메소드, 클래스에 선언하는 것은 어떤 의미가 있습니까?
  • synchronized 를 메소드에 선언하는 것과, 특정 객체에 선언하는 것은 어떤 차이가 있습니까?
  • Reflection 을 유용하게 사용하는 사례를 말씀해 주세요.
  • JDK/JVM 은 대표적으로 OpenJDK 와 Oracle JDK 로 나뉘는데요, 업무에 어떤 JDK 를 사용하시겠습니까? 선택의 이유를 말씀해 주세요.
  • hashCode / equals 메소드의 역할에 대해 아시는 내용을 최대한 설명해주세요.
  • Java 의 Collections.unmodifiableList 같은 API 를 이용해 List 같은 collection 을 변경 불가능하게 만들 수 있습니다. 그렇다면 이 API 를 사용하면 immutability 를 달성할 수 있을까요?
  • 다음 싱글턴 코드의 어떤 점을 개선하실 수 있습니까? (개선이 필요 없을 수도 있음 / 왜?)
class MySingleton {
  private static MySingleton instance;

  public static synchronized MySingleton getInstance() {
    if (instance == null) {
        instance = new MySingleton();
    }
    return instance;
  }
}

 

  • java 9 이상에 도입된 추가 기능들 중 마음에 드는거 아무거나 하나만 설명해주세요.
  • 민감한 정보를 String 으로 저장하는 것과, char[] 또는 StringBuilder/StringBuffer 같은 클래스로 저장하는 것은 어떤 차이가 있나요?
  • 크기를 지정하지 않고 ArrayList 를 new 로 생성하면 크기 10의 ArrayList 가 생성됩니다. Array 는 크기를 넘길 수 없는데 반해 ArrayList 는 꽉 찬 List 에 element 를 추가로 더할 수 있습니다. 그렇다면 10개의 element 를 채워넣은 ArrayList 의 11번째 element 을 add 하기위해 어떤 일이 일어나는지 설명해주세요.
  • java.lang.String 의 hashCode 구현에 대해 고찰해 봅시다. 왜 그런 구현일지, 문제점은 없을지 이야기해주세요.
  • lambda 와 메소드 1개만 있는 익명 클래스 직접 선언은 문법적 차이 외에 어떤 내부적인 차이가 있을까요?
  • Java generics 에는 primitive type 을 쓸 수 없는 문제가 있습니다. 왜 그럴까요? 어떻게 해결할 수 있을까요?
  • I/O 를 Java nio 로 코딩할 때 주의점은 어떤게 있을까요?
  • Java 는 Pure OOP 언어가 아니라고 하는데, 왜 그런 걸까요?
  • java.lang.String 의 length 메소드는 정확한 결과를 반환하지 않는 경우가 종종 있습니다. 정확한 의 의미란 무엇이고, 왜 그럴까요?
  • Maven 이나 Gradle 이, 의존성 선언한 artifact 들을 찾는 과정에 대해 설명해주세요.
  • java.util.Property extends Hashtable, java.util.Stack extends Vector 같은 클래스는 상속으로 망한 대표 사례입니다. 이유를 설명해 주세요.
  • Spring boot 가 stereotype annotation 을 붙인 클래스들을 어떻게 찾고 bean 으로 등록하는지 그 과정을 최대한 상세하게 설명해주세요.
  • Spring 은 @Transactional 어노테이션 붙인 메소드를 어떻게 찾고 트랜잭션을 처리하나요? 그 내부 구현을 상세하게 설명해 주세요.
  • 메소드에 @Transactional 을 붙이는 것과, TransactionTemplate 을 사용해 트랜잭션을 직접 제어하는 것에는 어떤 차이가 있나요? 어떤 방식을 더 선호하시는지 그 이유도 함께 설명해 주시기 바랍니다.

Kotlin

  • Kotlin 으로 작성한 jvm target 코드는 숨은 비용이 있습니다. 어떤 숨은 비용을 말하는걸까요? 그럼에도 불구하고 Kotlin 을 써야 할까요?
  • Kotlin extension function 이 실제 native code 로 바뀔 때 어떤 형태로 바뀌는지 설명해주세요.

Python

  • object 의 기본 메소드인 __eq__, __hash__ 에 대해 설명해 주세요. 두 메소드를 모두 구현할 때, 어떤 점을 주의해야 할까요?
  • Memory leak 을 유발하는 python 코딩 패턴의 사례를 말씀해주세요.
  • yield 키워드의 역할에 대해 설명해주세요.
  • Global Interperter Lock 에 대해 설명해주세요.

Node.js

  • Promise 에 대해 설명해 보세요.
  • Typescript 의 type 과 interface 의 공통점 및 차이점을 설명해 보세요.
  • Typescript 의 interface 의 특징? 컴파일 이후에는 어떻게 되는지 말씀해주세요.
  • Javascript 와 Java 의 차이를 우리 할머니도 알아들으실 수 있도록 설명해주실 수 있습니까?
  • Map 의 키로 number, string 대신 object 를 쓰고 싶다면, 어떤 점을 고려해야 합니까?
  • Prototype 기반 상속과 일반적인 OOP 에서의 상속은 어떤 차이가 있습니까?

 

Android

  • 비동기로 처리한 작업을 UI 에 표시하기 위해 어떤 일이 필요한지 설명해주세요.
  • 안드로이드 Activity 처리 결과를 다루는 onActivityResult` 메소드는 왜 deprecated 처리되었을까요?
  • ViewGroup 내에 선언한 View 들에 onClickListener 를 선언할 경우 안드로이드가 이벤트를 어떻게 핸들링하는지 설명해 주시기 바랍니다.
  • systrace 가 뭐고, 결과 분석은 어떻게?
  • Memory leak 을 유발하는 coding pattern?
  • Dagger 를 왜 쓸까요? 다른 대안은 없나요?
  • Android HAL(Hardware Abstraction Layer) 에 대해 설명해주세요.

ios

  • 비동기로 처리한 작업을 UI 에 표시하기 위해 어떤 일이 필요한지 설명해주세요.

Web

  • 비동기로 처리한 작업을 UI 에 표시하기 위해 어떤 일이 필요한지 설명해주세요.
  • DOM 의 class 와 id 의 차이?
  • Event bubbling 과 Event capturing 에 대해 설명해주세요.
  • 웹 UI 프레임워크들은 SPA 로 개발하는게 2022년 현재 대세인데 native app 에서는 그런 방식이 일반적이지 않다. 왜 그럴까요?
  • flutter/RN 이 제공하는 hot reload 와 hot restart(live reload) 의 차이에 대해 설명해주세요.
  • React 를 이용해 구현한 SPA 의 SEO 경험을 공유해주세요.
728x90
반응형
728x90
반응형

** 추가 내용이 있을 경우 지속적으로 업데이트 되는 게시글입니다.

 

TCP ? 

  • Transmission Control Protocol
  • RFC 793
 

RFC 793 - Transmission Control Protocol

 

datatracker.ietf.org

 

  • 등장 배경

헤시넷 참조

 


 

참조 자료 링크

728x90
반응형
728x90
반응형

목적

  • Linux -> Linux, Linux -> Windows, Windows -> Linux등 여러 운영체제(서버) 간의 파일 전송

 

윈도우에서  OpenSSH 설치 확인하기

  • OpenSSH Client 기능 활성화 확인 

1. 윈도우 키 -> 앱 및 기능 검색 후 엔터 -> 선택적 기능 클릭

&nbsp;

2. openssh 검색

** 설치되지 않았을 경우 아래 링크 참조

https://docs.microsoft.com/ko-kr/windows-server/administration/openssh/openssh_install_firstuse

 

OpenSSH 설치

Windows용 OpenSSH 클라이언트 및 서버를 설치합니다.

docs.microsoft.com


 

리눅스에서 SCP 설치 확인하기

  • scp 설치 확인 : scp 명령어 입력해보기
  • scp 설치
# Ubuntu
sudo apt-get install openssh-server -y

# cent
yum -y install openssh-server openssh-clients

 

윈도우에서 SCP 사용하기

  • 윈도우에서 리눅스로 파일 보내기
scp '윈도우 파일 경로' '리눅스 계정@리눅스 서버:리눅스 디렉토리 경로'

ex)
scp c:\users\hwan\desktop\test.txt linux_user@192.168.0.0:/home/linux_user/Desktop

 

  • 윈도우에서 리눅스에 있는 파일 가져오기
scp '리눅스 계정@리눅스 서버 주소:리눅스 파일 경로' '윈도우 디렉토리 경로' 

ex)
scp linux_user@192.168.0.0:/home/linux_user/Desktop/test.txt c:\users\hwan\desktop\

 

리눅스에서 SCP 사용하기

  • 리눅스에서 윈도우로 파일 보내기 (윈도우에 ssh 서비스가 실행중이라고 가정)
scp '리눅스 파일 경로' '윈도우 계정@윈도우 IP : 디렉토리 경로' 

ex)
scp /home/user/file.txt hwan@x.x.x.x:/c:\users\hwan\desktop\

** 윈도우에서 서비스 실행은 아래 링크 참조

https://superuser.com/questions/414803/how-to-scp-from-linux-server-to-windows-client

 

How to SCP from Linux server to Windows client

I'm SSHing into a Linux machine using PuTTY and trying to copy a file down somewhere (anywhere) to my local machine. I figure SCP is the best candidate for the job but don't really care, so long as...

superuser.com

 

  • 리눅스에서 윈도우 파일 가져오기
scp '윈도우 계정@윈도우 IP : 파일 경로' '리눅스 디렉토리 경로' 

ex)
scp hwan@x.x.x.x:/c:\users\hwan\desktop\file.txt /home/user/

 

정리

  • scp는 콘솔에서 서버로의 파일 송수신을 도와주는 도구이다.
  • scp의 사용을 위해서는 openssh가 설치되어 있어야하며, 서버에서는 ssh 서비스가 실행 중이어야 한다.
  • 위 조건이 만족되면 운영체제에 상관없이 파일의 송수신이 가능하다.
# 명령어는 클라이언트에서 실행

# 클라이언트에서 서버로 파일 보내기
scp '클라이언트 내부의 파일 위치' '유저명@서버주소:파일이 위치할 서버 내부의 경로'

# 서버에서 클라이언트로 파일 가져오기
scp '유저명@서버주소:서버 내부의 파일 위치' '파일이 위치할 클라이언트 내부의 경로'

 

728x90
반응형
728x90
반응형

개요

  • Dorker와 Django를 사용하여 Web 서버를 구축한다.
  • 집에 있는 장비를 활용하여 서버를 구축하고 Django 공부한다.
  • 만들어진 Docker 이미지를 AWS에 이식하고 남는 장비는 포맷 후 보관한다.

구성

  • OS : 우분투 20.04 LTS
  • 도메인 : iptime 공유기 도메인 등록 후 사용
  • 장비 : 남는 노트북 활용

macbook air 2010


집에서 로컬 웹 서버 구축하기

각 항목들은 아래 링크의 글에 설명되어 있다.

 

  • Ubuntu 20.04 LTS 설치 및 설정

리눅스 서버 설치 및 설정 : 

 

  • Docker 설치하고 사용하기

도커 설치 : https://hwan001.tistory.com/180

도커 사용 : https://hwan001.tistory.com/184

 

  • Django 설치

Django 설치 : https://hwan001.tistory.com/186

 

  • 공유기 도메인 등록 및 보안 설정

iptime 공유기 무료 도메인 등록 및 설정 방법 : 

ssh 접속 포트 변경 : https://hwan001.tistory.com/182

 

  • 우분투 컨테이너로 Django 웹 서버 구축 후 hub 배포

우분투 컨테이너에서 Django 띄우기 : https://hwan001.tistory.com/193

 

  • 도메인 구매, 적용

hosting.kr 구매 및 도메인 적용 후기 : 

 

  • AWS, Docker, Django 서버 열기

AWS 구매 :

AWS에 Docker 환경 설정 :

 


 

728x90
반응형
728x90
반응형

1. 문제

https://www.acmicpc.net/problem/10773

 

10773번: 제로

첫 번째 줄에 정수 K가 주어진다. (1 ≤ K ≤ 100,000) 이후 K개의 줄에 정수가 1개씩 주어진다. 정수는 0에서 1,000,000 사이의 값을 가지며, 정수가 "0" 일 경우에는 가장 최근에 쓴 수를 지우고, 아닐 경

www.acmicpc.net


2. 접근 방식

  • Stack 활용

3. 코드

#include <iostream>
#include <stack> 

using namespace std;

int main() {
    int test_case, tmp, sum=0;
    cin >> test_case;

    stack<int> stack_zero;

    for (int i = 0; i < test_case; i++) {
        cin >> tmp;
        if (tmp==0) {
            stack_zero.pop();
        }
        else {
            stack_zero.push(tmp);
        }
    }
    
    while (!stack_zero.empty()) {
        sum += stack_zero.top();
        stack_zero.pop();
    }

    cout << sum << "\n";
    
    return 0;
}

4. 결과

 

728x90
반응형
728x90
반응형

1. 문제

https://www.acmicpc.net/problem/15829

 

15829번: Hashing

APC에 온 것을 환영한다. 만약 여러분이 학교에서 자료구조를 수강했다면 해시 함수에 대해 배웠을 것이다. 해시 함수란 임의의 길이의 입력을 받아서 고정된 길이의 출력을 내보내는 함수로 정

www.acmicpc.net


 

2. 접근 방식

  • 1차 : 문제에서 알려준 공식대로 구현 -> 50점, 작은 문자열에서는 잘 동작하지만 큰 문자열에서는 시간초과
  • 2차 :  합동식 활용 A * B mod C -> (A mod C) * (B mod C) -> 통과

 

3. 코드

  • 1차 코드
#include<iostream>
#include <cmath> 

typedef unsigned long long ll;

using namespace std;

int main() {
    int str_len;
    cin >> str_len;
    string str;
    cin >> str;

    int a, r = 31, M = 1234567891;
    ll sum = 0;

    for (int i = 0; i < str_len; i++) {
        a = (str[i] - 'a') + 1;
        sum += a * pow(r, i);
    }

    cout << sum % M << "\n";
}
  • 2차 코드
#include<iostream>

using namespace std;

typedef unsigned long long ll;

int main() {
    int str_len;
    cin >> str_len;

    string str;
    cin >> str;

    ll r, sum = 0, a;
    int M = 1234567891;

    for (int i = 0; i < str_len; i++) {
        a = (str[i] - 'a') + 1;

        r = 1;
        for (int j = 0; j < i; j++) {
            r *= 31;
            r %= M;
        }

        sum += a * r;
        sum %= M;
    }
    
    cout << sum;
}

 

4. 결과

728x90
반응형
728x90
반응형

1. 문제

https://www.acmicpc.net/problem/18111

 

18111번: 마인크래프트

팀 레드시프트는 대회 준비를 하다가 지루해져서 샌드박스 게임인 ‘마인크래프트’를 켰다. 마인크래프트는 1 × 1 × 1(세로, 가로, 높이) 크기의 블록들로 이루어진 3차원 세계에서 자유롭게

www.acmicpc.net


2. 접근 방식

  • 1차 : 전체 블록의 평균(높이)을 구해서 해당 높이까지 블록을 맞춰주는 로직 작성 -> 틀림
  • 2차 : 0~가장 큰 높이의 블록을 기준으로 각 케이스를 계산하여 가장 시간이 빠른 경우 선택 -> 1%에서 틀림
  • 3차 : 위와 동일하지만 블록을 먼저 다 회수하고 설치 진행 -> 시간초과
  • 4차 : 제거할 블록과 쌓을 블록의 개수를 구하고 시간을 나중에 구함 -> 통과

3. 반례

// 1 64
3 4 1
64 64 64 64
64 64 64 64
64 64 64 63

// 22 63
3 4 0
64 64 64 64
64 64 64 64
64 64 64 63

// 2 0
3 4 99
0 0 0 0
0 0 0 0
0 0 0 1

// 2 1
1 3 68
0 0 1

// 250 35
3 4 11
29 51 54 44
22 44 32 62
25 38 16 2

// 355 32 
4 4 36
15 43 61 21
19 33 31 55
48 63 1 30
31 28 3 8

// 0 0
1 1 0
0

// 768 128
2 2 0
256 256
0 0

// 879 10
7 7 6000
30 21 48 55 1 1 4
0 0 0 0 0 0 0
15 4 4 4 4 4 8
20 40 60 10 20 30 2
1 1 1 1 1 1 9
24 12 33 7 14 25 3
3 3 3 3 3 3 32

// 350 40
2 2 35
20 10
190 40

// 290 170
2 2 68
120 90
250 170

 


4. 코드

  • 1차 코드 : 동일한 시간일 경우 높은 높이 조건을 충족하지 못함. ( + 틀린 케이스 존재)
#include<iostream>
#include<cmath>

using namespace std;

int main() {
    int n, m, inventory, height, time = 0;
    double sum = 0;

    cin >> n >> m >> inventory;

    // 맵 입력
    int** map = new int*[n];
    for (int i = 0; i < n; i++) {
        map[i] = new int[m];
        for (int j = 0; j < m; j++) {
            cin >> map[i][j];
            sum += map[i][j];
        }
    }

    // 전체 높이 결정 (인벤토리 기준)
    if (inventory > 0) {
        height = round(sum / (n * m));
    }
    else {
        height = floor(sum / (n * m));
    }
    
    // 땅 다듬기
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (map[i][j] == height)
                continue;

            if (map[i][j] > height) {
                time += 2;
                map[i][j] -= 1;
                inventory++;
            }
            else {
                time += 1;
                map[i][j] += 1;
                inventory--;
            }

        }
    }

    cout << time << " " << height << "\n";
    
    return 0;
}

 

  • 2차 코드 : 틀린 케이스 존재 (앞에부터 가져와서 쌓기 때문에 블록이 부족한 경우 발생)
#include<iostream>
#include<cmath>

using namespace std;

// 현재 맵에서 입력된 높이까지 얼마의 시간이 걸리는지 반환
int func_18111_getTime(int height, int n, int m, int inventory, int **map) {
    int time = 0, tmp_map;
    bool flag = true;

    // map 전체 스캔
    for (int i = 0; i < n && flag; i++) {
        for (int j = 0; j < m && flag; j++) {
            tmp_map = map[i][j];

            if (tmp_map == height)
                continue;
			
            // 현재 블록의 높이가 원하는 높이보다 높으면 블록 회수
            if (tmp_map > height) {
                while (tmp_map != height) {
                    time += 2;
                    tmp_map -= 1;
                    inventory++;
                }
            }
            else {
                // 블록 설치 (인벤토리가 부족하면 flag == false
                while (tmp_map != height) {
                    if (inventory > 0) { 
                        inventory--; 
                    }
                    else {
                        flag = false;
                    }

                    if (!flag) 
                        break;

                    time += 1;
                    tmp_map += 1;
                }

                if (!flag || tmp_map != height) {
                    flag = false;
                    break;
                }
            }

        }
    }
    
    // flag 가 false 면 time 초기화
    if (!flag) {
        time = 0;
    }

    return time;
}

int main() {
    int n, m, inventory, height=-1, time = 0, tmp, min = 2100000000, max=0;
    double sum = 0;

    cin >> n >> m >> inventory;

	// 맵 정보 입력 및 블록 최대값 구하기
    int** map = new int* [n];
    for (int i = 0; i < n; i++) {
        map[i] = new int[m];
        for (int j = 0; j < m; j++) {
            cin >> map[i][j];
            if (max < map[i][j]) {
                max = map[i][j];
            }
        }
    }
    
    // 0 ~ 블록 최대 값 중 시간이 가장 빠르고, 높이가 높은 값 찾기
    for (int i = 0; i <= max; i++) {
        tmp = func_18111_getTime(i, n, m, inventory, map);

        if (min >= tmp && tmp > 0) {
            if (min == tmp && height > i) continue;
            min = tmp;
            height = i;
        }
    }

    // 찾을 수 없으면 0으로 초기화
    if (min == 2100000000 || height == -1) {
        min = 0;
        height = 0;
    }
    
    cout << min << " " << height << "\n";
    
    return 0;
}

 

  • 3차 코드 : 입력 높이(height)보다 높은 블록들 먼저 회수하고, 낮은 블록 쌓기
#include<iostream>
#include<cmath>

using namespace std;

int func_18111_getTime(int height, int n, int m, int inventory, int **map) {
    int time = 0, tmp_map;
    bool flag = true;

    // 블록 회수 (높이 낮추기)
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            tmp_map = map[i][j];

            if (tmp_map == height)
                continue;
            
            if (tmp_map > height) {
                while (tmp_map != height) {
                    time += 2;
                    tmp_map -= 1;
                    inventory++;
                }
            }
        }
    }
    
    // 블록 설치 (부족하면 flag == false)
    for (int i = 0; i < n && flag; i++) {
        for (int j = 0; j < m && flag; j++) {
            tmp_map = map[i][j];

            if (tmp_map == height)
                continue;

            if (tmp_map < height) {
                while (tmp_map != height) {
                    if (inventory > 0) {
                        inventory--;
                    }
                    else {
                        flag = false;
                    }

                    if (!flag)
                        break;

                    time += 1;
                    tmp_map += 1;
                }

                if (!flag || tmp_map != height) {
                    flag = false;
                    break;
                }
            }
        }
    }

    if (!flag) {
        time = 0;
    }

    return time;
}

int main() {
    int n, m, inventory, height=-1, time = 0, tmp, min = 2100000000, max=0;
    double sum = 0;

    cin >> n >> m >> inventory;

    int** map = new int* [n];
    for (int i = 0; i < n; i++) {
        map[i] = new int[m];
        for (int j = 0; j < m; j++) {
            cin >> map[i][j];
            if (max < map[i][j]) {
                max = map[i][j];
            }
        }
    }
    
    for (int i = 0; i <= max; i++) {
        tmp = func_18111_getTime(i, n, m, inventory, map);

        if (min >= tmp && tmp > 0) {
            if (min == tmp && height > i) continue;
            min = tmp;
            height = i;
        }
    }

    if (min == 2100000000 || height == -1) {
        min = 0;
        height = 0;
    }
    
    cout << min << " " << height << "\n";
    
    return 0;
}

 

  • 4차 코드 : 통과
#include<iostream>
#include<cmath>

using namespace std;

int main() {
    int n, m, inventory, min = 2100000000, max = 0;
    int height = -1, time = 0, tmp_block, time_min= 2100000000;
    double sum = 0;

    cin >> n >> m >> inventory;

    // 맵 입력
    int** map = new int* [n];
    for (int i = 0; i < n; i++) {
        map[i] = new int[m];
        for (int j = 0; j < m; j++) {
            cin >> map[i][j];

            if (max < map[i][j]) {
                max = map[i][j];
            }

            if (min > map[i][j]) {
                min = map[i][j];
            }
        }
    }

    int build_block, remove_block;

    // 맵의 최소 블록 높이부터 가장 높은 블록까지 반복
    for (int h = min; h <= max; h++) {
        build_block = 0;
        remove_block = 0;

        // h에서의 회수할 블록, 설치할 블록 개수 구하기
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                tmp_block = map[i][j];

                // 현재 블록이 h보다 낮으면 설치할 블록 개수 누적
                if (h > tmp_block) {
                    build_block += h - tmp_block;
                }

                // 현재 블록이 h 보다 높으면 회수할 블록 개수 누적
                if (h < tmp_block) {
                    remove_block += tmp_block - h;
                }
            }
        }

        // 설치할 블록 개수가 인벤토리와 회수한 블록의합보다 부족한지 검사
        if (build_block <= remove_block + inventory) {
            time = remove_block * 2 + build_block;

            if (time_min >= time) {
                if (height > h) continue;
                time_min = time;
                height = h;
            }
        }
    }

    cout << time_min << " " << height << "\n";
    
    return 0;
}

5. 결과

728x90
반응형
728x90
반응형

** 추가 내용이 있을 경우 지속적으로 업데이트 되는 게시글입니다.

 

FTP ?

  • File Transfer Protocol 약어
  • TCP/IP 기반의 응용 프로토콜로 서버와 클라이언트 간의 파일 전송을 위해 고안됨
  • 크게 2개의 연결 종류가 있음 (명령 연결, 데이터 전송용 연결)
  • 위키피디아 링크
  • RFC 114 (1971년 4월) : 최초의 FTP (CNP 기반?)
  • RFC 765 (1980년 6월) : TCP/IP 버전
 

RFC 765 - File Transfer Protocol specification

 

datatracker.ietf.org

  •  RFC 959 (1985년 10월) : 현재 사양의 FTP
 

RFC 959 - File Transfer Protocol

 

datatracker.ietf.org

  • RFC 1579 (1994년 2월) : RFC 959의 방화벽 친화 FTP (수동 모드)
 

RFC 1579 - Firewall-Friendly FTP

 

datatracker.ietf.org

  • RFC 2228 (1997년 6월) : 보안 확장
 

RFC 2228 - FTP Security Extensions

 

datatracker.ietf.org

  • RFC 2428 (1998년 9월) : IPv6 지원
 

RFC 2428 - FTP Extensions for IPv6 and NATs

 

datatracker.ietf.org

 


 

프로토콜 구조

  • Active Mode와 Passive Mode

Active Mode와 Passive Mode

  • FTP 구조
    FTP는 TCP기반의 응용 프로토콜로 이더넷 헤더 + IP 헤더 + TCP 헤더 + FTP 데이터 로 이루어져 있음

 

 


 

FTP 보안 문제

 

RFC 2577 - FTP Security Considerations

 

datatracker.ietf.org

 

 

 

 

- FTPS : File Transfer Protocol Secure

- SSH : Secure SHelll

- SFTP : SSH File Transer Protocol

 

728x90
반응형
728x90
반응형

1. 문제

https://www.acmicpc.net/problem/1009

 

1009번: 분산처리

입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트 케이스에 대해 정수 a와 b가 주어진다. (1 ≤ a < 100, 1 ≤ b < 1,000,000)

www.acmicpc.net


2. 접근 방식

  • mod연산의 성질을 통해 큰 제곱수를 연산하지 않고 mod 값을 알아냄
  • 빠른 모듈로 거듭제곱법을 적용함

3. 코드

#include <iostream>
#include <vector>

using namespace std;

typedef unsigned long long ll;

int func_1009_mod(int a, int b) {
    vector<int> tmp, tmp2;
    int *x;
    ll res = 1;

    while(b!=0) {
        tmp.push_back(b % 2);
        b /= 2;
    }

    x = new int[21];
    x[0] = a % 10;
    for (int j = 1; j <= 20; j++) {
        x[j] = (x[j-1] * x[j - 1]) % 10;
    }

    for (int i = 0; i < tmp.size(); i++) {
        if (tmp.at(i) == 1) {
            res *= x[i];
        }
    }

    if (res % 10 == 0) res = 10;
    else res %= 10;
    
    return res;
}

int main() {
    int n, a, b;
    cin >> n;

    for (int i = 0; i < n; i++) {
        cin >> a >> b;
        cout << func_1009_mod(a, b) << "\n";
    }
    
    return 0;
}

4. 결과

  • C++로 구현시 큰 수를 변수 하나로 처리하기 어려워 다른 방법을 찾아야했지만, 파이썬을 활용하면 Pow 연산만으로 결과를 구할 수 있음
  • 파이썬 활용하면 좋은 문제인듯함

 

728x90
반응형
728x90
반응형

1. UI/ XML

<Window x:Class="youtube_viewer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:youtube_viewer"
        mc:Ignorable="d"
        Title="YouTube Player" Height="500" Width="800"
        Background="#FFE5E5E5"
        >

    <Grid Name="GridViewer">
        <Grid.RowDefinitions>
            <RowDefinition Height="215*"/>
            <RowDefinition Height="27*"/>
        </Grid.RowDefinitions>

        <Grid Margin="0,3,0,0" Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="677*"/>
                <ColumnDefinition Width="123*"/>
            </Grid.ColumnDefinitions>

            <Button Name ="btn_play" Margin="5,10,10,10" Content="Play" Click="btn_play_Click" Grid.Column="1"/>
            <TextBox Name="txtbox_url" Margin="10,10,5,10" Grid.Column="0" TextWrapping="Wrap" Text="Input youtube url" Grid.ColumnSpan="1"/>
        </Grid>
    </Grid>
</Window>

2. C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace youtube_viewer
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        CefSharp.Wpf.ChromiumWebBrowser _browser;
        string str;

        public MainWindow()
        {
            InitializeComponent();

            _browser = new CefSharp.Wpf.ChromiumWebBrowser();
            GridViewer.Children.Add(_browser);
        }

        private void btn_play_Click(object sender, RoutedEventArgs e)
        {
            str = txtbox_url.Text.Split('=')[1].Split('&')[0];

            if (this._browser != null)
            {
                _browser.Address = $"https://www.youtube-nocookie.com/embed/{str}";
            }
        }
    }
}

3. Nuget

cef.redist.x64

728x90
반응형

+ Recent posts