본문:

Python에서 모듈을 import할 때, 시스템은 해당 모듈의 위치를 찾기 위해 경로를 검색합니다. 경로를 올바르게 설정하지 않으면 모듈을 찾을 수 없는 오류가 발생할 수 있습니다. 이러한 상황에서는 모듈의 경로를 확인하고 필요한 경로를 추가하는 방법을 알아야 합니다. 이번 글에서는 이와 관련된 방법에 대해 알아보겠습니다.

1. 모듈 경로 확인하기

Python에서 모듈의 경로를 확인하는 방법은 sys 모듈의 path 속성을 이용하는 것입니다. sys.path는 리스트 형태로 현재 사용 중인 Python 인터프리터가 모듈을 검색하는 경로들을 담고 있습니다. 이를 출력하여 확인해볼 수 있습니다. 아래는 이를 수행하는 예제 코드입니다:

import sys

print(sys.path)

위 코드를 실행하면 Python 인터프리터가 사용하는 경로들이 출력됩니다. 이를 통해 모듈을 검색하는 기본 경로를 확인할 수 있습니다.

2. 경로 추가하기

모듈을 검색하는 경로에 직접 경로를 추가하려면 sys.path 리스트에 경로를 추가하면 됩니다. sys.path 리스트의 첫 번째 요소로 현재 디렉토리가 자동으로 포함되어 있습니다. 그 외에 추가로 경로를 추가해야 하는 경우에는 다음과 같이 수행할 수 있습니다:

import sys

# 경로 추가
sys.path.append("/path/to/module")

# 경로 확인
print(sys.path)

위 예제 코드에서 "/path/to/module" 부분은 실제 모듈이 위치한 디렉토리 경로로 대체되어야 합니다. 경로를 추가한 후에는 해당 경로에서 모듈을 검색할 수 있게 됩니다.

3. 특정 기능만 가져오기

만약 모듈에서 특정한 함수나 변수만 사용하고 싶다면, import문을 다음과 같이 작성할 수 있습니다:

from 모듈명 import 기능명

위 예제에서 모듈명은 가져올 모듈의 이름이고, 기능명은 가져올 함수나 변수의 이름입니다. 예를 들어, math 모듈에서 sqrt 함수만 사용하고 싶다면 다음과 같이 작성할 수 있습니다:

from math import sqrt

이제 sqrt 함수를 직접 사용할 수 있습니다.

3. 모듈에 별칭(alias) 붙이기

가끔 모듈의 이름이 길거나 중복되는 경우가 있습니다. 이럴 때는 모듈에 별칭(alias)을 붙여 사용할 수 있습니다. import문을 다음과 같이 작성하면 모듈에 별칭을 지정할 수 있습니다:

import 모듈명 as 별칭

위 예제에서 모듈명은 가져올 모듈의 이름이고, 별칭은 모듈에 지정할 별칭입니다. 예를 들어, numpy 모듈을 가져올 때 np라는 별칭을 사용하고 싶다면 다음과 같이 작성할 수 있습니다:

import numpy as np

이제 np 별칭을 통해 numpy 모듈의 기능을 사용할 수 있습니다.

Splunk SOAR(이하 Phantom 으로 지칭) 에서 제공하는 AWS 관련 app을 보면 아래와 같이 2가지 방법으로 Phantom 과 AWS를 연결할 수 있다.

첫번째, Access Key / Secret Key 를 입력하는 방법.

두번재, EC2에서 현재 Phantom 을 실행할때 연결된 role 을 사용하는 방법.

위 두가지 방법 중 두번째 방법을 보면 체크 박스에 체크를 하는것만으로도 AWS App 의 Test connectivity 가 정상적으로 Pass가 되는걸 볼수가 있다. (Phantom이 EC2에 실행이 되어야 하고 role을 사용해야 함.) 어떻게 key 또는 ID / PWD가 없이 연결이 되는거지? 라는 의문이 들었다. 해당 의문에 대해서는 다음과 같은 사이트에서 이해할 수 있었다. (https://cloudguardians.medium.com/ec2-instance-metadata-보안-edd23f56b64c)

메타데이터를 이용해 EC2에 대한 정보를 가져올수가 있는데 아래와 같이 curl을 던지면 사용 가능한 meta-data정보 리스트를 확인해볼수 있다.

/iam/security-credentials/ 정보를 체크해보면

해당 Phantom이 설치된 EC2 인스턴스는 bob_role이라는 role을 사용하고 있다는걸 알수 있다. bob_role 를 통해 임시보안자격증명을 하려면 아래와 같이 임시로 쓸수 있는 key와 만료시간을 전달받을 수가 있다.


임시로 쓰는 키지만…다 보여드리기 기분이 좀 그래서 가림..ㅎㅎ
다시 돌아와 Phantom app 에서 use_role을 체크한다면 아래와 같은 boto3를 이용한 소스가 실행되 key 값을 받게된다.

from boto3 import Session, client, resource

if config.get('use_role'):
		credentials = self._handle_get_ec2_role()
		if not credentials:
		    return self.set_status(phantom.APP_ERROR, EC2_ROLE_CREDENTIALS_FAILURE_MSG)
		self._access_key = credentials.access_key
		self._secret_key = credentials.secret_key
		self._session_token = credentials.token
		
		return phantom.APP_SUCCESS
	
self._access_key = config.get(EC2_JSON_ACCESS_KEY)
self._secret_key = config.get(EC2_JSON_SECRET_KEY)

def _handle_get_ec2_role(self):
	  session = Session(region_name=self._region)
	  credentials = session.get_credentials()
	  return credentials

하지만 현재 사용하고 있는 role 이 아닌 다른 role 접근을 하려면 STS를 사용해야 한다.우선 권한이 필요하다. (https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/id_credentials_temp_control-access_enable-create.html) bob_role 에서 bob_role2 연결을 하려면 아래와 같은 권한이 필요하다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com",
                "AWS": "arn:aws:iam::[bob Account]:role/bob_role"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

권한 부여가 되었으면 python에서 STS를 사용하면 된다.

def _assume_a_role(self, param):
		boto_config = None
		if self._proxy:
		    boto_config = Config(proxies=self._proxy)
		
		self.debug_print("Creating boto3 STS client assuming given role")
		sts_client = client(
		    'sts',
		    region_name=self._region,
		    aws_access_key_id=self._access_key,
		    aws_secret_access_key=self._secret_key,
		    aws_session_token=self._session_token,
		    config=boto_config)
		response = sts_client.assume_role(
		    RoleArn=param['role_arn'],
		    RoleSessionName="AssumeRoleSession2"
	)
	# self._access_key = response['Credentials']['AccessKeyId']
	# self._secret_key = response['Credentials']['SecretAccessKey']
	# self._session_token = response['Credentials']['SessionToken']
	return response['Credentials']


# 사용 예시
if param and 'role_arn' in param:
		try:
		    temp_credentials = self._assume_a_role(param) # ast.literal_eval(param['credentials'])
		    self._access_key = temp_credentials.get('AccessKeyId', '')
		    self._secret_key = temp_credentials.get('SecretAccessKey', '')
		    self._session_token = temp_credentials.get('SessionToken', '')
		
		    self.save_progress("Using temporary assume role credentials for action")
		except Exception as e:
		    return action_result.set_status(phantom.APP_ERROR,
		                                    "Failed to get temporary credentials:{0}".format(e))

 

실행 결과

Status : success 가 나오는걸 확인할 수 있다.

Phantom의 AWS 관련 앱에서 어떻게 key가 없이 연결이 되는지 라는 물음에서 많은 공부가 되었다. 해당 문제를 해결하려면 기본적인 AWS IAM 을 이해해야 해서 관련 문서를 보면 많은 도움이 된다.

잘못되거나 수정해야 할 내용이 있으면 알려주길 바란다.

안녕하세요! 여러분에게 저의 최근 'snowpro core certification' 시험 경험을 소개하려 합니다.

Pearson VUE를 통해 Snowflake Core 시험은 온라인 또는 오프라인으로 응시할 수 있습니다. 저는 온라인 시험의 경우 외국인 감독관이 확인하는 것으로 들었기에(확실한 정보는 아니었습니다만), 선호하는 오프라인 시험을 선택했습니다. 지난주인 6월 8일, 목요일에 학동에 위치한 ETEVERS에서 시험을 보았습니다.

결제를 하고 이메일을 꼭 확인해야 한다.

시험은 총 100문제로 구성되어 있으며, 공식적인 시험 시간은 115분입니다. 하지만, 비영어권 국가에서 시험을 보는 경우 추가로 30분이 주어져 총 150분 동안 시험을 볼 수 있습니다. 시험 응시료는 175달러로, 약 20만원이라고 할 수 있습니다. (당연히, 한번에 합격해야겠죠..!)


선택 가능한 언어는 영어와 일본어입니다. 아쉽게도 한국어는 제공되지 않습니다. 시험은 총 1000점 만점으로, 750점 이상을 얻어야 합격입니다. 다행히, 저는 한번에 시험에 합격했습니다! 시험을 마치고 나면 모니터에 바로 합격 여부가 나타나고, 시험장을 나와 프론트로 가면 합격 여부 및 점수가 적힌 종이를 받을 수 있습니다.

공부는 처음에는 dumpkorea에서 dump를 구입했습니다. 하지만 첫 문제부터 답이 틀려서 큰 충격을 받았고 거의 50% 이상이 틀리더군요. 이런 상황에서 dump에서 틀린 답을 외울지, examtopics에서 투표로 선택된 답을 외울지 많은 고민을 했습니다. 결국, 시험에 떨어지더라도 올바른 지식을 습득하는 것이 더 중요하다는 결론을 내리고, 총 260개의 문제 중 각각 examtopics에서 찾아 정답을 고쳐 외웠습니다.

그런데 examtopics에 들어가서 전체 문제를 보니 총 650개의 문제가 있고, dump에는 없는 문제가 많았습니다. 이에 dump를 외우는 것을 중단하고, examtopics를 결제한 후에 examtopics의 문제를 3일 동안 미친 듯이 외웠습니다. 
하루에 약 200개씩 외우고, 당일에는 전체 문제를 한 번씩 다시 보는 방법을 사용했습니다.

시험에서는 650개의 문제 이외에도 전혀 처음 보는 문제가 몇 개 나와서 당황스러웠지만 차근차근 풀어보니, 그리 많은 문제를 틀리지 않고 넉넉한 점수로 합격할 수 있었습니다. examtopics에서 특히 400~638 사이의 최근 문제가 비중이 높게 나온 것 같습니다.

국내에서 Snowflake에 관심 있는 사람이 얼마나 될지는 모르겠지만, 파트너나 사용자라면 이론적인 측면에서 Snowflake Core 자격증 공부를 하고, 실습은 Hand-on badge 1~5를 해보는 것이 큰 도움이 될 것 같습니다. 또, 만약 MSSQL 혹은 MySQL과 같은 SQL을 사용해본 경험이 있다면, 이해하기 더 쉬울 것입니다.

그럼 모두 행운을 빕니다!

AWS STS와 Assume Role이란 무엇인가요?

AWS는 클라우드 기술 서비스를 제공하고 있습니다. AWS의 서비스를 사용하면 클라우드에서 간단하고 안전하게 애플리케이션을 실행할 수 있습니다. 그 중 AWS STS와 Assume Role에 대해 알아보겠습니다.

AWS STS란 무엇인가요?

AWS STS(Security Token Service)는 AWS에서 보안 토큰을 생성하는 서비스입니다. AWS STS를 사용하면 AWS IAM 사용자나 AWS 외부 자격 증명을 사용하여 액세스 권한을 부여할 수 있습니다.

AWS STS의 장점

  • AWS STS는 일시적인 보안 자격 증명을 생성하므로 보안성이 높습니다.
  • IAM 사용자 또는 AWS 외부 자격 증명으로 AWS 리소스에 대한 액세스 권한을 제한할 수 있습니다.
  • AWS STS를 사용하면 AWS 리소스에 대한 권한을 부여하는 방법을 보다 더 유연하게 조정할 수 있습니다.

Assume Role이란 무엇인가요?

Assume Role은 AWS IAM에서 지원하는 기능 중 하나입니다. AWS IAM에서 Assume Role을 사용하면 IAM 사용자 또는 AWS 외부 자격 증명으로 다른 AWS 계정 또는 리소스에 액세스할 수 있습니다.

Assume Role의 장점

  • Assume Role을 사용하면 하나의 IAM 사용자 또는 외부 자격 증명을 여러 AWS 계정 또는 리소스에 대해 공유할 수 있습니다.
  • Assume Role을 사용하여 AWS 계정 또는 리소스에 대한 액세스 권한을 조정할 수 있습니다.
  • Assume Role을 사용하면 권한 부여를 간편하게 할 수 있습니다.

AWS STS와 Assume Role을 사용하는 방법

AWS STS와 Assume Role을 사용하는 방법은 다음과 같습니다.

  1. AWS STS를 사용하여 일시적인 자격 증명을 생성합니다.
  2. 생성된 일시적인 자격 증명으로 Assume Role을 호출합니다.
  3. Assume Role이 호출되면, 해당하는 AWS 리소스에 대한 액세스 권한을 부여받게 됩니다.

AWS STS와 Assume Role을 사용하는 이유

AWS STS와 Assume Role을 사용하는 이유는 다음과 같습니다.

  • IAM 사용자나 외부 자격 증명으로 AWS 리소스에 대한 액세스 권한을 부여할 수 있습니다.
  • AWS 리소스에 대한 권한을 더욱 세밀하게 제어할 수 있습니다.
  • 일시적인 자격 증명을 사용하기 때문에 보안성이 높습니다.

AWS STS와 Assume Role을 함께 사용하는 경우

AWS STS와 Assume Role을 함께 사용하면 보다 유연하게 AWS 리소스에 대한 권한을 관리할 수 있습니다. 다음은 AWS STS와 Assume Role을 함께 사용하는 경우입니다.

  1. AWS STS를 사용하여 일시적인 자격 증명을 생성합니다.
  2. Assume Role을 호출하고 생성된 일시적인 자격 증명을 사용하여 IAM 사용자나 외부 자격 증명으로 다른 AWS 계정 또는 리소스에 액세스합니다.

AWS STS와 Assume Role의 보안

AWS STS와 Assume Role은 일시적인 자격 증명을 사용하여 AWS 리소스에 대한 액세스 권한을 부여합니다. 이러한 일시적인 자격 증명은 만료되므로 보안성이 높습니다. 또한 AWS STS와 Assume Role을 사용하면 권한 부여를 보다 세밀하게 제어할 수 있으므로 보안성이 더욱 강화됩니다.

AWS STS와 Assume Role의 사용 사례

AWS STS와 Assume Role은 다양한 사용 사례를 가지고 있습니다. 예를 들어, 다음과 같은 경우에 AWS STS와 Assume Role을 사용할 수 있습니다.

  • 여러 AWS 계정 간의 권한 부여
  • AWS 리소스에 대한 세밀한 권한 부여
  • 일시적인 자격 증명을 사용하여 보안성 강화

결론

AWS STS와 Assume Role은 AWS에서 제공하는 보안 기능 중 하나입니다. 이러한 기능을 사용하면 AWS 리소스에 대한 액세스 권한을 보다 유연하게 관리할 수 있습니다. 또한 보안성을 강화하기 위한 일시적인 자격 증명을 사용하여 권한 부여를 할 수 있습니다.

FAQ

AWS STS와 Assume Role을 사용하는 이유는 무엇인가요?

  • AWS STS와 Assume Role을 사용하면 IAM 사용자나 외부 자격 증명으로 AWS 리소스에 대한 액세스 권한을 부여할 수 있습니다.
  • AWS 리소스에 대한 권한을 더욱 세밀하게 제어할 수 있습니다.
  • 일시적인 자격 증명을 사용하기 때문에 보안성이 높습니다.

AWS STS와 Assume Role을 함께 사용하는 경우는 어떤 경우인가요?

  • AWS STS와 Assume Role을 함께 사용하면 보다 유연하게 AWS 리소스에 대한 권한을 관리할 수 있습니다.

AWS STS와 Assume Role을 사용하면 어떤 보안 이점이 있나요?

  • AWS STS와 Assume Role을 사용하면 일시적인 자격 증명을 사용하여 AWS 리소스에 대한 액세스 권한을 부여합니다.
  • 이러한 일시적인 자격 증명은 만료되므로 보안성이 높습니다.
  • 또한 AWS STS와 Assume Role을 사용하면 권한 부여를 보다 세밀하게 제어할 수 있으므로 보안성이 더욱 강화됩니다.

AWS STS와 Assume Role의 사용 사례는 어떤 것이 있나요?

  • 여러 AWS 계정 간의 권한 부여
  • AWS 리소스에 대한 세밀한 권한 부여
  • 일시적인 자격 증명을 사용하여 보안성 강화

AWS STS와 Assume Role은 보안성을 어떻게 강화하나요?

  • 일시적인 자격 증명을 사용하여 AWS 리소스에 대한 액세스 권한을 부여합니다.
  • 권한 부여를 보다 세밀하게 제어할 수 있습니다.

AWS STS와 Assume Role을 사용하는 방법은 어떻게 되나요?

  • AWS STS를 사용하여 일시적인 자격 증명을 생성합니다.
  • 생성된 일시적인 자격 증명으로 Assume Role을 호출합니다.
  • Assume Role이 호출되면, 해당하는 AWS 리소스에 대한 액세스 권한을 부여받게 됩니다.

AWS STS와 Assume Role은 어떤 기능을 제공하나요?

  • AWS STS는 AWS에서 보안 토큰을 생성하는 서비스입니다.
  • Assume Role은 IAM 사용자나 외부 자격 증명으로 다른 AWS 계정 또는 리소스에 액세스할 수 있는 기능입니다.

AWS STS와 Assume Role을 사용하여 어떤 문제를 해결할 수 있나요?

  • AWS 리소스에 대한 액세스 권한을 보다 세밀하게 제어할 수 있습니다.
  • 하나의 IAM 사용자 또는 외부 자격 증명을 여러 AWS 계정 또는 리소스에 대해 공유할 수 있습니다.

AWS STS와 Assume Role을 사용하여 어떤 장점이 있나요?

  • 일시적인 자격 증명을 사용하기 때문에 보안성이 높습니다.
  • AWS 리소스에 대한 권한을 더욱 세밀하게 제어할 수 있습니다.

AWS STS와 Assume Role을 사용하면 어떤 단점이 있나요?

  • 복잡한 권한 관리가 필요할 수 있습니다.
  • 세밀한 권한 부여가 필요한 경우 복잡해질 수 있습니다.

 

## 2023-06-20 내용 추가
저는 AWS와 SOAR 제품 연동을 위해 STS/Assume Role을 사용했는데 위 내용 이외에 개발 관련 내용을 원하시면
아래 링크를 확인부탁드립니다.
https://kyung123a.tistory.com/entry/AWS-%EC%9E%84%EC%8B%9C%EB%B3%B4%EC%95%88%EC%9E%90%EA%B2%A9

'개발' 카테고리의 다른 글

React useEffect 예제  (0) 2023.03.14
code에서 1.1 + 0.1 == 1.2가 다른 이유  (0) 2023.03.14
flex 화면이 레이어 아래로 내려 갈수 있게  (0) 2014.10.08
유용한 사이트 모음  (0) 2014.06.26

React useEffect란 무엇인가요?

React는 UI를 구축하기 위한 JavaScript 라이브러리입니다. useEffect는 React의 라이프사이클 메소드 중 하나로, 컴포넌트가 렌더링될 때마다 특정한 작업을 수행할 수 있도록 해줍니다. 이번 글에서는 React useEffect에 대해 예제와 함께 자세히 설명해보겠습니다.

React의 라이프사이클 메소드

React에서는 라이프사이클 메소드를 사용하여 컴포넌트의 생명주기를 관리합니다. 이 메소드들은 컴포넌트가 생성되고, 업데이트되고, 제거될 때 자동으로 호출됩니다. useEffect는 이러한 라이프사이클 메소드 중 하나이며, 컴포넌트가 렌더링될 때마다 실행됩니다.

useEffect의 기본 사용법

useEffect는 두 개의 매개변수를 받습니다. 첫 번째 매개변수는 함수이며, 두 번째 매개변수는 배열입니다. 함수는 컴포넌트가 렌더링될 때마다 실행되며, 배열에는 useEffect가 의존하는 변수들을 넣습니다.

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

위 예제에서는 버튼을 클릭할 때마다 count가 증가합니다. useEffect는 count가 변경될 때마다 실행되며, 문서의 제목을 업데이트합니
다.

useEffect의 종류

useEffect는 종류에 따라 다양한 방식으로 사용될 수 있습니다. 가장 일반적인 예제는 API 호출과 같은 비동기 작업을 수행할 때 사용하는 것입니다.

componentDidMount 대체하기

import React, { useState, useEffect } from 'react';

function Example() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('/api/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  if (!data) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      {data.map(item => (
        <div key={item.id}>{item.name}</div>
      ))}
    </div>
  );
}

위 예제에서는 API를 호출하여 데이터를 가져오고, 데이터가 없으면 "Loading..."을 표시합니다. 데이터가 있으면 각 항목의 이름을 출력합니다.

componentDidUpdate 대체하기

useEffect를 사용하면 componentDidUpdate를 대체할 수 있습니다. useEffect의 두 번째 매개변수 배열에 상태값을 포함시켜 놓으면 해당 상태값이 업데이트될 때마다 useEffect가 실행됩니다.

` import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('');

  useEffect(() => {
    console.log(`You clicked ${count} times`);
  }, [count]);

  useEffect(() => {
    console.log(`Your name is ${name}`);
  }, [name]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
      <input value={name} onChange={e => setName(e.target.value)} />
    </div>
  );
}

위 예제에서는 count와 name이 변경될 때마다 useEffect가 실행되며, 변경된 값을 console에 출력합니다.

useEffect의 주의사항

useEffect는 컴포넌트가 렌더링될 때마다 실행됩니다. 따라서, 너무 많은 useEffect를 사용하면 애플리케이션의 성능에 영향을 미칠 수 있습니다. 또한, useEffect에서 상태값을 변경하는 경우 무한 루프에 빠질 수 있습니다.

결론

React useEffect는 컴포넌트의 생명주기를 관리하고, 특정 작업을 수행할 수 있도록 해줍니다. 이를 활용하면 비동기 작업이나, componentDidUpdate를 대체할 수 있습니다. 하지만, 주의사항에 유의하여 사용해야 합니다.

FAQ

useEffect는 어떤 상황에서 사용하나요?

  • 컴포넌트가 렌더링될 때마다 실행되는 작업을 수행할 때 사용합니다.

useEffect에서 상태값을 변경하면 어떻게 되나요?

  • 무한 루프에 빠질 수 있으므로, 주의해서 사용해야 합니다.

useEffect 대신 componentDidMount와 componentDidUpdate를 사용해도 되나요?

  • useEffect는 두 메소드를 대체할 수 있습니다.

useEffect에서 API 호출을 어떻게 처리하나요?

  • useEffect 안에서 비동기 작업을 처리하면 됩니다.

useEffect를 사용하면 성능에 영향을 미칠까요?

  • 너무 많은 useEffect를 사용하면 성능에 영향을 미칠 수 있습니다.

'개발' 카테고리의 다른 글

AWS STS와 Assume Role  (3) 2023.03.14
code에서 1.1 + 0.1 == 1.2가 다른 이유  (0) 2023.03.14
flex 화면이 레이어 아래로 내려 갈수 있게  (0) 2014.10.08
유용한 사이트 모음  (0) 2014.06.26

문제의 원인

이 문제는 부동소수점 숫자를 표현하는 방식 때문에 발생합니다. 컴퓨터에서 부동소수점 숫자는 이진수로 표현됩니다. 이진수로 표현된 소수는 종종 무한 소수가 될 수 있기 때문에, 컴퓨터는 이진수에서 유한한 비트 수만큼만 표현합니다.

1.1과 0.1은 이진수로 정확히 표현할 수 없는 무한 소수입니다. 따라서 컴퓨터에서 이 값들은 근사치로 표현됩니다.

따라서 **1.1 + 0.1**은 컴퓨터에서는 **1.2000000000000002**와 같은 값을 가질 수 있습니다. 이는 **1.2**와 같지 않으므로, **1.1 + 0.1 == 1.2**가 False가 됩니다.

해결 방법

이러한 문제를 해결하기 위해, 부동소수점 숫자를 비교할 때는 약간의 오차를 허용해야 합니다. 즉, "1.1 + 0.1이 1.2와 거의 같다"라는 식으로 비교해야 합니다. 일반적으로는 다음과 같은 방법을 사용합니다.

import math

tolerance = 1e-10
if math.isclose(1.1 + 0.1, 1.2, rel_tol=tolerance):
    print("approximately equal")
else:
    print("not approximately equal")

위 코드는 math.isclose()함수를 사용하여 1.1 + 0.11.2가 "거의 같은" 값인지 확인합니다. 이 함수는 두 숫자가 동일하거나(rel_tol=0), 혹은 상대 오차(rel_tol) 혹은 절대 오차(abs_tol) 안에 있는 경우 True를 반환합니다. 위 코드에서는 상대 오차를 사용하여 비교합니다.

'개발' 카테고리의 다른 글

AWS STS와 Assume Role  (3) 2023.03.14
React useEffect 예제  (0) 2023.03.14
flex 화면이 레이어 아래로 내려 갈수 있게  (0) 2014.10.08
유용한 사이트 모음  (0) 2014.06.26

소개

REST API 서버는 최근 웹 개발에서 매우 중요한 역할을 합니다. Python Flask는 간단하고 빠르게 REST API 서버를 만드는 데에 매우 적합한 프레임워크입니다. 이 글에서는 Python Flask를 이용해 REST API 서버를 어떻게 만드는지에 대해 알아보겠습니다.

목차

  1. Flask 소개
  2. REST API란?
  3. Flask로 REST API 서버 만드는 방법
    1. Flask 설치하기
    2. Flask 라우팅
    3. HTTP Methods
    4. JSON 데이터 전송
    5. REST API 응답 처리
    6. 예외 처리
    7. RESTful API
  4. Flask RESTful 사용하기
    1. Flask-RESTful 설치하기
    2. Flask-RESTful Resource
    3. Flask-RESTful Request Parsing
    4. Flask-RESTful Marshmallow
  5. Flask REST API 서버 보안
    1. JWT(Json Web Token) 인증
    2. Flask-HTTPAuth

1. Flask 소개

Flask는 Werkzeug 툴킷과 Jinja2 템플릿 엔진을 기반으로한 마이크로 웹 프레임워크입니다. Flask는 빠르고 간단한 구성과 디자인을 가지고 있습니다. Flask는 확장성과 유연성이 높아서 다양한 기능을 제공하면서도 쉽게 사용할 수 있습니다.

2. REST API란?

REST (Representational State Transfer)는 분산 시스템에서 구현할 수 있는 아키텍처 스타일입니다. REST API는 HTTP 프로토콜을 이용하여 웹 어플리케이션에서 데이터를 주고 받는 방식 중 하나입니다. REST API는 자원(resource)을 정의하고, 자원에 대한 행위(method)를 구분하여 정의합니다.

3. Flask로 REST API 서버 만드는 방법

3.1 Flask 설치하기

Flask를 사용하기 위해서는 우선 Flask를 설치해야 합니다. 가상환경을 이용하는 것을 권장합니다.

    pip install Flask

3.2 Flask 라우팅

Flask에서는 URL 패턴을 사용하여 함수를 연결합니다. 이를 라우팅(Routing)이라고 합니다.

    from flask import Flask

    app = Flask(__name__)

    @app.route('/')
    def index():
        return 'Hello, World!'

3.3 HTTP Methods

HTTP Method는 REST API에서 자원에 대한 행위를 정의합니다. Flask에서는 HTTP Method에 따라 다르게 처리됩니다.

    from flask import Flask, request

    app = Flask(__name__)

    @app.route('/example', methods=['GET'])
    def example():
        return 'GET method'

    @app.route('/example', methods=['POST'])
    def example():
        return 'POST method'

    @app.route('/example', methods=['PUT'])
    def example():
        return 'PUT method'

    @app.route('/example', methods=['DELETE'])
    def example():
        return 'DELETE method'

3.4 JSON 데이터 전송

REST API에서는 데이터를 주고 받을 때 JSON 데이터 형식을 사용하는 것이 일반적입니다. Flask에서는 JSON 데이터를 쉽게 전송할 수 있는 jsonify 함수를 제공합니다.

    from flask import Flask, jsonify, request

    app = Flask(__name__)

    @app.route('/example', methods=['POST'])
    def example():
        data = request.get_json()  # JSON 데이터 받아오기
        result = {'message': 'success'}
        return jsonify(result)

3.5 REST API 응답 처리

REST API에서는 HTTP 상태 코드를 이용하여 응답을 처리합니다. Flask에서는 make_response 함수를 이용하여 HTTP 상태 코드와 함께 응답을 전송할 수 있습니다.

    from flask import Flask, jsonify, make_response

    app = Flask(__name__)

    @app.route('/example', methods=['GET'])
    def example():
        data = {'key': 'value'}
        response = make_response(jsonify(data))
        response.status_code = 200  # HTTP 상태 코드 설정
        return response

3.6 예외 처리

REST API에서는 예외 처리가 매우 중요합니다. Flask에서는 예외 처리를 위해 abort 함수를 제공합니다.

    from flask import Flask, abort

    app = Flask(__name__)

    @app.route('/example/<int:id>', methods=['GET'])
    def example(id):
        if id == 0:
            abort(404)  # 404 에러 발생
        return 'success'

3.7 RESTful API

RESTful API는 REST API의 설계 규칙을 따르는 API를 말합니다. Flask에서는 RESTful API를 쉽게 구현할 수 있도록 Flask-RESTful이라는 확장 모듈을 제공합니다.

4. Flask RESTful 사용하기

4.1 Flask-RESTful 설치하기

Flask-RESTful를 사용하기 위해서는 우선 Flask-RESTful을 설치해야 합니다.

    pip install flask-restful

4.2 Flask-RESTful Resource

Flask-RESTful에서는 Resource 클래스를 이용하여 API를 구현합니다.

    from flask import Flask
    from flask_restful import Api, Resource

    app = Flask(__name__)
    api = Api(app)

    class Example(Resource):
        def get(self):
            return {'message': 'success'}

    api.add_resource(Example, '/example')

4.3 Flask-RESTful Request Parsing

Flask-RESTful에서는 Request Parsing을 지원합니다. Request Parsing을 이용하면 요청한 데이터를 쉽게 받아올 수 있습니다.

    from flask import Flask
    from flask_restful import Api, Resource, reqparse

    app = Flask(__name__)
    api = Api(app)

    parser = reqparse.RequestParser()
    parser.add_argument('name', type=str)

    class Example(Resource):
        def get(self):
            args = parser.parse_args()
            return {'name': args['name']}

    api.add_resource(Example, '/example')

4.4 Flask-RESTful Marshmallow

Flask-RESTful에서는 Marshmallow를 이용하여 데이터 검증 및 직렬화를 수행할 수 있습니다.

    from flask import Flask
    from flask_restful import Api, Resource, reqparse
    from marshmallow import Schema, fields, ValidationError

    app = Flask(__name__)
    api = Api(app)

    class ExampleSchema(Schema):
        name = fields.String(required=True)

        def handle_error(self, error, data):
            raise ValidationError(error, data=data)

    example_schema = ExampleSchema()

    class Example(Resource):
        def post(self):
            json_data = request.get_json()
            try:
                data = example_schema.load(json_data)
            except ValidationError as e:
                return {'message': str(e)}, 400
            return {'name': data['name']}

    api.add_resource(Example, '/example')

5. Flask REST API 서버 보안

5.1 JWT(Json Web Token) 인증

REST API 서버에서는 보안이 매우 중요합니다. JWT(Json Web Token) 인증은 REST API 서버에서 자주 사용되는 인증 방식 중 하나입니다. Flask에서는 PyJWT 라이브러리를 이용하여 JWT 인증을 구현할 수 있습니다.

    import jwt
    from flask import Flask, jsonify, request

    app = Flask(__name__)

    @app.route('/login', methods=['POST'])
    def login():
        username = request.json.get('username')
        password = request.json.get('password')
        if username == 'admin' and password == 'password':
            token = jwt.encode({'username': username}, 'secret', algorithm='HS256')
            return jsonify({'token': token.decode('utf-8')})
        else:
            return jsonify({'message': 'Invalid username or password'}), 401

5.2 Flask-HTTPAuth

Flask-HTTPAuth는 Flask에서 인증 처리를 쉽게 구현할 수 있도록 도와주는 확장 모듈입니다.

    from flask import Flask, jsonify
    from flask_httpauth import HTTPTokenAuth

    app = Flask(__name__)
    auth = HTTPTokenAuth(scheme='JWT')

    @auth.verify_token
    def verify_token(token):
        try:
            data = jwt.decode(token, 'secret', algorithms=['HS256'])
            return data['username'] == 'admin'
        except:
            return False

    @app.route('/example', methods=['GET'])
    @auth.login_required
    def example():
        return jsonify({'message': 'success'})

결론

이 글에서는 Python Flask를 이용하여 REST API 서버를 만드는 방법에 대해 알아보았습니다. Flask를 이용하면 간단하고 빠르게 REST API 서버를 만들 수 있습니다. 또한 Flask-RESTful을 이용하여 RESTful API를 쉽게 구현할 수 있습니다. 마지막으로 JWT 인증과 Flask-HTTPAuth를 이용하여 REST API 서버 보안을 강화할 수 있습니다.

자주 묻는 질문(FAQs)

  1. Python Flask를 이용한 REST API 서버는 무엇인가요?
    • Python Flask를 이용하여
  2. Flask에서 HTTP Method는 어떻게 처리되나요?
    • Flask에서는 HTTP Method에 따라 다르게 처리됩니다. 예를 들어, GET 메소드는 데이터 조회에 사용되고, POST 메소드는 데이터 생성에 사용됩니다.
  3. Flask-RESTful에서 Request Parsing을 어떻게 수행하나요?
    • Flask-RESTful에서는 reqparse 모듈을 이용하여 Request Parsing을 수행합니다. reqparse 모듈을 이용하면 요청한 데이터를 쉽게 받아올 수 있습니다.
  4. Flask-RESTful에서 Marshmallow를 이용하여 무엇을 할 수 있나요?
    • Flask-RESTful에서는 Marshmallow를 이용하여 데이터 검증 및 직렬화를 수행할 수 있습니다. Marshmallow를 이용하면 데이터의 유효성 검사를 쉽게 할 수 있습니다.
  5. JWT 인증은 무엇인가요?
    • JWT(Json Web Token) 인증은 REST API 서버에서 자주 사용되는 인증 방식 중 하나입니다. JWT는 서버에서 발행한 Token을 클라이언트가 저장하고, 이를 이용하여 인증을 수행합니다.

이상으로 Python Flask를 이용한 REST API 서버 만드는 방법에 대해 알아보았습니다. Flask를 이용하면 간단하고 빠르게 REST API 서버를 만들 수 있습니다. 또한 Flask-RESTful을 이용하여 RESTful API를 쉽게 구현할 수 있습니다. 마지막으로 JWT 인증과 Flask-HTTPAuth를 이용하여 REST API 서버 보안을 강화할 수 있습니다.

리스트 컴프리헨션과 for문은 모두 파이썬에서 반복문을 처리하는 방법 중 하나입니다. 그러나 두 가지 방법은 서로 다른 성능 특성을 가지고 있습니다.

일반적으로 리스트 컴프리헨션은 for문보다 더 빠른 실행 속도를 보입니다. 이는 리스트 컴프리헨션은 내부적으로 C 코드로 작성되어 있어 파이썬 인터프리터에서 해석되는 일반적인 for문에 비해 더 빠르기 때문입니다. 또한, 리스트 컴프리헨션은 코드가 더 짧고 간결하며 가독성이 높아 유지 보수가 더 쉽다는 이점도 있습니다.

그러나 리스트 컴프리헨션은 데이터 크기가 매우 큰 경우에는 메모리 사용량이 더 높을 수 있습니다. 리스트 컴프리헨션은 한 번에 모든 데이터를 생성하기 때문에 매우 큰 리스트를 생성하려면 많은 메모리가 필요합니다. 이에 비해 for문은 데이터를 한 번에 하나씩 처리하므로 메모리 사용량이 더 낮습니다.

따라서, 리스트 컴프리헨션과 for문 중 어느 것이 더 나은 방법인지는 상황에 따라 다릅니다. 작은 데이터 크기에서는 리스트 컴프리헨션이 더 나은 선택일 수 있으며, 대규모 데이터에서는 for문이 더 나은 선택일 수 있습니다.

리스트 컴프리헨션과 for문의 성능 비교를 위해 간단한 예제를 작성해보겠습니다. 예제는 1부터 100000까지의 숫자 리스트를 생성하고 각 숫자를 제곱하여 새로운 리스트를 생성하는 것입니다.

리스트 컴프리헨션을 사용한 예제:

import time

start_time = time.time()

num_list = [i**2 for i in range(1, 100001)]

end_time = time.time()
elapsed_time = end_time - start_time
print(f"Elapsed time using list comprehension: {elapsed_time:.5f} seconds")

결과:

Elapsed time using list comprehension: 0.02984 seconds

for문을 사용한 예제:

import time

start_time = time.time()

num_list = []
for i in range(1, 100001):
    num_list.append(i**2)

end_time = time.time()
elapsed_time = end_time - start_time
print(f"Elapsed time using for loop: {elapsed_time:.5f} seconds")

결과:

Elapsed time using for loop: 0.04094 seconds

위의 예제에서는 리스트 컴프리헨션과 for문을 사용하여 같은 작업을 수행합니다. 실행 시간을 측정하면 리스트 컴프리헨션이 약 0.03초, for문이 약 0.04초 걸렸다는 것을 알 수 있습니다. 이 예제에서는 리스트 컴프리헨션이 for문보다 더 빠른 것으로 나타났습니다.

객체지향 프로그래밍(Object-Oriented Programming)은 컴퓨터 프로그래밍 패러다임 중 하나로, 현실 세계를 객체(Object)라는 개념으로 모델링하여 프로그래밍 하는 방법입니다. Python은 객체지향 언어로, 클래스(Class)와 객체(Object)를 중심으로 프로그래밍이 이루어집니다.

클래스(Class)는 객체를 만들기 위한 설계도로, 객체를 만드는데 사용되는 변수와 함수들의 집합입니다. 예를 들어, 동물이라는 클래스를 만들 때, 동물의 특징인 눈, 다리, 꼬리 등의 변수와 움직이기, 먹기 등의 함수를 정의할 수 있습니다.

객체(Object)는 클래스를 기반으로 만들어진 실체입니다. 클래스를 인스턴스화(Instantiate) 하여 객체를 생성하고, 객체는 클래스에서 정의된 변수와 함수를 사용할 수 있습니다. 예를 들어, 동물 클래스를 인스턴스화하여 개, 고양이, 돼지 등의 객체를 생성하고, 이들 객체는 각각 눈, 다리, 꼬리 등의 변수와 움직이기, 먹기 등의 함수를 사용할 수 있습니다.

Python에서 클래스는 다음과 같이 정의됩니다.

class Animal:
    def __init__(self, eyes, legs, tail):
        self.eyes = eyes
        self.legs = legs
        self.tail = tail
        
    def move(self):
        print("I am moving")
        
    def eat(self, food):
        print("I am eating", food)

위의 코드는 Animal 클래스를 정의하는 예시입니다. 클래스는 class 예약어로 시작하며, 클래스 이름은 대문자로 시작하는 것이 관례입니다. __init__ 메서드는 객체가 생성될 때 자동으로 호출되는 생성자(Constructor)로, 클래스에서 정의된 변수들을 초기화합니다. **move**와 eat 메서드는 동물 객체에서 호출할 수 있는 함수입니다.

클래스에서 정의된 변수와 함수를 사용하기 위해서는, 객체를 먼저 생성해야 합니다.

dog = Animal(2, 4, True)
cat = Animal(2, 4, True)

dog.move() # "I am moving" 출력
cat.eat("fish") # "I am eating fish" 출력

위의 코드는 Animal 클래스에서 dog와 cat 객체를 생성한 후, move와 eat 함수를 호출하는 예시입니다. 이렇게 객체지향 프로그래밍에서는, 클래스를 설계하고, 객체를 생성하여 사용함으로써 현실 세계를 모델링하여 프로그래밍할 수 있습니다.

Docker는 컨테이너 간 통신을 위한 다양한 방법을 제공합니다. 이를 위해서는 컨테이너 간 네트워크를 설정해야 합니다.

  1. 사용자 정의 브리지 네트워크 생성 Docker에서는 사용자 정의 브리지 네트워크를 생성하여 두 개 이상의 컨테이너가 동일한 네트워크에서 통신할 수 있습니다. 먼저, 다음 명령어로 사용자 정의 브리지 네트워크를 생성합니다.
docker network create my-network

그리고 컨테이너를 실행할 때, --net 옵션을 사용하여 해당 네트워크에 연결합니다.

docker run --name container1 --net my-network image1
docker run --name container2 --net my-network image2

이제 container1에서 container2로 통신이 가능해집니다.

  1. 호스트 네트워크 사용 컨테이너가 호스트와 동일한 네트워크를 사용하도록 설정할 수 있습니다. 다음과 같이 --net=host 옵션을 사용하여 호스트 네트워크를 사용할 수 있습니다.
docker run --name container1 --net=host image1
docker run --name container2 --net=host image2

이제 container1에서 container2로 바로 통신이 가능합니다.

  1. 링크(Link) 사용 Docker는 --link 옵션을 사용하여 컨테이너 간 통신을 가능하게 합니다. 이 옵션을 사용하면, 명령어에서 컨테이너 이름을 지정할 수 있으며, 그에 따라 해당 컨테이너의 IP 주소 및 환경 변수를 사용할 수 있습니다.
docker run --name container1 --link container2:image2 image1

위의 예시에서 container1은 container2의 IP 주소 및 환경 변수를 사용할 수 있게 됩니다.

Docker는 위와 같은 방법을 통해 컨테이너 간 통신을 가능하게 합니다. 이를 통해 각각의 컨테이너는 독립적으로 실행되면서도 필요한 경우 다른 컨테이너와 연결하여 통신할 수 있습니다.

참고 문헌: [1] https://stackoverflow.com/questions/55862431/how-to-communicate-between-two-containers-using-docker[2] https://www.tutorialworks.com/container-networking/[3] https://stackoverflow.com/questions/30545023/how-to-communicate-between-docker-containers-via-hostname

'개발 > Docker' 카테고리의 다른 글

도커 기본 명령어 설명 (Docker basic commands)  (0) 2023.03.09

+ Recent posts