├── .github └── workflows │ └── aws.yml ├── .gitignore ├── Java ├── 000. Spring │ └── README.md ├── 002. Inheritance │ └── Inheritance.md └── README.md ├── Python ├── 000. flask │ ├── 000. requirements.txt.py │ ├── 001. Hello world.py │ ├── 002-1 URL slash.py │ ├── 002. Variable Rules.py │ ├── 003-1 app.add_url_rule().py │ ├── 003. Routing.py │ ├── 004. Redirect.py │ ├── 005. HTTP Method.py │ ├── 006. Templates.py │ ├── 007. Sending data.py │ ├── 008.(Redirect) Error.py │ ├── 009. request.py │ ├── 010. cookie.py │ ├── 011. session.py │ ├── 012. logging.py │ ├── 013. app.config.py │ ├── 014. Blueprint.py │ ├── 015. flask-restful.py │ ├── 016. Mongoengine.py │ ├── 017. flask-jwt-extended.py │ ├── learned_extensions │ │ ├── 015. flask-restful.py │ │ ├── 016. Mongoengine.py │ │ ├── 017. flask-jwt-extended.py │ │ └── 018. flask-validation.py │ └── readme.md ├── 001. Hello world │ └── Hello, world!.py ├── 002. Type │ ├── Bool │ │ └── Bool.py │ ├── Decode, Encode │ │ └── numbers.py │ ├── None │ │ └── None.py │ ├── Numbers │ │ └── numbers.py │ └── String │ │ ├── Formating.py │ │ └── String.py ├── 003. Iterable │ ├── Non-Sequence │ │ ├── Dictionary │ │ │ └── Dictionary.py │ │ └── Set │ │ │ └── Set.py │ └── Sequence │ │ ├── List │ │ └── main.py │ │ └── Tuple │ │ └── Tuple.py ├── Module │ ├── Module.py │ └── mod1.py ├── closure │ └── closure.py ├── decorator │ └── decorator.py ├── instance, class, static method │ └── main.py ├── override │ └── override.py └── super │ └── main.py ├── README.md ├── Terraform ├── 001. Input Variable.md └── README.md └── test.md /.github/workflows/aws.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build and push a new container image to Amazon ECR, 2 | # and then will deploy a new task definition to Amazon ECS, on every push 3 | # to the master branch. 4 | # 5 | # To use this workflow, you will need to complete the following set-up steps: 6 | # 7 | # 1. Create an ECR repository to store your images. 8 | # For example: `aws ecr create-repository --repository-name my-ecr-repo --region us-east-2`. 9 | # Replace the value of `ECR_REPOSITORY` in the workflow below with your repository's name. 10 | # Replace the value of `aws-region` in the workflow below with your repository's region. 11 | # 12 | # 2. Create an ECS task definition, an ECS cluster, and an ECS service. 13 | # For example, follow the Getting Started guide on the ECS console: 14 | # https://us-east-2.console.aws.amazon.com/ecs/home?region=us-east-2#/firstRun 15 | # Replace the values for `service` and `cluster` in the workflow below with your service and cluster names. 16 | # 17 | # 3. Store your ECS task definition as a JSON file in your repository. 18 | # The format should follow the output of `aws ecs register-task-definition --generate-cli-skeleton`. 19 | # Replace the value of `task-definition` in the workflow below with your JSON file's name. 20 | # Replace the value of `container-name` in the workflow below with the name of the container 21 | # in the `containerDefinitions` section of the task definition. 22 | # 23 | # 4. Store an IAM user access key in GitHub Actions secrets named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. 24 | # See the documentation for each action used below for the recommended IAM policies for this IAM user, 25 | # and best practices on handling the access key credentials. 26 | 27 | on: 28 | pull_request: 29 | branches: 30 | - master 31 | 32 | name: CI 33 | 34 | jobs: 35 | deploy: 36 | name: Deploy 37 | runs-on: ubuntu-latest 38 | steps: 39 | - name: Checkout 40 | uses: actions/checkout@v1 41 | 42 | - name: Setup Python 3.6 43 | id: setup-python 44 | uses: actions/setup-python@v1 45 | with: 46 | python-version: 3.6 47 | 48 | - name: Install Dependancies 49 | run: | 50 | python -m pip install --upgrade pip 51 | pip install -r requirements_base.txt -r requirements_dev.txt 52 | 53 | - name: Test Application 54 | run: | 55 | pytest 56 | - name: Configure AWS credentials 57 | uses: aws-actions/configure-aws-credentials@v1 58 | with: 59 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 60 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 61 | aws-region: ap-northeast-2 62 | 63 | - name: Login to Amazon ECR 64 | id: login-ecr 65 | uses: aws-actions/amazon-ecr-login@v1 66 | 67 | - name: Build, tag, and push image to Amazon ECR 68 | id: build-image 69 | env: 70 | ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} 71 | ECR_REPOSITORY: test-github-action 72 | IMAGE_TAG: ${{ github.sha }} 73 | 74 | run: | 75 | # Build a docker container and 76 | # push it to ECR so that it can 77 | # be deployed to ECS. 78 | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . 79 | docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG 80 | echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" 81 | 82 | - name: Elastic Beanstalk Deploy 83 | id: task-def 84 | run: | 85 | pip install awscli 86 | pip install awsebcli 87 | eb init -r ap-northeast-2 -p "multi-container-docker-18.09.9-ce-(generic)" test-action 88 | eb deploy 89 | 90 | - name: Slack Notification 91 | uses: 8398a7/action-slack@v2 92 | with: 93 | status: ${{ job.status }} 94 | author_name: Test-Action 95 | env: 96 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 97 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} 98 | if: always() 99 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/macos,python,pycharm+all 3 | 4 | ### macOS ### 5 | # General 6 | .DS_Store 7 | .AppleDouble 8 | .LSOverride 9 | 10 | # Icon must end with two \r 11 | Icon 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | .com.apple.timemachine.donotpresent 24 | 25 | # Directories potentially created on remote AFP share 26 | .AppleDB 27 | .AppleDesktop 28 | Network Trash Folder 29 | Temporary Items 30 | .apdisk 31 | 32 | ### PyCharm+all ### 33 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 34 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 35 | 36 | # User-specific stuff 37 | .idea/**/workspace.xml 38 | .idea/**/tasks.xml 39 | .idea/**/usage.statistics.xml 40 | .idea/**/dictionaries 41 | .idea/**/shelf 42 | 43 | # Sensitive or high-churn files 44 | .idea/**/dataSources/ 45 | .idea/**/dataSources.ids 46 | .idea/**/dataSources.local.xml 47 | .idea/**/sqlDataSources.xml 48 | .idea/**/dynamic.xml 49 | .idea/**/uiDesigner.xml 50 | .idea/**/dbnavigator.xml 51 | 52 | # Gradle 53 | .idea/**/gradle.xml 54 | .idea/**/libraries 55 | 56 | # Gradle and Maven with auto-import 57 | # When using Gradle or Maven with auto-import, you should exclude module files, 58 | # since they will be recreated, and may cause churn. Uncomment if using 59 | # auto-import. 60 | # .idea/modules.xml 61 | # .idea/*.iml 62 | # .idea/modules 63 | 64 | # CMake 65 | cmake-build-*/ 66 | 67 | # Mongo Explorer plugin 68 | .idea/**/mongoSettings.xml 69 | 70 | # File-based project format 71 | *.iws 72 | 73 | # IntelliJ 74 | out/ 75 | 76 | # mpeltonen/sbt-idea plugin 77 | .idea_modules/ 78 | 79 | # JIRA plugin 80 | atlassian-ide-plugin.xml 81 | 82 | # Cursive Clojure plugin 83 | .idea/replstate.xml 84 | 85 | # Crashlytics plugin (for Android Studio and IntelliJ) 86 | com_crashlytics_export_strings.xml 87 | crashlytics.properties 88 | crashlytics-build.properties 89 | fabric.properties 90 | 91 | # Editor-based Rest Client 92 | .idea/httpRequests 93 | 94 | ### PyCharm+all Patch ### 95 | # Ignores the whole .idea folder and all .iml files 96 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 97 | 98 | .idea/ 99 | 100 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 101 | 102 | *.iml 103 | modules.xml 104 | .idea/misc.xml 105 | *.ipr 106 | 107 | ### Python ### 108 | # Byte-compiled / optimized / DLL files 109 | __pycache__/ 110 | *.py[cod] 111 | *$py.class 112 | 113 | # C extensions 114 | *.so 115 | 116 | # Distribution / packaging 117 | .Python 118 | build/ 119 | develop-eggs/ 120 | dist/ 121 | downloads/ 122 | eggs/ 123 | .eggs/ 124 | lib/ 125 | lib64/ 126 | parts/ 127 | sdist/ 128 | var/ 129 | wheels/ 130 | *.egg-info/ 131 | .installed.cfg 132 | *.egg 133 | MANIFEST 134 | 135 | # PyInstaller 136 | # Usually these files are written by a python script from a template 137 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 138 | *.manifest 139 | *.spec 140 | 141 | # Installer logs 142 | pip-log.txt 143 | pip-delete-this-directory.txt 144 | 145 | # Unit test / coverage reports 146 | htmlcov/ 147 | .tox/ 148 | .coverage 149 | .coverage.* 150 | .cache 151 | nosetests.xml 152 | coverage.xml 153 | *.cover 154 | .hypothesis/ 155 | .pytest_cache/ 156 | 157 | # Translations 158 | *.mo 159 | *.pot 160 | 161 | # Django stuff: 162 | *.log 163 | local_settings.py 164 | db.sqlite3 165 | 166 | # Flask stuff: 167 | instance/ 168 | .webassets-cache 169 | 170 | # Scrapy stuff: 171 | .scrapy 172 | 173 | # Sphinx documentation 174 | docs/_build/ 175 | 176 | # PyBuilder 177 | target/ 178 | 179 | # Jupyter Notebook 180 | .ipynb_checkpoints 181 | 182 | # pyenv 183 | .python-version 184 | 185 | # celery beat schedule file 186 | celerybeat-schedule 187 | 188 | # SageMath parsed files 189 | *.sage.py 190 | 191 | # Environments 192 | .env 193 | .venv 194 | env/ 195 | venv/ 196 | ENV/ 197 | env.bak/ 198 | venv.bak/ 199 | 200 | # Spyder project settings 201 | .spyderproject 202 | .spyproject 203 | 204 | # Rope project settings 205 | .ropeproject 206 | 207 | # mkdocs documentation 208 | /site 209 | 210 | # mypy 211 | .mypy_cache/ 212 | 213 | ### Python Patch ### 214 | .venv/ 215 | 216 | -------------------------------------------------------------------------------- /Java/000. Spring/README.md: -------------------------------------------------------------------------------- 1 | # Base 2 | 3 | ## FrameWork 4 | 5 | 프레임워크를 이야기하기 전, 디자인패턴과 라이브러리에 대해 설명드리도록 하겠습니다. 6 | 7 | 8 | 9 | ## Design pattern 10 | 11 | 일정한 규칙 없이 다른 사람이 작성한 코드, 기존에 오픈소스로 존재하는 코드를 읽기란 정말 어렵습니다. 12 | 코드를 읽을 때나, 수정하거나, 새로운 코드를 추가할 때에도 정확한 개발자의 의도를 알기 쉽지 않으며, 성능을 최적화 하기에도 부적합합니다. 13 | 14 | 디자인 패턴은, 특정한 패턴에 대해 규칙을 정해 이런 문제를 해결해 준다. 15 | 특정 클래스에 대해 타인을 이해시키는 데 시간이 오래 걸리지만, 16 | "Singleton 패턴을 썼다"고 말하면 훨씬 이해하기 쉽다. 17 | 18 | 19 | 20 | ## Library 21 | 22 | 라이브러리는 어떤 기능을 다른 사람들도 사용할 수 있도록 만들어진 것을 의미합니다. 23 | 24 | 예를 들어, 로그인을 할 때 토큰을 발급해주는 소스를 만든다고 해봅시다. 25 | 라이브러리 없이는, 토큰을 발급하는 소스를 만드는 모든 사람들은 모두 기능을 각자 구현해야 합니다. 26 | 하지만 모두 제작하지 않고 라이브러리를 사용하여 다른 사람들도 같은 기능을 만들 때 사용할 수 있도록 제공하는 것이 라이브러리 입니다. 27 | 28 | 29 | 30 | ## FrameWork 31 | 32 | 프레임워크는 디자인패턴과 라이브러리의 집합이라고 할 수 있습니다. 33 | 34 | 정해진 디자인 패턴으로 틀을 가지고 라이브러리를 제공하여 필요한 기능을 가져다가 기능을 만들 수 있습니다. 35 | 36 | 예를 들어, 자동차를 만든다고 할 때 틀 없이 처음부터 제작하는 것보다, 37 | 기본적인 틀을 가지고 부품들을 조합하여 자동차를 만든다면 더욱 효율이 높아지겠죠 ? 38 | 39 | 40 | 41 | ## Framework vs Library 42 | 43 | 라이브러리는 자주 사용되는 기능을 다른 사람들도 사용할 수 있도록 기능을 제공하는 코드의 집합을 의미합니다. 44 | 45 | 프레임워크는 라이브러리와 달리 디자인 패턴을 가지고 있어 기본적으로 뼈대를 가지고 있습니다. 46 | 47 | 어떠한 기능을 만들기 위해 라이브러리는 기능을 제공하여 자유롭게 로직을 구현하지만 48 | 프레임워크는 그 기능을 만들기 위한 기능을 제공하지만 정해진 틀을 기반으로 로직을 구현합니다. 49 | 50 | 51 | 52 | ## Framework의 장점 53 | 54 | - 효율적 55 | 56 | 프레임워크는 개발에 필요한 다양한 기능을 미리 제공한다. 57 | 58 | 백지 상태에서 개발 하는 방식에 비해 생산성이 높다. 59 | 60 | - 코드 품질 61 | 62 | 프레임워크는 반복적인 작업에서의 실수하기 쉬운 부분을 내부에서 쉽게 처리 해 줄 수 있다. 63 | 64 | 디자인 패턴을 통해 타인이 코드를 더욱 이해하기 쉽다. 65 | 66 | - 유지 보수가 안정적이고 편리해진다 67 | 68 | 프레임워크를 적용하면서 서비스의 담당자가 바뀌는 상황이라도 프레임워크를 사용함으로써 그 패턴이 유사하기 때문에 보다 안정적으로 유지보수를 할 수 있다. 69 | 70 | 71 | ## Framework의 단점 72 | 73 | - 학습 기간이 필요하다. 74 | 75 | 프레임워크의 기본적인 사용법이나 로직을 이해하려면 프레임워크를 따로 공부해야 하므로 일정 시간을 투자해야 한다. 76 | 77 | - 개발의 자유도에 한계가 존재한다. 78 | 79 | 프레임워크 구조와 패턴을 꼭 따라야 하므로 자유도에 제한이 존재한다. 80 | 81 | 82 | 83 | [참고] : http://tobetong.com/?p=6640 -------------------------------------------------------------------------------- /Java/002. Inheritance/Inheritance.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | 3 | 객체지향 언어를 공부하게 된 계기는, 파이썬만 공부했던 필자가 다른 언어를 공부한다고 무작정 자바 공부에 뛰어들게 되었다. 4 | 자바를 처음부터 공부하면서, 언어의 문법. 기능을 공부하는 것보다 더 중요한 것은 객체 지향을 먼저 아는 것이 중요하다고 느꼈다. 5 | 6 | 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴이라는 책을 읽으면서, 더 자세하게 공부해보자고 결심했다. 7 | 8 | 9 | 10 | # 상속 11 | 상속이라는 개념을 웹 서핑을 통해 구글링 해보았는데, 상속에 대해 생각하는 방식이 사람들마다 달라서 여러 개발 블로그들을 참조해봐도 정확한 정의를 내리기 힘들었다. 12 | 13 | 내가 생각하는 상속이란, 14 | 15 | **상위 객체의 필드와 메소드를 하위 객체에게 물려주는 행위**라고 생각한다. 16 | 17 | 객체 간의 관계를 설정하는 것이라고도 정의하지만, 상속이란 개념은 관계를 설정할 뿐만 아니라 좀 더 포괄적인 의미를 담고 있다고 생각했다. 18 | 19 | ### 상속을 사용했을 때 발생할 수 있는 세 가지 문제점 20 | 21 | ------------------------ 22 | 23 | - 상위 클래스 변경이 어렵다. 24 | - 클래스의 개수가 증가한다. 25 | - 상속을 오용하여 사용할 가능성이 있다. 26 | 27 | -------------------------------------------------------------------------------- /Java/README.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | 3 | 객체지향 언어를 공부하게 된 계기는, 지금까지 파이썬만 공부했고 다른 언어를 공부하고 싶다고 느꼈다. 4 | 원래부터 배우고 싶었던 자바를 선택하고, 바로 자바 공부에 뛰어들게 되었다. 5 | 자바를 처음부터 공부하면서, 언어의 문법. 기능을 공부하는 것도 중요하지만, 객체 지향에 대해 깊게 공부하는 것이 더욱 중요하다고 느꼈다. 6 | 7 | 객체지향에 대한 많은 책들을 읽으면서, 유익한 내용을 정리하고자 만들게 되었다. 8 | 9 | 10 | [개발자가 반드시 정복해야 할 객체지향과 디자인 패턴](http://www.yes24.com/24/goods/9179120?scode=032&OzSrank=1) 11 | [객체지향의 사실과 오해](http://www.yes24.com/24/goods/18249021?scode=032&OzSrank=1) 12 | [Jeremy's Clean Code](http://sungjk.github.io/2017/07/27/clean-code.html) 13 | -------------------------------------------------------------------------------- /Python/000. flask/000. requirements.txt.py: -------------------------------------------------------------------------------- 1 | # 애플리케이션은 정확한 버전 넘버를 포함하여 모든 패키지 의존성을 기록한 requirements.txt 파일을 포함해야 한다. 2 | # 가상 환경의 경우 컴퓨터에서 재생성해야 하기 때문에 중요하다. 3 | 4 | # 이 파일은 pip를 사용하여 자동으로 생성할 수 있다. 5 | # (venv) $ pip freeze >requirements.txt 6 | 7 | # 가상 환경을 완벽하게 복사할 필요가 있을 때 새로운 가상 환경을 생성하고 다음과 같은 커맨드로 실행할 수 있다. 8 | # (venv) $ pip install -r requirements.txt 9 | -------------------------------------------------------------------------------- /Python/000. flask/001. Hello world.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | # flask 폴더 안의 flask를 import. 3 | # 정확히는 flask.app.Flask import 하는 것 4 | 5 | app = Flask(__name__) 6 | # app에 현재 모듈의 이름을 인자로 넣음 7 | 8 | 9 | @app.route('/') 10 | # 데코레이터를 사용. URL을 빌드하기 위해. 11 | def hello_world(): 12 | # '/' 라는 URL에 접근할 경우 실행되는 함수를 정의. 13 | 14 | return 'hello world!' 15 | # 'hello world!' 라는 문자열 return 16 | # '/'라는 URL에 접근할 경우 실행되는 함수의 반환값으로 웹 페이지에 출력되는 값을 뜻함 17 | 18 | 19 | if __name__ == '__main__': 20 | # app.py가 실행될 경우 __name__라는 변수에는 __main__의 값이 저장됨 21 | # 말 그대로 app.py를 실행할 경우 True, 아니면 False. 22 | # 이 파일이 import 되어 사용될 경우 __name__ == '__main__'이 성립하지 않음 23 | 24 | app.run() 25 | # 서버 실행 26 | """ 27 | options : 28 | host = Default 인 경우 127.0.0.1 (localhost)으로 설정 됨 29 | '0.0.0.0' = 외부의 ip에서도 접근 가능 30 | 31 | port = 서버의 포트 설정. Default는 5000. 32 | http://127.0.0.1:5000/ 뒤의 포트 값을 설정해주는 옵션. 33 | 34 | debug = debug=True 일 경우 debug 모드로 서버 실행 35 | app.debug = True / app.run(debug=True) 두 가지 방법으로 디버그 사용 가능하다 36 | 오류가 났을 경우 웹페이지 상에서 Traceback 창이 뜨고 오류를 보여주며 코드를 수정할 수 있음. 37 | """ 38 | -------------------------------------------------------------------------------- /Python/000. flask/002-1 URL slash.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | app = Flask(__name__) 3 | 4 | 5 | @app.route('/python') 6 | # URL 마지막에 슬래쉬가 있는 것과 없는 것의 차이 7 | # 뒤에 슬래쉬가 없는 경우 웹 페이지에서 8 | # localhost:5000/python에서는 정상 작동 하지만 9 | # localhost:5000/python/ 에서는 404 Not Found가 뜬다 10 | def print_hello(): 11 | return 'Hello world!' 12 | 13 | 14 | @app.route('/flask/') 15 | # 슬래쉬가 있는 경우 16 | # 둘 다 정상 작동 한다 17 | def print_flask(): 18 | return 'Hello flask!' 19 | 20 | 21 | if __name__ == '__main__': 22 | app.run() 23 | 24 | -------------------------------------------------------------------------------- /Python/000. flask/002. Variable Rules.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | app = Flask(__name__) 3 | 4 | 5 | @app.route('/hello/') 6 | # route 데코레이터는 /hello라는 URL 뒤에 이라는 variable이 있음. 7 | # name이라는 변수는 <>에 감싼다 8 | def hello_name(name): 9 | # name 이라는 variable를 인자로 받는 hello_name을 선언 10 | return 'hello %s !' % name 11 | # hello_name의 인자값인 name을 넣어 출력 12 | 13 | 14 | @app.route('/User_Num/') 15 | # 뒤의 변수를 int형으로 선언. 16 | # ex ) localhost:5000/User_Num/12 일 경우 num은 int형 변수인 12가 됨. 17 | def Show_User_Num(num): 18 | # 12가 인자가 됨 19 | return 'Your user id is %d' % num 20 | # 문자열 포맷팅 21 | 22 | 23 | @app.route('/User_Score/') 24 | # float형 변수 25 | def Show_User_Score(score): 26 | return 'Your score is %s' % score 27 | # 위와 동일 28 | 29 | 30 | if __name__ == '__main__': 31 | app.run() 32 | -------------------------------------------------------------------------------- /Python/000. flask/003-1 app.add_url_rule().py: -------------------------------------------------------------------------------- 1 | # flask.app.Flask.add_url_rule 2 | from flask import Flask 3 | 4 | app = Flask(__name__) 5 | 6 | 7 | def index(): 8 | return 'Hi' 9 | # 데코레이터 없이 함수를 선언 10 | 11 | 12 | app.add_url_rule('/index', view_func=index, methods=['GET']) 13 | # add_url_rule이라는 메서드로 리소스를 추가한다. 14 | # rule, endpoint, view function 순서로 넣어주어야 하지만 지정해서 넣어줄 수도 있음. 메소드도 설정 가능 15 | 16 | app.run(debug=True) 17 | -------------------------------------------------------------------------------- /Python/000. flask/003. Routing.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | app = Flask(__name__) 3 | 4 | 5 | @app.route('/index1') 6 | # 데코레이터를 통한 라우팅 7 | # app.add_url_rule()을 통한 방법으로도 라우팅 할 수 있다 8 | # 함수를 선언 해 주고 app.add_url_rule(rule, endpoint, 'view function') 으로 사용 9 | def index1(): 10 | # 해당 URL을 요청했을 때 실행되는 함수(view function)을 정의 11 | return 'Hello world' 12 | 13 | 14 | @app.route('/index2') 15 | def index2(): 16 | return 'Hello Flask' 17 | 18 | 19 | @app.route('/index3/') 20 | # 동적 URL 라우팅 21 | def index3(name): 22 | # 변수를 '/index3/' 에 들어갔을 때 실행되는 index3 함수에 인자로 넣어줌 23 | return 'Welcome ' + name 24 | # Welcome {name} 출력 25 | 26 | 27 | @app.route('/index4/') 28 | # 동적 타입 변수 변환 (정수형) 29 | def index4(num): 30 | return 'Your code is ' + num 31 | 32 | 33 | if __name__ == '__main__': 34 | app.run() 35 | -------------------------------------------------------------------------------- /Python/000. flask/004. Redirect.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, redirect, url_for 2 | # flask.app에 Flask, redirect, url_for를 import 한다. 3 | """ 4 | 설명 : 5 | redirect() = 인자의 값으로 다시 direct함 6 | 7 | url_for() = 인자의 값의 절대 주소값를 리턴하는 함수 8 | ex ) 밑에서의 코드에서 url_for('hello_admin') 일 경우 9 | hello_admin 이라는 함수가 정의된 URL을 리턴. 즉, /admin이 리턴됨. 10 | """ 11 | app = Flask(__name__) 12 | 13 | 14 | @app.route('/admin') 15 | def hello_admin(): 16 | return 'hello admin !' 17 | # /admin 에 접속할 경우 hello_admin 함수가 실행되며 return 값으로 'hello admin !'이라는 string이 반환 18 | 19 | 20 | @app.route('/guest/') 21 | def hello_guest(name): 22 | return 'Hello %s !' % name 23 | # /guest/ name의 값에 따라 URL의 뒤에 있는 은 달라짐. 24 | # hello_guest의 함수에서 'hello {name} !' 을 리턴. 25 | 26 | 27 | @app.route('/user/') 28 | # /user/{name} 으로 접속하면 name 변수에 값이 들어감 29 | def hello_user(name): 30 | if name == 'admin': 31 | # name이 admin 이면 32 | return redirect(url_for('hello_admin')) 33 | # hello_admin의 주소로 redirect해줌. 34 | # == localhost:8080/admin으로 접속 해 준다. 35 | else: 36 | return redirect(url_for('hello_guest', name=name)) 37 | # name이 admin이 아니면, 38 | # url에서 /user/에서 name 변수를 /guest/ 에서 name 변수 값으로 넣어준다. 39 | # 그 후 localhost:8080/guest/ 으로 다시 접속 해줌. 40 | 41 | 42 | if __name__ == '__main__': 43 | app.run(debug=True, port=8080) 44 | -------------------------------------------------------------------------------- /Python/000. flask/005. HTTP Method.py: -------------------------------------------------------------------------------- 1 | # HTTP 프로토콜이란, (HyperText Transper Protocol) 2 | # 클라이언트와 서버 사이에 이루어지는 요청과 응답의 프로토콜이다. 3 | # 클라이언트가 서버로부터 요청(request)를 보내면, 서버가 요청에 대하여 응답(response) 하여 전달한다. 4 | """ 5 | HTTP Methods 6 | Get = 정보를 받아오기 위해 URL 형식으로 서버측에 데이터를 요청 7 | 8 | Head = 메세지 헤더 취득 9 | Get과 비슷하나 문서를 요청하는 것이 아닌 문서 정보를 요청함. 10 | == HTTP 헤더 정보만 보냄 11 | 12 | Post = 내용 전송 13 | 클라이언트에서 서버로 어떤 정보를 전송함. 14 | 15 | Put = 내용 갱신 전송 16 | Post랑 비슷하지만 Put은 내용을 갱신해서 전송함. 17 | Put은 클라이언트 측이 서버측 구현에 관여하는 것으로 세밀한 Post를 더 많이 쓴다고 함. 18 | 19 | Delete = 파일 제거 20 | """ 21 | from flask import Flask, redirect, url_for, request 22 | app = Flask(__name__) 23 | 24 | 25 | @app.route('/success/') 26 | def success(name): 27 | return 'Hi %s' % name 28 | # /success/에서의 name을 넣은 문자열 반환 29 | 30 | 31 | @app.route('/login', methods=['POST', 'GET']) 32 | # route는 default일 경우 자동으로 'GET' 이지만 HTTP method를 지정해 줄 수 있다. 33 | def login(): 34 | if request.method == 'POST': 35 | # 요청 메소드가 POST일 경우 == 클라이언트에서 서버로 정보를 전송한 경우 36 | user = request.form['name'] 37 | # user라는 변수에 요청을 받은 form 안에서 name을 파라미터로 넣어 정의함 38 | return redirect(url_for('success', name=user)) 39 | # success라는 변수가 있는 주소에 redirect. success에서 name은 앞에서 선언한 user로 넣어줌. 40 | else: 41 | user = request.args.get('name') 42 | # name이라는 args를 get해서 user에 넣음 43 | return redirect(url_for('success', name=user)) 44 | # name 매개 변수에 해당하는 값은 전과 같이 '/success'URL로 전달한다. 45 | 46 | 47 | # POST를 통해서 클라이언트에서 정보를 받아오기 위해서는 48 | # HTML 등을 통해서 받아 와야 하는데, document에서는 html을 사용한 template를 사용한다. 49 | """ 50 | templete ( login.html ) 51 | 52 | 53 | 54 |
55 | // http://localhost:5000/login 의 method == post 56 |

Enter Name:

57 |

58 | // text 형태로 input 함 name을 선언할 수 있음 ( 변수명 ) 59 |

60 | // input type을 submit으로 하면 post하는 것. 서버로 전송함 61 |
62 | 63 | 64 | """ 65 | 66 | if __name__ == '__main__': 67 | app.run(debug=True) 68 | 69 | # http://localhost:5000/login URL의 경우 서버를 run 한 후 template로 들어가서 html을 실행시켜 쓸 수 있다. 70 | -------------------------------------------------------------------------------- /Python/000. flask/006. Templates.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | app = Flask(__name__) 3 | 4 | 5 | @app.route('/') 6 | def index(): 7 | return '

Hello World

' 8 | # return 값을 html 폼으로 할 수 있다. 9 | # 하지만 python 코드에서 HTML를 생성하는 것은 번거롭기 때문에 사용하지 않습니다. 10 | 11 | 12 | @app.route('/index') 13 | def index_2(): 14 | return render_template('hello.html') 15 | # HTML 코드을 반환하는 대신에 render_template() 함수 로 HTML 파일을 렌더링 할 수 있다. 16 | # Template 파일의 hello.html 파일을 렌더링함. == hello.html과 위 HTML 코드가 같다면 같은 결과 출력 17 | 18 | 19 | """ 20 | jinga2 템플릿 엔진을 사용하여 21 | HTML 코드에 넣어 템플릿이 렌더링 될 때 값으로 바뀌는 변수 및 표현식 사용 가능 ( Python 표현식과 동일 ) 22 | ex ) {% for key, value in result.iteritems() %} 23 | {{ key }} 24 | {{ value }} 25 | {% endfor %} 26 | 27 | Jinga2 템플릿 엔진은 HTML과 구분하기 위해 다음 구분 기호를 사용 28 | {% ~~~ %} ex ) {% if variable>60 %} {% else %} {% endif %} 29 | {{ ~~~ }} ex ) {{name}} 30 | 31 | 등등 더 있지만 웹 템플릿과 Jinga2는 나중에 알아보려고 한다. 32 | """ 33 | if __name__ == '__main__': 34 | app.run(debug=True) 35 | -------------------------------------------------------------------------------- /Python/000. flask/007. Sending data.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request 2 | app = Flask(__name__) 3 | 4 | 5 | @app.route('/') 6 | def index(): 7 | return render_template('data.html') 8 | # '/' URL 접속하면 data.html 파일을 띄워준다. 9 | 10 | 11 | """ 12 | ( data.html ) 13 | 14 | 15 | 16 | 17 |
18 |

Name

19 |

Age

20 |

Birthday

21 | // input type이 text인 세 변수의 값을 입력받음 22 |

23 | // submit 함 24 |
25 | 26 | 27 | 28 | """ 29 | 30 | 31 | @app.route('/result', methods=['GET', 'POST']) 32 | # GET과 POST 메소드를 사용 할 것이라고 명시 33 | def result(): 34 | if request.method == 'POST': 35 | # 메소드가 POST 면 36 | finally_result = request.form 37 | # request.form에는 {} 형태로 있음. 따라서 변수 finally_result = 딕셔너리 38 | return render_template('result.html', result=finally_result) 39 | # 데이터가 저장된 딕셔너리를 result라는 변수에 넣음. 40 | 41 | 42 | """ 43 | ( result.html ) 44 | 45 | 46 | 47 | 48 | 49 | {% for key, value in result.items() %} 50 | // 위의 코드에서 받아온 result 딕셔너리의 key, value 값을 for 문을 이용해 뽑아냄 51 | 52 | 53 | // key를 head ( 두꺼운 글씨 ) 로 넣음 54 | 55 | // value를 ( 일반 글씨 ) 로 넣음 56 | 57 | // tr = 테이블의 한 행 58 | {% endfor %} 59 | // for 문이 여러번 돌아가기 때문에 다시 돌아가면 tr 태그가 다시 나오므로 2번째 행에 넣어짐 60 |
{{ key }} {{ value }}
61 | 62 | 63 | 64 | """ 65 | 66 | if __name__ == '__main__': 67 | app.run(debug=True) 68 | -------------------------------------------------------------------------------- /Python/000. flask/008.(Redirect) Error.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, redirect, url_for, abort, render_template 2 | app = Flask(__name__) 3 | 4 | 5 | @app.route('/') 6 | def index(): 7 | return redirect(url_for('login')) 8 | # login 함수 있는 곳으로 redirect 9 | 10 | 11 | @app.route('/login') 12 | def login(): 13 | abort(401) 14 | # '/login' 에 접속할 경우 abort(args) 15 | # abort()는 괄호 안에 지정된 에러 코드를 가지고 요청을 중단한다. 16 | this_is_never_executed() 17 | # 앞에서 에러가 발생했을 경우 뒤의 코드는 실행되지 않는다. 18 | 19 | # 에러 페이지를 변경하고 싶다면 errorhander() 데코레이터를 사용할 수 있다. 20 | 21 | 22 | @app.errorhandler(404) 23 | def page_not_found(error): 24 | return render_template('page_not_found.html', 404) 25 | # 페이지의 상태 코드가 404인 것을 Flask에게 말해 준다. 26 | 27 | 28 | @app.errorhandler(AssertionError) 29 | # view function에서 발생하는 AssertionError를 intercept하여 처리 30 | def assertion_error(): 31 | return 'AssertionError.', 500 32 | 33 | 34 | @app.route('/2') 35 | def test2(): 36 | raise AssertionError() 37 | # AssertionError 일부러 발생시킴. 28번줄의 errorhandler(AssertionError)를 테스트 하기 위함.from 38 | 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) 42 | 43 | -------------------------------------------------------------------------------- /Python/000. flask/009. request.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask import request 3 | 4 | app = Flask(__name__) 5 | 6 | 7 | @app.route('/request/args', methods=['GET']) 8 | def args(): 9 | return request.args['keys'] 10 | # keys를 가져옴 ( GET ) 11 | 12 | 13 | @app.route('/request/form', methods=['POST']) 14 | def form(): 15 | return request.form['keys'] 16 | # keys를 리턴함 ( POST일 때 ) 17 | 18 | 19 | @app.route('/request/json') 20 | def json(): 21 | req = request.get_json() 22 | 23 | print(type(req)) 24 | # json 타입은 dict타입 또는 list 타입으로 바뀜 25 | return req 26 | 27 | 28 | if __name__ == '__main__': 29 | app.run(debug=True) 30 | -------------------------------------------------------------------------------- /Python/000. flask/010. cookie.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, Response 2 | 3 | app = Flask(__name__) 4 | # HTTP는 Stateless 라는 특징을 가진다. 5 | # 한번의 요청과 응답을 거치면 응답을 받은 후에 유지되지 않고 끊긴다 6 | # login을 해야만 들어가지는 mypage 같은 기능들을 구현하려면 로그인이 유지되어야 하는데 7 | # HTTP 특성상 stateless이기 때문에 cookie나 session을 통해 강제로 statefull 상태를 유지하도록 만들어준다. 8 | 9 | """ 10 | cookie : 11 | 쿠키에는 클라이언트 로컬에 저장되는 키와 값이 들어있는 작은 데이터 파일이다. 12 | 일정 시간동안 데이터를 저장할 수 있다. 13 | 14 | 클라이언트가 서버에게 Request를 보낸다. ( 클라이언트가 브라우저로 웹 페이지에 접속 ) 15 | 서버는 웹페이지를 전송할 때 쿠키까지 전송한다 16 | 클라이언트가 요청한 웹페이지를 전송받으면서 쿠키 하드에 저장한다. 17 | 쿠키는 클라이언트 쪽에 저장되며 클라이언트를 재받문시 cookie를 같이 request하는 방식임. 18 | 19 | Response Header에 Set-cookie 속성을 사용하면 클라이언트에 쿠키를 만들 수 있다. 20 | 21 | 쿠키의 예시: 22 | 자동 로그인, "오늘 더 이상 이 창을 보지 않음" 등등. 23 | """ 24 | 25 | 26 | @app.route('/cookie', methods=['GET', 'POST']) 27 | def send_cookie(): 28 | if request.method == 'GET': 29 | response = Response('cookie') 30 | # 쿠키를 주려면 Response 객체가 필요하다 31 | response.set_cookie('cookie', 'value') 32 | 33 | return response 34 | elif request.method == 'POST': 35 | response = Response('Hi') 36 | response.set_cookie('cookie', '', expires=0) 37 | 38 | # 쿠키 제거는 expires를 0으로 해주면 된다 39 | 40 | return response 41 | else: 42 | return '', 405 43 | 44 | 45 | if __name__ == '__main__': 46 | app.run(debug=True) 47 | -------------------------------------------------------------------------------- /Python/000. flask/011. session.py: -------------------------------------------------------------------------------- 1 | # 세션 (Session) 2 | 3 | # 사용자 정보 파일을 브라우저에 저장하는 쿠키와 달리 세션은 서버 측에서 관리한다. 4 | # 세션 ID를 부여하며 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증상태를 유지합니다. 5 | # 사용자에 대한 정보를 서버에 두기 때문에 쿠키보다 보안에 좋지만, 사용자가 많아질수록 서버 메모리를 많이 차지하게 됨. 6 | 7 | """ 8 | session: 9 | 클라이언트가 서버에 접속 시 세션 ID를 발급 10 | 11 | 클라이언트는 세션 ID에 대해 쿠키를 사용해서 저장 ( 이 때 쿠키 이름은 JSESSIONID이다. ) -> 12 | 13 | 클라이언트가 서버에 다시 접속 시 이 쿠키를 이용해서 세션 ID 값을 서버에 전달 14 | """ 15 | from flask import Flask, request, session 16 | 17 | app = Flask(__name__) 18 | 19 | 20 | @app.route('/session', methods=['GET', 'POST', 'DELETE']) 21 | def index(): 22 | if request.method == 'DELETE': 23 | session.pop('username') 24 | # session.pop은 username을 출력하며 삭제함 25 | return 'session deleted' 26 | 27 | else: 28 | if 'username' in session: 29 | return 'Hello {}'.format(session['username']) 30 | # 세션 안에 'username'이 있으면 'Hello {username}'을 반환 31 | 32 | else: 33 | # 세션 안에 'username'이 없다면 34 | session['username'] = 'value' 35 | # 'username'을 'vaule'로 설정 36 | print(session['username']) 37 | # 출력 38 | return 'Session appended!' 39 | 40 | 41 | if __name__ == '__main__': 42 | app.run(debug=True) 43 | -------------------------------------------------------------------------------- /Python/000. flask/012. logging.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, g 2 | import logging 3 | from logging.handlers import RotatingFileHandler 4 | 5 | app = Flask(__name__) 6 | print(app.logger) 7 | 8 | # Flask.logger는 'flask.app'이라는 이름의 logger를 반환 9 | # 여기에 custom logger를 붙여줄 수 있다 10 | 11 | 12 | @app.before_request 13 | # 되기 전에 실행할 것 14 | def before_first_request(): 15 | def make_logger(): 16 | handler = RotatingFileHandler('server_log.log', maxBytes=10000, backupCount=3) 17 | # RotatingFileHandler 18 | # 첫 번째 인자 -> 로그 파일의 이름 19 | # 두 번째 인자 -> max치를 설정. maxBytes를 채우면 새 로그 파일을 생성 20 | # 세 번째 인자 -> n번째 로그 파일이 생성되면 원래 있던 로그파일을 버리고 새로운 로그 파일 생성 21 | 22 | formatter = logging.Formatter("[%(asctime)s] %(levelname)s - %(message)s") 23 | # logging.Formatter를 사용하여 로그 포매팅 24 | 25 | handler.setFormatter(formatter) 26 | # handler에 Formatter 설정 27 | app.logger.addHandler(handler) 28 | # app의 logger에 handler 추가 29 | """ 30 | 31 | CRITICAL = 50 32 | FATAL = CRITICAL 33 | ERROR = 40 34 | WARNING = 30 35 | WARN = WARNING 36 | INFO = 20 37 | DEBUG = 10 38 | NOTSET = 0 39 | """ 40 | app.logger.setLevel(logging.INFO) 41 | # logger의 level을 세팅 42 | # -> 기본 level은 WARNING 43 | 44 | make_logger() 45 | g.logger = app.logger 46 | print(g.logger) 47 | 48 | g.logger.info('<=====server logging=====>') 49 | 50 | 51 | @app.route('/index1') 52 | def index(): 53 | g.logger.info('Access router') 54 | return 'logging', 200 55 | 56 | 57 | if __name__ == '__main__': 58 | app.run(debug=True) 59 | -------------------------------------------------------------------------------- /Python/000. flask/013. app.config.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | app.config['config'] = 'hello?' 6 | # app.config를 통해 설정 값들을 저장할 수 있음. 7 | 8 | print(app.config) 9 | ''' 10 | 11 | ''' 12 | # 대충 이러한 기본 config를 가지고 있는데, config를 추가해서 'config':'hello?' 값이 추가된 것을 볼 수 있다. 13 | 14 | app.config.update({ 15 | 'CONFIG_1': 1, 16 | 'CONFIG_2': True 17 | }) 18 | # app.config.update으로 추가해 줄 수도 있다. 19 | 20 | del app.config['CONFIG_2'] 21 | # config 삭제 22 | print('CONFIG_2' in app.config) 23 | # False 값 return. CONFIG_2를 삭제했기 때문임 24 | 25 | # app.config는 많은 기본 값들을 가지고 있는데 26 | # 이미 들어가 있는 해당 설정 값들의 일부는 즉시 접근 가능하다 27 | print(app.debug, app.testing, app.secret_key) 28 | 29 | 30 | class Someconfig(object): 31 | SOME_CONFIG = 1 32 | 33 | 34 | app.config.from_object(Someconfig) 35 | print(app.config['SOME_CONFIG']) 36 | -------------------------------------------------------------------------------- /Python/000. flask/014. Blueprint.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask import Blueprint 3 | 4 | # flask application은 blueprint들의 집합으로 고려한다. 5 | # blueprint의 집합체 = flask application 이라고 볼 수 있음. 6 | # blueprint를 사용해서 모듈화 된 flask application을 만들기에 적합한 구조를 만들 수 있다. 7 | 8 | blueprint = Blueprint('my_first_blueprint', __name__) 9 | 10 | # blueprint의 구현은 이런 식으로 되어있다 11 | # def __init__(self, name, import_name, static_folder=None, static_url_path=None, 12 | # template_folder=None, url_prefix=None, subdomain=None, url_defaults=None) 13 | 14 | # 2가지의 인자값은 name과 import_name이다. 15 | # name은 중복될 수 없는 값이며, blueprint의 name을 설정해주는 인자 값이다. 16 | # 모듈 마다 각각의 blueprint를 만들어 주는 경우 blueprint의 이름을 __name__으로 해도 좋다. 17 | 18 | 19 | @blueprint.route('/') 20 | # Blueprint의 객체인 blueprint를 사용해서 route를 해준다. 21 | # Flask app 객체와 비슷한 route 형식을 가지고 있다. 22 | def test_blueprint(): 23 | return 'made my first blueprint!!' 24 | 25 | 26 | app = Flask(__name__) 27 | app.register_blueprint(blueprint, url_prefix='/prefix') 28 | # Flask 객체를 얻어서, app 객체에 blueprint를 등록시켜준다. 29 | # blueprint 들이 많다면, 각 모듈에서 blueprint를 import 해서 한 app 객체에서 묶어주는 작업이 필요하다. 30 | # url_prefix는 **options 인자값에 해당되며, 해당 blueprint에 해당하는 URL의 prefix를 지정해 주는 option이다. 31 | 32 | if __name__ == "__main__": 33 | app.run() 34 | -------------------------------------------------------------------------------- /Python/000. flask/015. flask-restful.py: -------------------------------------------------------------------------------- 1 | # flask-restful 모듈을 통한 REST API 구현 2 | 3 | # REST는 Representational State Transfer라는 용어의 약자로서 웹의 장점을 최대한 활용할 수 있는 아키텍처 4 | # 최근의 서버 프로그램은 다양한 브라우저와 안드로이폰, 아이폰과 같은 모바일 디바이스에서도 통신을 할 수 있어야 한다. 5 | 6 | """ 7 | REST의 특징 8 | 1. Uniform ( 유니폼 인터페이스 ) 9 | * 지정한 리소스에 대한 조작을 통일되고, 한정적인 인터페이스로 조작하는 인터페이스이다. 10 | 11 | 2. Stateless ( 무상태성 ) 12 | * REST는 무상태성 성격을 가짐. 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다. 13 | * 세션 정보나 쿠키 정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 된다. 14 | 15 | 3. Cacheable ( 캐시 가능 ) 16 | * REST의 가장 큰 특징은 HTTP라는 기존 웹 표준을 그대로 사용하기 때문에 웹에서 사용하는 기존 인프라를 그대로 활용이 가능하다. 17 | 18 | 이 외에도 Self-descriptiveness( 자체 표현 구조 ) - 말 그대로 자기 자신을 표현해야 함. , 19 | Client-server 구조 (클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어듬) 20 | 계층형 구조 가 있음. 21 | """ 22 | 23 | # more exception - http://meetup.toast.com/posts/92, http://private.tistory.com/28 24 | 25 | from flask import Flask, abort, request 26 | from flask_restful import Api, Resource 27 | # flask_restful을 이용해 라우팅하려면, flask_restful.Resource를 사용하자. 28 | # Resource 클래스를 상속받은 클래스는 하나의 uri에 대한 자원이 된다. 29 | 30 | app = Flask(__name__) 31 | api = Api(app) 32 | 33 | 34 | class Hello_world(Resource): 35 | # class를 이용한 routing 구현 36 | def get(self): 37 | # http 메서드를 Hello_world의 메서드 이름으로 지정해준다 38 | # print(request.args['key']) 39 | # 요청 데이터에 접근할 때, 해당 key가 존재하지 않는다면 자동으로 '400 bad request'를 abort해 준다 40 | 41 | return {'name': 'goming', 'age': '17'} 42 | # 원래 flask routing에서는 오류가 나지만, flask-restful에서는 Content type이 application/json으로 반환됨. 43 | 44 | 45 | api.add_resource(Hello_world, '/') 46 | 47 | if __name__ == '__main__': 48 | app.run(debug=True, port=8000) 49 | -------------------------------------------------------------------------------- /Python/000. flask/016. Mongoengine.py: -------------------------------------------------------------------------------- 1 | from mongoengine import * 2 | 3 | # pip install mongoengine 으로 install 할 수 있다. 4 | # 참조 : http://docs.mongoengine.org/guide/connecting.html 5 | 6 | connect('Mongo') 7 | # mongoDB는 스키마가 없는 Nosql Database 이다. 8 | # 테이블이 없는 구조를 통해 데이터베이스를 구현해 볼 수 있다. 9 | # 일반 ORM의 구조와 비슷함. 10 | 11 | # 사용자의 필드와 사용자가 저장할 데이터 자료형을 명시해야 함 12 | 13 | 14 | class User(Document): 15 | 16 | # 틀은 Field(max_length=None, min_length=None, **kwargs) 대충 이러함 17 | # required = True == 필수로 입력되어야 하는 값 18 | # primary_key = True 일 경우 식별자가 됨 19 | # unique = True 일 경우 유일한 값이어야 함. 20 | 21 | username = StringField(primary_key=True) 22 | # 식별자일 경우 필수로 입력되어야 하기 때문에 required는 사용하지 않았음. 23 | 24 | password = StringField(required=True) 25 | 26 | nickname = StringField(default='test_nickname', max_length=6) 27 | # default 값을 지정할 수 있음 28 | 29 | 30 | from flask import Flask, Response, request 31 | 32 | app = Flask(__name__) 33 | 34 | 35 | @app.route('/', methods=['POST']) 36 | def using_mongo_engine(): 37 | username = request.form['username'] 38 | password = request.form['password'] 39 | nickname = request.form['nickname'] 40 | # 세 가지 값 입력 받음 41 | 42 | User( 43 | username=username, 44 | password=password, 45 | nickname=nickname 46 | ).save() 47 | # User에 새로운 값 insert. 48 | 49 | return Response('successful', 200) 50 | 51 | 52 | @app.route('/find', methods=['POST']) 53 | def find_values_from_mongo(): 54 | username = request.form['username'] 55 | 56 | find_value = User.objects(username=username).first() 57 | # 입력받은 username이 User Collection에 존재할 경우, 그 값의 row를 가져옴. 58 | 59 | print(find_value) 60 | 61 | user = User.objects() 62 | print(list(user)) 63 | # list casting 64 | 65 | print(find_value.username) 66 | # 찾은 value 안에서의 username을 출력함. 67 | 68 | 69 | @app.route('/update', methods=['POST']) 70 | def update(): 71 | username = request.form['username'] 72 | new_password = request.form['new_password'] 73 | 74 | u = User.objects(username=username).first() 75 | 76 | print(u.password) 77 | # 현재 password 78 | 79 | u.update(password=new_password) 80 | 81 | print(u.password) 82 | # 바뀐 password 적용. 83 | 84 | 85 | @app.route('/delete', methods='DELETE') 86 | def delete(): 87 | User.objects().delete() 88 | # delete of crud 89 | 90 | 91 | if __name__ == '__main__': 92 | app.run() 93 | 94 | -------------------------------------------------------------------------------- /Python/000. flask/017. flask-jwt-extended.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, jsonify, request 2 | from flask_jwt_extended import ( 3 | JWTManager, jwt_required, create_access_token, 4 | get_jwt_identity 5 | ) 6 | 7 | app = Flask(__name__) 8 | # JWT extension 설정 9 | app.config['JWT_SECRET_KEY'] = 'secret' 10 | JWT = JWTManager(app) 11 | 12 | 13 | @app.route('/login', method=['POST']) 14 | def login(): 15 | if not request.is_json: 16 | return jsonify({'msg': 'missing json in request'}), 400 17 | 18 | username = request.json.get('username', None) 19 | password = request.json.get('password', None) 20 | # username과 password는 None으로 json 형태로 설정 21 | if not username: 22 | return jsonify({'msg': 'Missing username parameter'}), 400 23 | if not password: 24 | return jsonify({'msg': 'Missing password parameter'}), 400 25 | 26 | if username != 'goming' and password != 'abcd': 27 | return jsonify({'msg': 'bad username or password'}), 400 28 | else: 29 | access_token = create_access_token(identity=username) 30 | return jsonify(access_token=access_token), 200 31 | 32 | 33 | @app.route('protected', methods=['GET']) 34 | @jwt_required 35 | def protected(): 36 | current_user = get_jwt_identity() 37 | return jsonify(logged_in_as=current_user) 38 | 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) 42 | 43 | 44 | -------------------------------------------------------------------------------- /Python/000. flask/learned_extensions/015. flask-restful.py: -------------------------------------------------------------------------------- 1 | # flask-restful 모듈을 통한 REST API 구현 2 | 3 | # REST는 Representational State Transfer라는 용어의 약자로서 웹의 장점을 최대한 활용할 수 있는 아키텍처 4 | # 최근의 서버 프로그램은 다양한 브라우저와 안드로이폰, 아이폰과 같은 모바일 디바이스에서도 통신을 할 수 있어야 한다. 5 | 6 | """ 7 | REST의 특징 8 | 1. Uniform ( 유니폼 인터페이스 ) 9 | * 지정한 리소스에 대한 조작을 통일되고, 한정적인 인터페이스로 조작하는 인터페이스이다. 10 | 11 | 2. Stateless ( 무상태성 ) 12 | * REST는 무상태성 성격을 가짐. 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다. 13 | * 세션 정보나 쿠키 정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 된다. 14 | 15 | 3. Cacheable ( 캐시 가능 ) 16 | * REST의 가장 큰 특징은 HTTP라는 기존 웹 표준을 그대로 사용하기 때문에 웹에서 사용하는 기존 인프라를 그대로 활용이 가능하다. 17 | 18 | 이 외에도 Self-descriptiveness( 자체 표현 구조 ) - 말 그대로 자기 자신을 표현해야 함. , 19 | Client-server 구조 (클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어듬) 20 | 계층형 구조 가 있음. 21 | """ 22 | 23 | # more exception - http://meetup.toast.com/posts/92, http://private.tistory.com/28 24 | 25 | from flask import Flask, Blueprint 26 | from flask_restful import Api, Resource 27 | # flask_restful을 이용해 라우팅하려면, flask_restful.Resource를 사용하자. 28 | # Resource 클래스를 상속받은 클래스는 하나의 uri에 대한 자원이 된다. 29 | 30 | blueprint = Blueprint(__name__, __name__) 31 | api = Api(blueprint) 32 | # Api 클래스의 생성자에는 Flask 의 인스턴스를 직접 넣어주거나, blueprint를 전달해서 api 객체를 생성 33 | 34 | 35 | class Hello_world(Resource): 36 | # class를 이용한 routing 구현 37 | def get(self): 38 | # http 메서드를 Hello_world의 메서드 이름으로 지정해준다 39 | # print(request.args['key']) 40 | # 요청 데이터에 접근할 때, 해당 key가 존재하지 않는다면 자동으로 '400 bad request'를 abort해 준다 41 | 42 | return {'name': 'goming', 'age': '17'} 43 | # 원래 flask routing에서는 오류가 나지만, flask-restful에서는 Content type이 application/json으로 반환됨. 44 | 45 | 46 | api.add_resource(Hello_world, '/') 47 | 48 | app = Flask(__name__) 49 | app.register_blueprint(blueprint) 50 | 51 | # api 객체에 add_resource 해주는 방법도 있지만, api 객체의 데코레이터를 사용할 수 도 있음. 52 | 53 | 54 | @api.resource('/resource') 55 | # api에 대한 자원이 되는 것임. 56 | class TestResource(Resource): 57 | def get(self): 58 | return 'hi' 59 | 60 | # flask_restful과 blueprint를 함께 사용해서 고도화된 구조화 형태의 flask application을 만드는 것이 가능하다. 61 | 62 | 63 | if __name__ == '__main__': 64 | app.run(debug=True, port=8000) 65 | -------------------------------------------------------------------------------- /Python/000. flask/learned_extensions/016. Mongoengine.py: -------------------------------------------------------------------------------- 1 | from mongoengine import * 2 | 3 | # pip install mongoengine 으로 install 할 수 있다. 4 | # 참조 : http://docs.mongoengine.org/guide/connecting.html 5 | 6 | connect('Mongo') 7 | # mongoDB는 스키마가 없는 Nosql Database 이다. 8 | # 테이블이 없는 구조를 통해 데이터베이스를 구현해 볼 수 있다. 9 | # 일반 ORM의 구조와 비슷함. 10 | 11 | # 사용자의 필드와 사용자가 저장할 데이터 자료형을 명시해야 함 12 | 13 | 14 | class User(Document): 15 | 16 | # 틀은 Field(max_length=None, min_length=None, **kwargs) 대충 이러함 17 | # required = True == 필수로 입력되어야 하는 값 18 | # primary_key = True 일 경우 식별자가 됨 19 | # unique = True 일 경우 유일한 값이어야 함. 20 | 21 | username = StringField(primary_key=True) 22 | # 식별자일 경우 필수로 입력되어야 하기 때문에 required는 사용하지 않았음. 23 | 24 | password = StringField(required=True) 25 | 26 | nickname = StringField(default='test_nickname', max_length=6) 27 | # default 값을 지정할 수 있음 28 | 29 | 30 | from flask import Flask, Response, request 31 | 32 | app = Flask(__name__) 33 | 34 | 35 | @app.route('/', methods=['POST']) 36 | def using_mongo_engine(): 37 | username = request.form['username'] 38 | password = request.form['password'] 39 | nickname = request.form['nickname'] 40 | # 세 가지 값 입력 받음 41 | 42 | User( 43 | username=username, 44 | password=password, 45 | nickname=nickname 46 | ).save() 47 | # User에 새로운 값 insert. 48 | 49 | return Response('successful', 200) 50 | 51 | 52 | @app.route('/find', methods=['POST']) 53 | def find_values_from_mongo(): 54 | username = request.form['username'] 55 | 56 | find_value = User.objects(username=username).first() 57 | # 입력받은 username이 User Collection에 존재할 경우, 그 값의 row를 가져옴. 58 | 59 | print(find_value) 60 | 61 | user = User.objects() 62 | print(list(user)) 63 | # list casting 64 | 65 | print(find_value.username) 66 | # 찾은 value 안에서의 username을 출력함. 67 | 68 | 69 | @app.route('/update', methods=['POST']) 70 | def update(): 71 | username = request.form['username'] 72 | new_password = request.form['new_password'] 73 | 74 | u = User.objects(username=username).first() 75 | 76 | print(u.password) 77 | # 현재 password 78 | 79 | u.update(password=new_password) 80 | 81 | print(u.password) 82 | # 바뀐 password 적용. 83 | 84 | 85 | @app.route('/delete', methods='DELETE') 86 | def delete(): 87 | User.objects().delete() 88 | # delete of crud 89 | 90 | 91 | if __name__ == '__main__': 92 | app.run() 93 | 94 | -------------------------------------------------------------------------------- /Python/000. flask/learned_extensions/017. flask-jwt-extended.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, jsonify, request 2 | from flask_jwt_extended import ( 3 | JWTManager, jwt_required, create_access_token, 4 | get_jwt_identity 5 | ) 6 | 7 | app = Flask(__name__) 8 | # JWT extension 설정 9 | app.config['JWT_SECRET_KEY'] = 'secret' 10 | JWT = JWTManager(app) 11 | 12 | 13 | @app.route('/login', method=['POST']) 14 | def login(): 15 | if not request.is_json: 16 | return jsonify({'msg': 'missing json in request'}), 400 17 | 18 | username = request.json.get('username', None) 19 | password = request.json.get('password', None) 20 | # username과 password는 None으로 json 형태로 설정 21 | if not username: 22 | return jsonify({'msg': 'Missing username parameter'}), 400 23 | if not password: 24 | return jsonify({'msg': 'Missing password parameter'}), 400 25 | 26 | if username != 'goming' and password != 'abcd': 27 | return jsonify({'msg': 'bad username or password'}), 400 28 | else: 29 | access_token = create_access_token(identity=username) 30 | return jsonify(access_token=access_token), 200 31 | 32 | 33 | @app.route('protected', methods=['GET']) 34 | @jwt_required 35 | def protected(): 36 | current_user = get_jwt_identity() 37 | return jsonify(logged_in_as=current_user) 38 | 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) 42 | 43 | 44 | -------------------------------------------------------------------------------- /Python/000. flask/learned_extensions/018. flask-validation.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_validation import Validator, json_required 3 | 4 | # callsign-viper ( 프로젝트팀 이름 ) 에서 입력 데이터를 검증하기 위한 extension을 만들었음 5 | # json 기반 요청 데이터를 처리해주는 라이브러리이다. 6 | 7 | 8 | app = Flask(__name__) 9 | Validator(app) 10 | # Validator 에 Flask 인스턴스를 넣어줌으로써 validation을 사용할 수 있다 11 | 12 | 13 | @json_required() 14 | # Content-Type이 application/json 형태가 아닐경우 400 BAD REQUEST를 반환, json일 경우 200 OK. 15 | # 입력 받은 데이터가 json인지를 검증해주는 데코레이터 16 | @app.route('/') 17 | def hello(): 18 | return 'hello!' 19 | 20 | 21 | from flask_validation import validate_keys 22 | # validate_keys 는 요청받는 json의 형태를 제한하여 검증해주는 데코레이터이다. 23 | # 필요하지 않은 다른 json 값을 받아오지 않을 수 있고, 필요한 데이터만 받아낼 수 있다. 24 | 25 | 26 | @validate_keys(['name', 'age', {'position': ['lati', 'longi']}]) 27 | @app.route('/index', methods=['POST']) 28 | def index(): 29 | return 'index!' 30 | 31 | # {"name": "Goming", "age": 17, "position": {"lati": 35.24, "longi": 127.681146}} 32 | # 이런 식으로 json 타입을 보내는지 아닌지 검증을 해준다. 33 | 34 | 35 | from flask_validation import validate_common, validate_with_fields, validate_with_jsonschema 36 | # 이 외에도 여러가지 검증을 할 수 있는 데코레이터들이 있다. 37 | # validate_common 데코레이터는, validate_keys 처럼 사용하지만, type까지 검증할 수 있다. 38 | 39 | 40 | if __name__ == '__main__': 41 | app.run() 42 | -------------------------------------------------------------------------------- /Python/000. flask/readme.md: -------------------------------------------------------------------------------- 1 | # Flask 2 | * 파이썬 웹 프레임워크 3 | 4 | ### Flask 설치 5 | ``` 6 | pip install flask 7 | ``` 8 | * Python Flask는 파이썬으로 작성된 마이크로 웹 프레임워크이다. 9 | - 간단한 웹이나 모바일 앱 서버를 만들기에 적합한 웹프레임워크 10 | 11 | -------------------------------------------------------------------------------- /Python/001. Hello world/Hello, world!.py: -------------------------------------------------------------------------------- 1 | print('Hello world!') 2 | # print() 함수를 사용하여 간단하게 출력할 수 있다. 3 | 4 | print("Hello world!") 5 | # 작은 따옴표와 큰 따옴표에 관계 없이 사용할 수 있다. 6 | -------------------------------------------------------------------------------- /Python/002. Type/Bool/Bool.py: -------------------------------------------------------------------------------- 1 | a = True 2 | b = False 3 | 4 | if a: 5 | print('True') 6 | else: 7 | print('False') 8 | # True 9 | 10 | if b: 11 | print('True') 12 | else: 13 | print('False') 14 | # False 15 | 16 | # 대부분의 언어들과는 달리 첫 글자를 대문자로 표기. -------------------------------------------------------------------------------- /Python/002. Type/Decode, Encode/numbers.py: -------------------------------------------------------------------------------- 1 | a = 'abcd' 2 | b = b'abcd' 3 | 4 | print(b.decode()) 5 | # bytes의 .decode() 메소드를 통해 str로 변경 6 | 7 | print(a.encode()) 8 | # str의 .encode() 메소드를 통해 bytes로 변경 9 | -------------------------------------------------------------------------------- /Python/002. Type/None/None.py: -------------------------------------------------------------------------------- 1 | # 다른 언어에서 Null처럼 사용 됨. Python 에서는 None으로 표현. 2 | # 아무런 값도 존재하지 않는다는 뜻. 아무것도 할당되어 있지 않다. 3 | a = None 4 | print(a) -------------------------------------------------------------------------------- /Python/002. Type/Numbers/numbers.py: -------------------------------------------------------------------------------- 1 | # int 2 | a = 1 3 | # 타입을 명시하지 않아도 자료형을 추론해 넣어줌 4 | print(type(a)) 5 | # 6 | 7 | a = int(1) 8 | a: int = 1 9 | # 물론 타입 명시도 가능 10 | 11 | a = 9999999999999999999999999999999999999 12 | # 값의 제한 없음 13 | 14 | a = 999_999_999_999 15 | # 언더바이스 활용 가능 16 | 17 | a = 0o13 18 | # 8진수 19 | 20 | a = 0xAF 21 | # 16진수 22 | 23 | # float ( 실수형 ) 24 | a = 1.0 25 | print(type(a)) 26 | # 27 | 28 | a = float(4) 29 | # 또한 가능 30 | 31 | # 복소수 32 | # 수학에서 사용하는 i 대신 j를 사용 33 | 34 | a = 2-3j 35 | 36 | # 사칙연산 37 | # 기본적인 산술 연산자( +, -. *, /, % 등등 모두 지원 ) 38 | 39 | print(5/2) 40 | # float 타입. 나누어 떨어지더라도 float 타입으로 명시함 41 | 42 | print(5//2) 43 | # int 타입. 소수점 자리 버림 44 | 45 | print(5 ** 2) 46 | # 5의 제곱 = 25. 개인적으로 이 기능이 엄청 신기했음 제곱이 이렇게 쉬울줄이야 -------------------------------------------------------------------------------- /Python/002. Type/String/Formating.py: -------------------------------------------------------------------------------- 1 | # 문자 열에 특정 값을 집어넣기 위해서 사용 2 | # 특정 값은 보통 변수를 사용 3 | 4 | # 1. 포맷 코드 사용 5 | 6 | username = 'Goming' 7 | age = 17 8 | 9 | print("Hello %s , your age is %d" % (username, age)) 10 | 11 | # 2. 문자열 객체의 .format 메서드 사용 12 | 13 | print("Hello {} , your age is {}".format(username, age)) 14 | 15 | # placeholder를 사용해서 index 값을 넣어줄 수 있음 16 | print("Hello {0} , your age is {1}".format(username, age)) 17 | 18 | # 3. fstring 19 | print(f"Hello {username} , your age is {age}") 20 | # Python 3.5 부터 지원하는 방식이라고 함 21 | # 중괄호 속에 넣어서 format()보다 보기 쉽다 22 | # .format 메서드보다 연산 처리 속도가 빠르다는 장점이 있다. 23 | -------------------------------------------------------------------------------- /Python/002. Type/String/String.py: -------------------------------------------------------------------------------- 1 | # String 타입 2 | # 문자, 문자열 모두 string 타입이다. 3 | 4 | # iterable 형임. 인덱스가 존재한다 5 | 6 | a = 'Life is short, You need Python' 7 | print(a[0]) 8 | # L 9 | # 0번 인덱스의 'L'을 출력하였다 10 | 11 | print(a[0:4]) 12 | # Life 13 | # 슬라이싱 또한 가능 14 | 15 | # 문자열 선언 16 | a = 'Hello' 17 | a = "Hello" 18 | # 특별한 경우가 아니라면 작은따옴표 사용 19 | 20 | a = ''' 21 | hello 22 | my name is 23 | goming 24 | ''' 25 | 26 | a = """ 27 | hello 28 | my name is 29 | goming 30 | """ 31 | 32 | # 따옴표 3개를 연속으로 이어 붙여서 선언할 수도 있음 33 | # 1. """를 사용해서 문자열에 '를 넣고 싶은 경우 또는 '''으로 ". 34 | # 2. 여러 줄에 걸쳐 문자열을 표현하기 위해서. 35 | -------------------------------------------------------------------------------- /Python/003. Iterable/Non-Sequence/Dictionary/Dictionary.py: -------------------------------------------------------------------------------- 1 | # 딕셔너리란 '사전' 이란 뜻임 2 | # 사람을 예로 들자면, 사람의 이름 : 김윤재, 성별 : 남자, 나이 : 17 3 | # Key와 vaule라는 것을 한 쌍으로 가진 자료형이다. 4 | 5 | # 딕셔너리는 시퀀스 자료형과는 달리 Key를 통해 value를 얻는다. 6 | # 이름이 무엇인가요 -> 라면 이름에 해당되는 vaule값을 반환해 그 이름 값을 얻게 되는 것이다. 7 | 8 | dic = {'name': 'Goming', 'age': '17', 'birth': '0706'} 9 | # 딕셔너리는 {과 }. 중괄호로 둘러싸여 있음. 10 | # {key: vaule} 형태임 11 | 12 | # Key에는 변하지 않는 값을 사용해야 하고, vaule 값에는 변하는 값과 변하지 않는 값 모두 사용할 수 있다. 13 | 14 | 15 | # -- 딕셔너리 쌍 추가 16 | a = {1: 'a'} 17 | a[2] = 'b' 18 | print(a) 19 | # {1: 'a', 2: 'b'} 20 | 21 | a['name'] = 'Goming' 22 | print(a) 23 | # {1: 'a', 2: 'b', 'name': 'Goming'} 24 | 25 | 26 | # 딕셔너리 쌍 삭제 27 | del a['name'] 28 | print(a) 29 | # {1: 'a', 2: 'b'} 30 | 31 | 32 | # -- 딕셔너리 기타 메서드 33 | print(a.keys()) 34 | # 딕셔너리의 key만 리스트로 반환 35 | # dict_keys([1, 2]) 36 | 37 | print(a.values()) 38 | # 딕셔너리의 value만 리스트로 반환 39 | # dict_values(['a', 'b']) 40 | 41 | print(a.items()) 42 | # 딕셔너리의 item을 (key, value) 형태의 튜플로 이루어진 리스트로 반환 43 | # dict_items([(1, 'a'), (2, 'b')]) 44 | 45 | a.clear() 46 | # 클리어 -------------------------------------------------------------------------------- /Python/003. Iterable/Non-Sequence/Set/Set.py: -------------------------------------------------------------------------------- 1 | # Set . 수학의 집합과 비슷함 2 | # Set의 가장 큰 특징 3 | 4 | # 1. 중복을 허용하지 않는다. 5 | # 2. 순서가 없다. 6 | 7 | # 자료형의 중복을 제거하기 위해서 사용되기도 함 8 | s1 = set([1, 2, 3]) 9 | print(s1) 10 | # {1, 2, 3} 11 | 12 | s2 = set("Hello") 13 | print(s2) 14 | # {'e', 'H', 'l', 'o'} 15 | # l이 2번 있기 때문에 중복을 제거하고 1개만 출력. 순서가 없음 16 | 17 | 18 | # -- 교집합, 합집합 , 차집합 구하기 19 | 20 | s1 = set([1, 2, 3, 4, 5, 6]) 21 | s2 = set([4, 5, 6, 7, 8, 9]) 22 | print(s1 & s2) 23 | # 둘의 교집합인 4, 5, 6이 출력 24 | 25 | s1.intersection(s2) 26 | # intersection 함수를 통해 s1와 s2의 교집합을 출력할 수도 있음. 27 | 28 | 29 | print(s1 | s2) 30 | # 합집합 . {1, 2, 3, 4, 5, 6, 7, 8, 9}. 이 때 4, 5, 6처럼 중복된 값은 한 번만 출력된다. 31 | 32 | s1.union(s2) 33 | # union 함수를 통해 s1와 s2의 합집합을 구할 수 있음 34 | 35 | 36 | print(s1 - s2) 37 | # {1, 2, 3} 38 | # s1과 s2에서 중복된 값을 제거한 나머지를 리턴함 39 | print(s2 - s1) 40 | # {8, 9, 7} 41 | 42 | s1.difference(s2) 43 | # difference 함수를 통해 차집합을 구할 수 있다. 44 | 45 | 46 | # Set 기타 메서드 47 | s1.add(7) 48 | print(s1) 49 | # 7 요소 추가 50 | 51 | s1.update([7, 8, 9]) 52 | print(s1) 53 | # 7, 8, 9를 추가시켜 update함 54 | 55 | s1.remove(2) 56 | print(s1) 57 | # 2 요소 제거 -------------------------------------------------------------------------------- /Python/003. Iterable/Sequence/List/main.py: -------------------------------------------------------------------------------- 1 | # 반복 가능한 자료형을 iterable 자료형이라고 하며 순서가 존재한다. 2 | 3 | l = [1, 2, 3, 4, 5, 6] 4 | # 다른 언어에서의 배열과 비슷한 형태를 하고 있음 5 | 6 | # 배열(Array)과 다른 점은, 7 | # 배열에서는 인덱스에 따라 값을 유지하기 때문에 빈 자리가 남게 된다. 8 | # 하지만 List는 중간에 빈 부분이 있으면 뒤에 인덱스의 값이 앞으로 와서 빈틈없이 연속적으로 위치한다. 9 | 10 | # -- 인덱스가 중요한 경우는 배열을 사용, 인덱스가 중요하지 않은 경우에는 리스트를 사용한다. 11 | 12 | 13 | # 요소 추가 14 | l.append(7) 15 | # 리스트의 맨 끝에 7이라는 값 추가 16 | 17 | l.insert(1, 10) 18 | # 1번 인덱스의 값을 10으로 변경 19 | 20 | 21 | # 인덱싱 22 | l[1] = 10 23 | l[-1] = 9 24 | # Python에서 -1번 인덱스는 맨 뒤에서 첫번째의 위치를 의미함 25 | # [1, 2, 3, 4, 5] 일 때, 5는 4번 인덱스, -1번 인덱스 두 개로 표현 가능함 26 | 27 | 28 | # 슬라이싱 29 | print(l[1:3]) 30 | # 특정 값을 잘라내기 위해 사용한다. 31 | # 슬라이싱의 기본 형태는 [start:end:stride(step)] 32 | # start란 시작 지점, end는 지정된 값의 -1 인덱스까지. ( 9라면 8번 인덱스까지 ), stride는 슬라이싱 할 간격을 의마함 33 | 34 | l[1:3] = [1, 2] 35 | # 특정 값을 바꿈 36 | 37 | print(l[:]) 38 | # 아무 숫자도 지정하지 않으면 처음부터 끝까지 39 | print(l[1:]) 40 | # 1번 인덱스부터 끝까지 41 | print(l[:4]) 42 | # 처음 인덱스부터 3번 까지 43 | 44 | 45 | # 요소 제거 46 | del l[0] 47 | del l[:2] 48 | # 말 그대로 delete. 값을 제거함 49 | 50 | # 기타 메서드 51 | l.sort() 52 | # 낮은 순서대로 정렬, 알파벳은 아스키 코드 순서로 정렬됨. 53 | 54 | l.reverse() 55 | # 거꾸로 56 | 57 | print(l.count(1)) 58 | # list 내 1의 갯수 59 | 60 | print(l.index(2)) 61 | # 2가 최초 반환되는 지점 반환 62 | 63 | print(l.pop()) 64 | # 리스트의 맨 마지막 값을 출력하며 삭제시킴 65 | 66 | l.clear() 67 | # 리스트 클리어 -------------------------------------------------------------------------------- /Python/003. Iterable/Sequence/Tuple/Tuple.py: -------------------------------------------------------------------------------- 1 | # Tuple은 몇 가지 점을 제외하고는 List와 거의 비슷하다. 2 | # 1. 리스트는 [과 ]로 둘러싸지만 튜픙른 (과 )로 둘러싸임 3 | # 2. 튜플은 값의 변경이 불가능하다. 4 | 5 | # Tuple 예시 6 | t1 = () 7 | t2 = (1,) 8 | # 요소 값이 1개일 때 ,를 붙여주지 않으면 t2는 값이 1인 int형 변수가 됨. 9 | t3 = (1, 2, 3) 10 | t4 = 1, 2, 3 11 | # 괄호를 생략해도 무방함. 12 | t5 = ('a', 'b', ('ab', 'cd')) 13 | # Tuple 안의 Tuple 14 | 15 | 16 | # -- Tuple 에서의 인덱싱과 슬라이싱 17 | t1 = (1, 2, 3, 4) 18 | print(t1[2]) 19 | # 3 출력 20 | 21 | print(t1[:2]) 22 | # (1, 2) 출력 23 | 24 | # 튜플 더하기 25 | t1 = (1, 2) 26 | t2 = (3, 4) 27 | print(t1 + t2) 28 | # (1, 2, 3, 4) 29 | 30 | # 튜플 곱하기 31 | print(t1 * 3) 32 | # (1, 2, 1, 2, 1, 2) 33 | # t1의 값을 3번 반복한 값을 리턴 해준다. -------------------------------------------------------------------------------- /Python/Module/Module.py: -------------------------------------------------------------------------------- 1 | import mod1 2 | # mod1을 import함 3 | 4 | from mod1 import sum 5 | # sum이라는 함수만 import함 6 | 7 | from mod1 import * 8 | # *은 mod1 모듈에 있는 모든 것을 import하다는 점이다. 9 | # 하지만 모든 것이 import되는 것은 아니다. 10 | # 자세한 내용은 mod1.py의 주석을 확인하자. 11 | 12 | print(sum(1, 2)) 13 | # import 했기 때문에 사용 가능하다 14 | 15 | new_instance = cal() 16 | print(new_instance.mul(3, 4)) 17 | # class 또한 import 해서 정상적으로 사용이 가능하다. 18 | 19 | print(_private_num) 20 | print(__all_private_num) 21 | -------------------------------------------------------------------------------- /Python/Module/mod1.py: -------------------------------------------------------------------------------- 1 | # 불러서 쓰는 Python 모듈. 2 | # 모듈은 mod1.py에서 컴파일 하는 것이 아닌 Module에서 import해 사용하는 것임. 3 | # 내장 모듈들을 불러와 기능을 사용하는 경우가 많음. 4 | 5 | # 다른 사람들이 이미 만들어 놓은 모듈을 사용할 수도 있고 우리가 직접 만들어서 사용할 수도 있다. 6 | # 역할에 맞게 분리하기 위해 모듈을 사용한다. flask를 할 때에도 한 파일에 모든 기능을 구현하는 것이 아닌 7 | # 여러 파일에 나누어 모듈을 import해 사용하는 식으로 사용된다. 8 | 9 | 10 | def sum(a, b): 11 | return a+b 12 | 13 | 14 | class cal(): 15 | def mul(self, a, b): 16 | return a*b 17 | 18 | 19 | # 함수를 불러와 사용할 수도 있고, 20 | # class를 불러와 사용할 수도 있다. 21 | 22 | num1 = 1 23 | num2 = 2 24 | # 변수 또한 가능하다 25 | 26 | _private_num = 3 27 | # _single_leading_underscore 28 | # 주로 한 모듈 내부에서만 사용하는 private 클래스/함수/변수/메서드를 선언할 때 사용하는 컨벤션이다. 29 | # 이 컨벤션으로 선언하게 되면 from module import *시 _로 시작하는 것들은 모두 임포트에서 무시된다. 30 | # 그러나 파이썬은 완전한 private을 지원하지 않기 때문에 직접 import 하고 호출할 경우 사용이 가능하다. 31 | 32 | __all_private_num = 4 33 | # __double_leading_underscore 34 | # 더블 언더스코어는 클래스 속성명을 맹글링하여 클래스간 속성명의 충돌을 방지하기 위한 용도로 사용된다. 35 | # 하지만 이는 private을 위한 것이 아니며 private으로의 사용도 권장되지 않는다. 36 | 37 | 38 | -------------------------------------------------------------------------------- /Python/closure/closure.py: -------------------------------------------------------------------------------- 1 | # closure 이란 , 함수 선언 안에 함수를 선언하는 방식 2 | def get_sum_func(): 3 | def sum(a, b): 4 | return a + b 5 | return sum 6 | # 내부 함수인 sum을 return 7 | 8 | 9 | sum = get_sum_func() 10 | print(sum(2, 3)) 11 | # 2 + 3 값인 5 출력 12 | 13 | 14 | def get_number_printer(n): 15 | def print_n(): 16 | print(n) 17 | return print_n 18 | 19 | # 내부함수가 외부 함수의 지역변수에 접근할 수 있음 20 | # 외부 함수가 종료됨가 동시에 사라지지 않고 지역변수가 그대로 남아있기 때문 21 | # 이를 closure라고 부름 22 | 23 | 24 | # 내부 함수를 반환하고 지역변수를 가지고 있는 외부 함수가 있다고 하자. 25 | def outer_function(something): 26 | def inner_function(): 27 | print(something) 28 | 29 | return inner_function 30 | return outer_function 31 | 32 | 33 | print_something = outer_function('Hello, world!') 34 | print_something() 35 | # something이 inner_function에서 출력됨. 36 | -------------------------------------------------------------------------------- /Python/decorator/decorator.py: -------------------------------------------------------------------------------- 1 | # 데코레이터는 함수 형태로 동작한다. 2 | 3 | 4 | def decorator(function): 5 | def wrapper(): 6 | print('Func will be called') 7 | 8 | return function() 9 | return wrapper 10 | # decorator 함수에 인자로 전달된 function을 실행하여 그 결과를 반환하는 wrapper 함수 선언 11 | 12 | 13 | def print_Hello(): 14 | print('Hello!') 15 | 16 | 17 | decorated_print_Hello = decorator(print_Hello()) 18 | # decorator 함수는 wrapper 함수를 출력하며 function을 받음. 19 | decorated_print_Hello() 20 | # wrapper 함수를 호출하며, Func will be called 가 출력되며 인자로 넣어준 function이 실행되고 그 결과를 반환한다. 21 | 22 | # 데코레이터를 쓰는 이유는 이미 만들어져 있는 코드를 수정하지 않고도 여러가지 기능을 추가하기 위해서이다. 23 | # 일반적으로 위처럼 데코레이터 함수를 호출하여 새로운 함수를 반환받는 구문은 잘 사용하지 않고, '@' 심볼을 사용 24 | 25 | 26 | @decorator 27 | def print_something(): 28 | print('Hello!') 29 | 30 | 31 | print_something() 32 | # Func will be called와 Hello 가 출력된다 decorator를 사용했기 떄문 33 | # @ 다음 줄에 함수를 선언해 주면 그 함수가 위에서 decorator(function)에서 function으로 들어가짐 34 | 35 | # 인자를 가진 함수를 데코레이팅 하려면, 인자를 추가하고 함수를 호출할 때 인자를 전달하자. 36 | def decorator(func): 37 | def wrapper(*args, **kwargs): 38 | return func(*args, **kwargs) 39 | return wrapper 40 | 41 | 42 | @decorator 43 | def print_msg(msg): 44 | print(msg) 45 | 46 | 47 | print_msg('Hello?') 48 | 49 | # 데코레이터 자체가 인자를 가져야 한다면 def를 하나 추가해주면 됨. 그리고 @decorator(*args) 해주면 됨 50 | # 전달할 인자가 없더라도 함수를 호출하는 형태로 사용해야 한다. 51 | -------------------------------------------------------------------------------- /Python/instance, class, static method/main.py: -------------------------------------------------------------------------------- 1 | # Instance Method의 정의는 클래스 내부에 정의되어있는 함수를 호출할 때, 2 | # Instance(객체)를 필요로 한다는 조건이 있는 것을 알 수 있습니다. 3 | # 이때 첫번째 매개변수는 항상 self 4 | 5 | 6 | class InstMethod: 7 | def __init__(self): 8 | self.name = 'paphopu' 9 | 10 | def print_name(self): 11 | print('my name is {}'.format(self.name)) 12 | 13 | 14 | # 인스턴스를 선언한다. 15 | name_instance = InstMethod() 16 | 17 | # print_name 이라는 함수를 호출하기 위해선 객체를 먼저 정의해줘야합니다. 18 | # 이것이 인스턴스 메소드입니다. 19 | 20 | name_instance.print_name() 21 | 22 | 23 | # # Class Method 24 | 25 | # 첫번째 매개변수를 보내는 일을 하지 않고, 26 | # 클래스 자기 자신을 첫번째 매개변수로 받는 차이가 있습니다. 27 | 28 | # Class Method는 @classmethod 데코레이터를 이용하여 선언합니다. 29 | 30 | # 이 경우 self를 사용하지 않고 cls를 매개변수로 사용하여 31 | # Class Method를 이용합니다. 32 | 33 | 34 | class ClassMethod: 35 | 36 | @classmethod 37 | def print_name(cls): 38 | print('my name is {}'.format(cls.__class__.__name__)) 39 | 40 | 41 | # 객체를 따로 선언해줄 필요없이 함수를 호출할 수 있습니다. 42 | # 이것이 클래스 메소드입니다. 43 | ClassMethod.print_name() 44 | # >>my name is type 45 | 46 | 47 | # # Static Method 48 | 49 | # 인스턴스나 클래스를 인자로 받지 않습니다. 50 | # static method의 특징은 클래스를 통해서도, 51 | # 인스턴스를 통해서도 호출이 가능하다는 점입니다. 52 | 53 | # Static Method는 클래스 내부에 선언되어 클래스 네임스페이드 안에 저장된다 54 | 55 | class StaticMethod: 56 | 57 | @staticmethod 58 | def print_name(name): 59 | return '내 이름은 {} 입니다.'.format(name) 60 | 61 | 62 | # 클래스를 통해서 호출가능 63 | 64 | print(StaticMethod.print_name('minsoo')) 65 | # >>내 이름은 minsoo 입니다. 66 | 67 | # 인스턴스를 통해서도 호출이 가능 68 | 69 | me = StaticMethod() 70 | print(me.print_name('minsoo')) 71 | # >>내 이름은 minsoo 입니다. 72 | 73 | 74 | -------------------------------------------------------------------------------- /Python/override/override.py: -------------------------------------------------------------------------------- 1 | class father(): # class parent 2 | def handsome(self): 3 | print("He's handsome!") 4 | 5 | 6 | class brother(father): 7 | """son""" # brother is handsome 8 | 9 | 10 | class sister(father): 11 | def pretty(self): 12 | print("She's pretty!") 13 | 14 | def handsome(self): # sister is pretty 15 | self.pretty() # it's override 16 | 17 | # 추가로 딸이 상속받은 메소드를 변형시켜도 다른 자식이나 부모까지 영향을 주지 않습니다! 18 | # 왜냐하면 물려받은 것일 뿐이니까요 19 | 20 | 21 | brother = brother() 22 | brother.handsome() 23 | # class 아들은 아빠에게 상속받아 잘생겼다가 출력되었고, 24 | 25 | girl = sister() 26 | girl.handsome() 27 | # class 딸은 이미 상속을 받았지만 예쁘다 라고 사용중이기 때문에 28 | # 잘생겼다를 무시하게 됩니다. (이것을 오버라이딩) 29 | 30 | -------------------------------------------------------------------------------- /Python/super/main.py: -------------------------------------------------------------------------------- 1 | class father(): # 부모 클래스 2 | def handsome(self): 3 | print("He's handsome!") 4 | 5 | 6 | class brother(father): 7 | # 자식클래스(부모클래스) 아빠매소드를 상속받겠다 8 | '''아들''' 9 | 10 | 11 | class sister(father): 12 | # 자식클래스(부모클래스) 아빠매소드를 상속받겠다 13 | def pretty(self): 14 | print("She's pretty!") 15 | 16 | def handsome(self): 17 | super().handsome() 18 | 19 | 20 | brother = brother() 21 | brother.handsome() 22 | 23 | girl = sister() 24 | girl.handsome() # 누락 25 | girl.pretty() 26 | 27 | print() 28 | 29 | 30 | class father(): 31 | def __init__(self, who): 32 | self.who = who 33 | 34 | def handsome(self): 35 | print("{}를 닮아 잘생겼다".format(self.who)) 36 | 37 | 38 | class sister(father): # 자식클래스(부모클래스) 아빠매소드를 상속받겠다 39 | def __init__(self, who, where): 40 | super().__init__(who) 41 | self.where = where 42 | 43 | def choice(self): 44 | print("{} 말이야".format(self.where)) 45 | 46 | def handsome(self): 47 | super().handsome() 48 | 49 | # who 와 handsome()은 부모에게 물려받은 것이기 때문에 50 | # 자식에서 사용하려면 무조건 super()를 사용해야 합니다. 51 | self.choice() 52 | 53 | 54 | girl = sister("Dad", "Face") 55 | girl.handsome() 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About what I Learned 2 | ~~Python 언어를 사용한 코드, example과 기능들을 정리한 repository입니다.~~ 3 | 4 | Python 뿐만이 아닌 무엇이든, 내가 공부하고 공유하고 싶은 기능들을 정리했습니다. 5 | 6 | -------------------------------------------------------------------------------- /Terraform/001. Input Variable.md: -------------------------------------------------------------------------------- 1 | ## Variable 2 | 3 | 변수는 아래와 같이 정의할 수 있다. 4 | 5 | ```shell 6 | variable "variable_name" {} 7 | 8 | variable "region" { 9 | type = "string" 10 | default = "us-east-1" 11 | } 12 | ``` 13 | 14 |
15 | 16 | 여러 리전을 사용하는 경우 하나의 변수를 Map으로 정의해서 리전 별로 지정하면 17 | 18 | var.amis["ap-northeast-1"]와 같이 참조할 수 있고 사용할 때도 의미를 알기 쉬워서 좋다. 19 | 20 | 액세스 키, AMI 등은 하드 코딩해서 직접 넣지 않도록 하자. 21 | 22 | ```shell 23 | provider "aws" { 24 | region = var.region 25 | } 26 | 27 | variable "amis" { 28 | type = "map" 29 | 30 | default = { 31 | "us-east-1" = "ami-b374d5a5" 32 | "us-west-2" = "ami-4b32be2b" 33 | } 34 | } 35 | 36 | resource "aws_instance" "example" { 37 | ami = var.amis[var.region] 38 | instance_type = "t2.micro" 39 | } 40 | ``` 41 | 42 |
43 | 44 | ------- 45 | 46 |
47 | 48 | 커맨드라인에서 -var flag를 사용해서 변수를 설정해 줄 수 있다. 49 | 50 | 예를 들어 terraform apply, plan, refresh 명령어 사용 시. 51 | 52 | ```shell 53 | $ terraform apply \ 54 | -var 'region=us-east-2' 55 | 56 | ``` 57 | 58 |
59 | 60 | terraform.tfvars 라는 파일을 이용해서 61 | 62 | 사용 할 변수를 -var-file flag를 통해 넣어줄 수도 있다. 63 | 64 | ```shell 65 | $ terraform apply \ 66 | -var-file="secret.tfvars" \ 67 | -var-file="production.tfvars" 68 | ``` 69 | 70 | tfvars 파일의 예제는, hashicorp에서 제공하는 best-practice를 참고하자. 71 | 72 | [[Github] terraform.tfvars]() 73 | 74 | -------------------------------------------------------------------------------- /Terraform/README.md: -------------------------------------------------------------------------------- 1 | # TerraForm 2 | 3 | 테라폼(Terraform)은 **HashiCorp**에서 개발한 오픈소스 **IaC(Infrastructure as code)** 소프트웨어다. 4 | 5 | 개발자는 테라폼에서 제공하는 HCL(Hashicorp Configuration Language)라는 고수준 설정 언어(high-level configuration language) 혹은 json 를 이용해서 데이터센터 인프라스트럭처를 정의할 수 있다. 6 | 7 | 하지만 HCL을 사용하는 것을 권장한다. 8 | 9 | 테라폼은 Amazon Web Service, IBM Cloud, Google Cloud Platform, Linode, Microsoft Azure, Oracle Cloud Infrastructure, VMware vSphere, OpenStack 등의 인프라스트럭처 제공자를 지원한다. 10 | 11 | ------ 12 | 13 | 14 | 15 | ## 내가 테라폼을 선택한 이유 16 | 17 | 사실 지금까지 내가 Infrastructure as Code를 사용 할 필요가 없다고 생각했다. 18 | 19 | 기숙사 지원 시스템을 만들면서, 같이 서비스를 구축해가는 선배들이 하나 둘 씩 졸업해가면서, 새로운 신입생이 왔을 때 내가 직접적으로 기술을 전수해 줄 수 없을 지도 모르겠다고 생각했다. 이 기회를 통해 Infra를 코드로 관리하고, 직접적으로 기술을 전수하지 않아도 누구든지 이 프로젝트를 되맡아 할 수 있도록 구축하는 것이 좋다고 생각했다. 20 | 21 | 문서화를 완벽하게 하여 이미 구축해둔 기숙사 시스템을 어떻게 구축했는지 하나 하나 설명하고 전수하는 것도 좋겠지만, 22 | 23 | 그게 코드로 보는 것만큼 직관적일까? 24 | 25 | 26 | 27 | 저자는, 코드가 말보다 인프라에 대한 높은 수준의 설명을 해 줄 수 있다고 생각한다. 28 | 29 | ## 내가 보고 배운 링크들. 30 | [Terraform - getting-started](https://learn.hashicorp.com/terraform/?track=getting-started#getting-started) 31 | 32 | [44bits.io - Terraform 기초 튜토리얼](https://www.44bits.io/ko/post/terraform_introduction_infrastrucute_as_code#%EC%B2%AB-%EB%B2%88%EC%A7%B8-%EB%8B%A8%EA%B3%84---%EC%95%84%EB%A7%88%EC%A1%B4-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%84%A4%EC%A0%95) 33 | 34 | [Outsider - Terraform으로 AWS 관리하기](https://blog.outsider.ne.kr/1260) 35 | -------------------------------------------------------------------------------- /test.md: -------------------------------------------------------------------------------- 1 | 테스트 2 | --------------------------------------------------------------------------------