[ 잡담 ]

Nodemon을 사용하다가 PM2로 갈아타게 되었다.

프로젝트 구조가 Nodejs Express를 사용하여 443, 80번 포트를 사용해야 하는 상황이었다.

설치를 마치고 아래 명령어를 입력하였다.

pm2 start app.js

80번 포트를 사용할 권한이 없다고 에러가 떴다.

Error: listen EACCES 0.0.0.0:80

[ 본론 ]

순서대로 입력해준다.

sudo apt-get install authbind
sudo touch /etc/authbind/byport/80
sudo chown ubuntu /etc/authbind/byport/80
sudo chmod 755 /etc/authbind/byport/80
sudo touch /etc/authbind/byport/443
sudo chown ubuntu /etc/authbind/byport/443
sudo chmod 755 /etc/authbind/byport/443

그리고

authbind --deep pm2 start app.js

입력하니깐 잘됐다.

 

출처

alnova2.tistory.com/1113

도커의 "ㄷ"도 잘모르지만 금방 까먹을 것 같아서 정리!

 

1. 도커 로그인

docker hub에 가입하고 해당 계정의로 로그인하면 된다.

https://hub.docker.com/

 

Docker Hub

Docker Certified:Trusted & Supported Products Certified Containers provide ISV apps available as containers. Certified Plugins for networking and volumes in containers. Certified Infrastructure delivers an optimized and validated Docker platform for enterp

hub.docker.com

docker login

 

2. 이미지 관리

- LIST

docker images

- DELETE
ex) docker rmi 637ba1465942 -f

docker rmi <image id> -f

- BUILD
ex) docker build --tag test/project:v0.0.1 .

docker build --tag <docker hub name>/<repository name>:<tag value> .


뒤에 .은 dockerfile의 위치를 나타내는 것 같다.


- PUSH
ex) docker push test/project:v0.0.1

docker push <docker hub name>/<repository name>:<tag value>

 

에러 없이 잘 PUSH되었다면 docker hub에서 이미지가 추가된 것을 확인할 수 있다.


- PULL
docker pull test/project:v0.0.1

docker pull <docker hub name>/<repository name>:<tag value>

PUSH로 올린 이미지를 받고 싶다면 위 명령어로 받을 수 있다.

 

3. 컨테이너 관리

- LIST

docker ps

- STOP

docker stop <container id>

- DELETE

docker rm <container id>

'Develop > Docker' 카테고리의 다른 글

[Docker] 설치 - ubuntu 18.04, windows 10  (0) 2020.06.19

[ 잡담 ]

"Docker"이라고 하면 라쿠텐 면접 때 들었던 질문이 떠오른다.

AWS 서비스를 여러가지 사용해 봤던 경험을 풀었는데 돌아오는 질문은 Docker를 사용해 본적이 있는가였다. 당시 나는 도커라는 이름만 들어봤지 정확히 어떤 것인지 전혀 알지 못했고 제대로 대답하지 못했다. 그 후 도커를 공부해보려고 했다.

공식 홈페이지에서 도커의 개요를 보면 도커란 "Docker는 컨테이너 이동을 주도하는 회사이며 하이브리드 클라우드의 모든 애플리케이션을 처리할 수 있는 유일한 컨테이너 플랫폼 제공 업체입니다" 라고 쓰여있다.

당시 졸업작품을 개발하고 있었는데 어디에 어떻게 써야할지 감을 잡을 수 없었고 사용하는 것을 포기했다. 하지만 이번에 "거래해요 동물의숲"이라는 프로젝트를 개발하면서 도커를 처음 접하게 되었다.

"거래해요 동물의숲"이란 내가 처음 실제 사용자들에게 유치하는 서비스이다.

이 프로젝트에서 나는 백엔드를 담당했는데 서비스를 배포하고 업데이트 환경을 구성하는데 서버의 다운 타임을 줄여줄 방법이 무었이 있을까 찾아보던 도중 도커가 제격이라는 생각이었다.

결국 아직 학습 부족으로 인증서 문제 때문에 도커를 사용하지 않고 있지만 더욱 공부해서 다시 적용시켜볼 생각이다.

[ 본론 ]

그럼 본론으로 들어가 도커 설치법을 알아보겠다. 상세한 내용은 전혀 모른다. 그냥 따라하면 잘되길래 정리해서 올려본다. 다음에 내가 또 설치해야할 일이 있을지도 모르니 ㅎㅎ...

설치 환경

 

1. windows

그냥 아래 링크타고 들어가서 installer 다운받고 설치했다!

https://hub.docker.com/editions/community/docker-ce-desktop-windows/

 

Docker Desktop for Windows - Docker Hub

Docker Desktop for Windows Docker Desktop for Windows is Docker designed to run on Windows 10. It is a native Windows application that provides an easy-to-use development environment for building, shipping, and running dockerized apps. Docker Desktop for W

hub.docker.com

 

2. ubuntu 18.04

2-1. 아래의 명령어를 사용하여 설치에 필요한 패키지들을 설치해 주시기 바랍니다.

$ sudo apt-get update && sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

 

2-2. 아래의 명령어를 사용하여 도커의 공식 GPG 키와 저장소를 추가해 주시기 바랍니다.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

 

2-3. 그리고 아래의 명령어를 사용하여 docker 패키지가 검색되는지 확인해 주시기 바랍니다.

$ sudo apt-get update && sudo apt-cache search docker-ce

만약 현재 우분투 버전에서 설치 패키지가 검색된다면 아래와 같은 내용이 출력될 것입니다.

docker-ce - Docker: the open-source application container engine

 

2-4. 그 다음 아래의 명령어를 사용하여 도커 CE 에디션을 설치해 주시면 됩니다.

$ sudo apt-get update && sudo apt-get install docker-ce

 

2-5. 그리고 일반 사용자계정으로 docker 명령어를 사용하기 위해서는 아래의 명령어로 그룹을 추가해 주시면 됩니다.
아래의 명령어는 ubuntu라는 사용자를 docker그룹에 추가하는 내용입니다.

$ sudo usermod -aG docker $USER

 

이제 docker --version 을 입력하면 버전이 잘나오는 것을 확인할 수 있을 것이다.

'Develop > Docker' 카테고리의 다른 글

[Docker] 명령어 정리  (0) 2020.06.20

RDS의 세팅을 마치고 사용을 할려고 하면 발목을 잡는 것이 한글 깨짐이다.

구글링하면서 여러가지 해봤지만 해결되지 않았다.

일반적으로 구글링하면 나오는 방법부터 내가 적용한 방법까지 적어보겠다.

1. 구글링하면 나오는 첫번째 방법

나는 파라미터를 새로 생성하지 않고 기존 파라미터를 수정해서 사용할려고 했지만 기존 파라미터는 수정이 불가능했다.
꼭 아래와 같이 파라미터 새로 생성 -> 편집 -> 적용 순서로 해주자.

1-1

파라미터 그룹을 선택한다.

1-2

그룹 이름과 설명을 대충 넣고 생성한다.

1-3

해당 파라미터에 들어가서 검색창에 character_set을 입력하면 나오는 친구들의 값을 전부 UTF8 로 변경해주자.

character-set-client : utf8
character-set-connection : utf8
character-set-database : utf8
character-set-filesystem : utf8
character-set-results : utf8
character-set-filesystem : utf8

1-4

그리고 DATABASE 수정에 들어가면 파라미터 그룹을 변경하고 DB를 재부팅하면 끝이다.

 


 

2. 구글링하면 나오는 두번째 방법

그럴 경우에 파라미터에서 collation을 검색해서 나오는 값들 또한 변경해주면 된다는 말이 있어서 해봤다.

collation_connection : utf8_general_ci
collation_server : utf8_general_ci


3. 나를 구원해준 마지막 방법

mysql 쿼리로 

alter database DB_NAME default character set utf8 collate utf8_general_ci;

이거 쿼리로 쏴주니깐 고쳐졌다.

 

출처

https://designdevelop.tistory.com/68

https://designdevelop.tistory.com/68 [DesignDevelop]

[ 주의 ] 삽질하면서 코딩한 경험을 바탕으로 작성한 것임으로 틀린것도 많으니 더 좋은 정보가 있으면 알려주세요!

[ 잡담 ]

요즘들어 새로 시작한 프로젝트가 있어서 12시에 기상해서 새벽 4~6시까지 코딩만 죽어라 하고 있다.

실제로 유저들에게 상용시킬 서비스를 제작하는 것이란 대학교 때 졸업작품을 개발하는 것과는 비교도 안될 정도로 많은 변수를 생각해야하기 때문에 시간이 많이 든다.

덕분에 정말 많은 삽질을 하고 있다. 하지만 이 삽질 끝에 문제를 해결하고 잘 작동하는 모습을 보면 너무 너무 재밌다.

그럼 본론으로 들어가 Multer에 대해서 알아보겠다.

+ 지금까지 Multer를 사용하면서 겪은 3가지 삽질

[ Multer ]

정의: Multersms Multypart / form-data 형식의 Request을 다루기 위한 Node.js 미들웨어이다.

설치

> npm install --save multer

1. Formdata 받기

나는 처음에 Multer의 존재를 몰랐다. 프론트에서 Formdata를 axios로 넘겨줬지만 req.body, res.file, res.files 전부 console.log로 찍어봤지만 빈값만 들어가 있었다. 이게 새벽 2~4시까지 골머리를 썩혔다.

찾다 찾다보니 Multer라는 친구를 발견했고 아래와 같이 작성해주면 formdata 값을 받을 수 있다고 해서 적용해 봤다.

1) single

  • 파일 한 개만 받을 경우에 사용한다.
  • req.file에 이미지 데이터가 담겨있다.
  • avatar는 formdata.append("avatar": value); 에서 value의 key값을 의미한다.
app.post('/profile', upload.single('avatar'), function (req, res, next) {})

2) array

  • 여러개의 이미지 파일을 하나의 key값으로 받아올 수 있다.
  • 구분없이 여러개의 이미지를 받을 때 좋은듯?
  • req.files에 데이터가 담겨있다.
  • 12 숫자는 넘겨 받는 이미지 갯 수를 나타낸다. 한계를 정해두고싶지 않다면 그냥 key값만 적으면 된다.
app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {})

3) fields

  • 전체적으로 array와 큰 차이를 모르겠다. 확장 버전인듯?
  • key값을 구분하여 데이터를 분류해서 받고 싶다면 사용하자.
  • req.file에 데이터가 담겨있다.
var cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {})

4) none

  • 안써봐서 몰라.
  • text만 담긴 formdata 받으라고 한다.

5) any

  • 마찬가지로 안써봄.
  • 유선으로 오는 모든 파일 다 받을 수 있다고 적혀잇다.

2. 그래도 값이 넘어오지 않는 경우

자! 열심히 알아봤다. 이제 받아져야지? 라고 생각한 나의 실수였다. 계속해서 데이터가 넘어오지 않았다. 여기서 삽질 또 시작.

문제는 프론트의 axios에 있었다. axios를 사용하면 받아지지 않았지만 아래의 코드를 사용하니 값이 넘어왔다.

var req = new XMLHttpRequest()
var file = new Blob(['This is a test'], { type: 'text/plain' })
var data = new FormData()

data.append('photo', file, 'test.txt')

req.open('POST', '/upload')
req.send(data)

3. 저장 폴더를 유동적으로 바꾸기

난 aws s3에 이미지 파일을 저장해야했기 때문에 multer-s3도 사용했다.

multer의 구조는 좀 이상했다. 프론트로 받은 데이터를 기반으로 이미지가 저장될 폴더를 만들고 싶었지만 

app.post('/image', s3.upload.single('avatar'), function (req, res, next) {})

이렇게 req로 받기도 전에 파일에 저장을 때리는데 어떻게 하란 말인가...

그래서 아래와 같은 방법으로 파일명을 고쳐보기로 했다.

/* router file */

const express = require('express');
const router = express.Router();
const ctrl = require('../api/c_board');
const multer = require("multer");
const {new_s3_storage} = require("../utils/u_s3_storage");


// s3를 빈 값으로 선언했더니 아래 라우터에서 빈 값에 
// array() 함수가 없다고 에러가 떠서 저장 폴더가 고정된 s3객체를 넘겨줬다
let s3 = require("../utils/u_s3");

// 해당 middleware부터 먼저 실행되고 아래 /image가 실행된다
router.use('/image', (req, res, next) => {

    // 프론트로부터 받은 데이터
    var bo_id = req.headers.bo_id;
    
    // 데이터를 매개변수로 넘겨 새로운 s3 storage 객체 생성
    var s3_storage = new_s3_storage(bo_id);
    
    // 기존 s3에 새로만들어진 s3 storage로 덮어준다
    s3 = multer({ storage : s3_storage });
    
    next();
})

router.post('/image', s3.array('img'), ctrl.image);

module.exports = router;

middleware를 사용해서 /image로 들어가기 전에 header 값으로 프론트로부터 받은 데이터(req.headers.bo_id)로 새로운 storage 객체를 만들어 s3에 덮어씌울 계획이었다.

 결과는 실패!

let s3 = require("../utils/u_s3"); 값이 middleware에서 아무리 덮어씌어도 안바뀌더라.

그렇게 구글을 이리저리 떠돌면서 해답을 찾던 도중 정답을 발견했다.

▼ 완성 코드

/* router file */

// lib
const express = require('express');
const router = express.Router();
const ctrl = require('../api/c_board');

// modules
let s3 = require("../utils/u_s3");

router.post('/image', s3.upload.array('img'), ctrl.image);

module.exports = router;

/* ../utils/u_s3.js */

// lib
const AWS = require('aws-sdk');
const multer = require('multer');
const multerS3 = require('multer-s3');
const path = require('path');

// config
const aws_crediential = require("../config/aws");

const s3 = new AWS.S3(aws_crediential);

let params = {
  Bucket: 'deac-project',
  ACL: 'public-read-write'
};

let s3Storage = multerS3({
  s3: s3,
  bucket: params.Bucket,
  key: function(req, file, cb) {
    // 요거 하나로 해결
    var bo_id = req.headers.bo_id;
    let extension = path.extname(file.originalname);
    let basename = path.basename(file.originalname, extension);
    // 아래 코드에서 header로 받은 bo_id를 활용하여 저장되는 파일이 유동적으로 바뀜
    cb(null, `images/${bo_id}/${basename}-${Date.now()}${extension}`);
  },
  acl: 'public-read-write',
  contentDisposition: 'attachment',
  serverSideEncryption: 'AES256'
});

exports.upload = multer({ storage: s3Storage });

그냥 multerS3에 있는 key 함수에서 req.headers.bo_id를 사용하니 불러와졌다.

multerS3안의 key함수의 req에도 프론트에서 보낸 데이터가 똑같이 포함되어 있을 줄은 몰랐다.

file데이터만 있을줄 알았는데...

 

이렇게 삽질이 끝났다.

 

출처

https://velog.io/@josworks27/2020-01-18-0001-%EC%9E%91%EC%84%B1%EB%90%A8-qrk5iamlmv

'Sequelize' 에 대해 알아보자!

프로젝트를 하면서 서버 개발은 PHP를 기반으로 하는 프레임워크인 Laravel을 가장 많이 사용했다.

이번에 새로운 프로젝트를 진행하면서 Laravel 대신 Nodejs를 사용하게 되었다.

서버의 제일 기본적인 역할은 DB를 탐색하여 프론트에서 요청하는 사항에 맞게 데이터를 돌려주는 역할이다. Laravel은 컨트롤러에서 쉽게 쿼리문을 DB에 보내 탐색할 수 있다. 하지만 Nodejs는 'Sequelize' 라는 라이브러리를 사용하여 MySQL에 접근해야 한다.

즉, 'Sequelize'를 사용하면 자바스크립트 코드로 MySQL을 제어할 수 있게 된다.

이론적인 자세한 내용은 나도 오늘 처음 만져보기에 모른다. 어떻게 사용하는지에 대해 차근차근 알아보자!

시작하기 전 준비물!

1. Nodejs
2. MySQL

1. sequelize-cli 를 설치해주자.

> npm i sequelize mysql2
> npm i -g sequelize-cli

i 는 install 의 약자이고 둘 다 사용해도 문제없다.
-g 는 sequelize-cli 를 전역에 설치한다는 의미로 설치를 마치고 아무 커맨드 창에서나 sequelize 를 호출할 수 있다.

2. sequelize 를 프로젝트 폴더에 설치하자.

> sequelize init

위 명령어를 입력했지만 "이 시스템에서 스크립트를 실행할 수 없으므로 파일을 로드할 수 없습니다" 이렇게 뜰 수도 있다. 권한에 맞지 않는 실행이으로 뜨는 에러다.

만약 위 설명과 같은 문제가 생긴다면 아래의 코드를 입력해주자.

> Set-ExecutionPolicy RemoteSigned

그리고 다시 sequelize init 를 입력하면 config, models, migrations, seeders 폴더가 생성된다.

3. config.json 을 수정하여 DB를 연결해주자.

/* config/config.json */

{
  "development": {
    "username": "root", // DB 계정
    "password": "", // DB 비밀번호
    "database": "test", // DB 이름
    "host": "127.0.0.1", // DB 주소
    "dialect": "mysql",
    "operatorsAliases": false
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "operatorsAliases": false
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "operatorsAliases": false
  }
}

주석이 달린 부분을 자신의 DB에 맞게 수정해주자.

4. 모델 정의하기.

migration을 할 수 있는 두 가지 방법이 존재한다. '직접 파일을 만들어 정의하기', '명령어로 정의하기'

1) 직접 파일을 만들어 정의하기

models 폴더를 보면 index.js 파일이 존재한다.
index.js 파일은 models 폴더 내에 있는 파일들을 읽고, 그것들을 모델로 정의한다. 

그렇다면 models 파일 안에 임의로 user.js 파일을 생성해 보자

/* models/user.js */

module.exports = (sequelize, DataTypes) => { 
  return sequelize.define('user', { 
    useremail: { 
      type: DataTypes.STRING(20), 
      allowNull: false, 
      unique: true, 
    }, 
    password: { 
      type: DataTypes.STRING(100), 
      allowNull: false, 
    }, 
    name: { 
      type: DataTypes.STRING(10), 
      allowNull: false, 
    }, 
  }); 
}

id, createdAt, updateAt 은 자동으로 생성해준다.

models/index.js에 user.js의 존재를 알려주자.

db.User = require('./user')(sequelize, Sequelize);

요렇게 한 줄 추가 시켜주자.

프로젝트 파일에 app.js 파일을 생성해주고 아래의 코드를 입력해주자.

var sequelize = require('./models').sequelize; 

sequelize.sync();

그리고 node로 app.js를 실행시켜주면 마이그레이션이 된다.

> node app

 

2) 명령어로 정의하기

파일을 만들고 코드를 쓰는 것이 귀찮은 사람은 한 줄의 명령어로 모델을 정의할 수 있다.

명령어 기본 문법

sequelize model:create --name TABLE_NAME  --attributes "COLUMN1:type, COLUMN2:type, COLUMN3:type"

예) User 모델을 생성하는 명령어

sequelize model:create --name user --attributes nickName: string, passWord: string

migrations 에 날짜가 적힌 js 파일, models에는 user.js 파일이 생성되었다.

sequelize db:migrate

이 명령어를 입력하면 마이그레이션이 완료된다.

 

더 다양한 조건을 추가하고 싶으면 아래 표를 참고하자.

이름 Type Attribute Description
type String , DataTypes    
allowNull Boolean default: true null가능, 불가능
defaultValue any default: null 초기 값
unique String , Boolean default: false 겹치는 값의 존재 가능 여부
primaryKey Boolean default: false  
field String default: null  
autoIncrement Boolean default: false 값을 1씩 증가해서 저장
comment String default: null  
references String , Model default: null  
references.model String , Model    
references.key String default: 'id'  
onUpdate String    
onDelete String    
get Function    
set Function    

 

출처

https://www.hahwul.com/2017/08/powershell-execution-of-scripts-is.html

https://medium.com/wasd/node-js%EC%97%90%EC%84%9C-mysql-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-1-b4b69ce7433f

'Develop > Node.js' 카테고리의 다른 글

[Nodejs] 실패 없이 무료로 HTTPS 등록하기  (0) 2020.06.20
PM2 80, 443포트 사용  (0) 2020.06.20
[Nodejs] Multer - Formdata 전송  (0) 2020.05.25

아마존 웹 서비스의 기원  

  IT에 관련된 지식이 없는 사람에게 아마존(Amazon)이 어떤 기업이냐 물어본다면 '세계에서 가장 큰 온라인 오픈마켓이 아니냐?'라는 답변이 돌아올 것이다. 틀린 말이 아니다. 하지만 과연 쇼핑몰 하나만으로 구글-애플을 제치고 브랜드 가치 1위의 기업에 거듭날 수 있었을까? 

  초기 아마존은 온라인 오픈마켓만을 운영했었다. 기업의 규모가 점점 커지면서 '블랙 프라이데이'와 같이 할인 행사 기간에 웹 사이트에 많은 사용자가 몰려들어 서버에 과부하가 걸리기 시작했다. 사용자들에게 불편함을 덜어주기 위해 아마존은 막대한 양의 서버를 사들였다. 

  서버 문제는 사라졌지만 트래픽이 몰리지 않는 날엔 그 많은 양의 서버를 돌릴 필요가 없었다. 그래서 아마존은 놀고 있는 서버를 개인, 기업들에 비용을 받고 대여해주는 사업을 시작하게 되었다. 2002년 아마존 웹 서비스를 시작했다.

 

아마존 웹 서비스란?

  아마존에서 제공하는 클라우드 컴퓨팅 서비스

  쉽게 설명하기 위해 내가 좋은 아이디어가 하나 떠올라서  IT사업을 진행한다고 가정해보자. 24시간 동안 내 서비스를 제공하기 위해서는 24시간 동안 작동되는 서버 컴퓨터가 필요하다. 매우 작은 프로젝트라면 컴퓨터 한 대로 충분할 것이다. 하지만 일반적으로 웹 서버, 데이터베이스 서버 등 많은 서버가 필요하다. 이 서버들을 들여놓을 초기 자금이 없다면 시작도 전에 포기해야 할까? 또 처음에는 평균 사용자가 100명이었는데 100,000명으로 늘어나면 서버를 확장하기 위해 얼마나 번거로운 작업이 많이 필요할까... 

  AWS를 사용하면 이런 문제를 쉽게 해결해 준다.

  1. 비용 절감

  AWS에서 이미 다양한 성능의 서버를 가지고 있기 때문에 내가 원하는 성능에 맞춰 커스텀 하여 우린 돈을 주고 빌리기만 하면 된다. 휴대폰 살 때 「일시불로 긁을 것이냐」 「할부로 천천히 낼 것이냐」 의 차이라고 보면 될 것 같다.

  2. 확장성

  상황에 따라 서버를 확장하거나 감축할 때 마우스 클릭 몇 번으로 정말 쉽게 처리할 수 있다. 

  AI, Blockchain, IoT 등 다양한 클라우드 서비스를 제공하고 있다. 이러한 다양한 서비스를 쉽게 연동 할 수 있도록 서비스를 제공하고 있다.

  3. 안전성

  서버를 전 세계 곳곳에 설치해 뒀기 때문에 자연재해로 회사가 사라져도 서비스를 안전하게 운영할 수 있다. 

  무엇보다 비용 절감에 있어서 메리트가 있기 때문에 다양한 스타트기업이 AWS를 활용하여 새로운 사업을 시작한다.


전하고 싶은 말...

  나(글쓴이)는 대학생 때 처음 AWS를 알게 되었다. 자취방에서는 전용 서버가 한 대 있었다. 서버용으로만 쓰는 것이 아니라 게임도 하고 웹툰도 보고 다양한 용도로 사용하다 보니 매일 켜두는 것도 컴퓨터에 부담이 가는 것 같고 프로젝트를 진행하던 도중 서버가 다운되거나 하면 너무 불편할 것 같아 클라우드 컴퓨팅 서비스에 대해서 찾아보게 되었다. 하지만 당시 구글링에 서툴렀던 나는 온통 영어로 된 검색 결과에 지쳐 온라인 수업을 통해서 AWS를 공부하기 시작했다.

나처럼 처음 AWS를 접하고 고군분투하고 있는 사람들에게 조금이나마 도움이 되길 바라는 마음으로 글을 작성한다.

 

출처: https://jobc.tistory.com/113

+ Recent posts