1. 실행 컨텍스트란?

자바스크립트 코드가 실행되고 있는 구역 또는 범위에 대한 정보를 저장하고 있는 객체입니다.

자바스크립트 엔진은 스크립트 혹은 함수를 실행할 때 새로운 컨텍스트를 만들고, 실행 스택에 쌓습니다. 

실행 스택이란 실행 컨텍스트가 생성될 때 마다 실행 컨텍스트를 쌓고 마지막으로 쌓인 실행 컨텍스트 부터 차례대로 실행하는 후입선출 자료구조입니다.

 

2. 실행 컨텍스트의 종류

1) Global Exception Context
자바스크립트 엔진이 실행될 때 가장 먼저 만드는 실행 컨텍스트입니다.
전역 컨텍스트라고 하며, window 객체를 만들고 전역 컨텍스트의 this를 window 객체로 할당합니다.

그리고 이후에 생성되는 모든 전역 변수, 함수는 window 객체에 저장됩니다.

2) Function Execution Context
함수가 호출되면, 함수의 실행 컨텍스트가 생성됩니다.

3) Eval Function Exception
사용되지 않음

 

실행 컨텍스트의 구조

ExecutionContext = {
    LexicalEnvironment : { 
    	EnvironmentRecords : {
           //function or variable
        },
        outer : (LexicalEnvironment),
        ThisBinding : (object)
    },
    
    VariableEnvironment : {(LexicalEnvironment와 동일한 구조)}
}

 

3. 실행 컨텍스트의 두가지 단계

모든 실행 컨텍스트는 Create 단계 Execution 단계를 통해 생성됩니다.

1) Create 단계

Create 단계에서 LexicalEnvironment 컴포넌트 VariableEnvironment 컴포넌트를 생성합니다.
두 컴포넌트가 생성될 때, VariableEnvironment 컴포넌트는 LexicalEnvironment 컴포넌트를 참조합니다.
그러다가 자바스크립트의 코드에 따라 참조가 바뀌기도 합니다.
executionContext.LexicalEnvironment = executionContext.VariableEnvironment;

 

 

1.1) LexicalEnvironment 

LexicalEnvironment 컴포넌트는 변수나 함수 등의 식별자를 저장하는 EnvironmentRecords 객체와 외부 LexicalEnvironment 컴포넌트를 참조하는 outer 그리고 this로 구성됩니다. 
outer는 스코프 탐색을 위해 사용됩니다.

LexicalEnvironment 컴포넌트는 3가지 동작을 합니다.

1) 변수와 함수의 저장공간을 메모리에 할당
실행 컨텍스트 내에서 선언된 변수와 함수의 저장공간을 메모리에 할당하고 EnvironmentRecords라는 객체에 저장합니다.

2) 외부 실행 컨텍스트의 LexicalEnvironment를 저장
코드를 실행하다가 특정 변수나 함수를 마주하면 LexicalEnviromemt에서 찾는데 찾지 못했을 경우 외부 LexicalEnvironment 에서 찾습니다. (scope chain)

3) 실핼 컨텍스트의 This 값을 지정
this 값은 이 단계에서 결정됩니다. 전역 실행 컨텍스트의 this 는 global object입니다. 

this 값은 함수를 호출한 객체를 가리키게 됩니다. 

 

this를 이해하기 위해 간단한 소스를 보겠습니다.

var player = {
    lastName : 'son',
    firstName : 'heung min',
    name : function(){
       console.log(`${this.lastName} ${this.firstName}`);
    }
}

player.name(); // son heung min

var getName = player.name;

getName(); // undefined undefined
// == window.getName()
player.name()은 player 객체가 호출했기 때문에 this값은 player 객체입니다.

getName()은 player.name 함수를 대입받았고, 그대로 실행 했기 때문에 this값은 window 객체를 가리킵니다.

 

정리하면 Create 단계에서는
1) 변수, 함수, 인자를 만들고 EnvronmentRecords에 저장합니다.
2) 외부 실행 컨텍스트를 가리킵니다. (Scope Chain)
3) 실행 컨텍스트 내에 선언된 변수와 함수를 찾아 메모리에 할당합니다. (호이스팅)
4) this가 결정됩니다.

2) Execution 단계

실행 컨텍스트 내에 코드들을 위에서 한줄 씩 읽으면서 선언해 두었던 변수에 값이 할당됩니다.

 


참조

https://velog.io/@imacoolgirlyo/JS-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-Hoisting-The-Execution-Context-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-6bjsmmlmgy

https://meetup.toast.com/posts/129

 

1. Git Repository 생성

2020/12/02 - [IT/git] - [Git] github를 이용한 Git Repository 만들기
 

[Git] github를 이용한 Git Repository 만들기

1. github 회원 가입하기 https://github.com/ GitHub: Where the world builds software GitHub is where over 50 million developers shape the future of software, together. Contribute to the open source..

bamdule.tistory.com

2. 생성한 Git Repository의 Settings로 이동 후 GitHub Pages 설정

 branch를 master로 선택후 save합니다.

ex) https://bamdule.github.io/myRepo/

위와 같은 주소가 생성된 것을 볼 수 있습니다.

3. index.html을 올려서 실행해보기

해당 주소로 이동하면 404 File Not Found 페이지가 노출됩니다.

소스 폴더에 index.html 파일을 만들고 아래와 같이 입력합니다.

<!DOCTYPE html>
<html>
    <head>
        <title>Github web page</title>
    </head>
    <body>
	<h1>Hello!</h1>
	<h3>Welcome</h3>
    </body>
</html>

index.html을 git repository에 올린 후 1분 정도 기다리면 갱신 됩니다.
만약 파일명을 다르게 하고 싶다면 주소 끝에 해당 파일 명을 입력해주면 됩니다.
index.html은 약속된 파일명 이기 때문에 주소 끝에 파일명을 입력하지 않아도 자동으로 찾아갑니다. 

https://bamdule.github.io/myRepo/ 로 이동했을 때 나오는 페이지 

4. 제한 사항

1) GitHub Pages 소스 저장소의 권장 제한은 1GB입니다.
2) 게시 된 GitHub 페이지 사이트는 1GB를 초과 할 수 없습니다.
3) GitHub 페이지 사이트의 대역폭 제한은 한 달에 100GB입니다.
4) GitHub 페이지 사이트의 builds 제한은 시간당 10회 입니다.

 

Bamdule.github.io와 같은 도메인으로 사용 하고 싶다면 repository 이름을 다음과 같이 변경해줍니다.

사용자명.github.io

참조:

wepplication.github.io/programming/github-pages/

'IT > git' 카테고리의 다른 글

[Github] GitHub Gist 사용하기  (1) 2021.03.31
[Git] Github를 이용한 Git Repository 만들기  (1) 2020.12.02
[git] git 설치하기  (0) 2020.06.15
[Git] git Source File Status  (1) 2020.01.01
[Git] git을 이용한 소스코드 관리  (0) 2019.12.31

1. github 회원 가입하기

https://github.com/

 

GitHub: Where the world builds software

GitHub is where over 50 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and feat...

github.com

 

2. Git Repository 생성하기

github에 로그인 후 오른쪽 상단에 +버튼을 눌러서 New repository를 클릭해주세요.

 

1) Repository name 입력
2) Description 입력
3) public 선택  (private은 유료지만, 3명까지는 무료라고 합니다.)
4) create repository

 

3. git과 gitbash 설치하기

git은 필수지만 gitbash는 선택입니다.
2020/06/15 - [IT/git] - [git] git 설치하기
 

[git] git 설치하기

안녕하세요. 이번에는 많은 곳에서 사용되고 있는 git 설치 방법에 대해 포스팅해보겠습니다. 1. Git 설치 파일 다운로드 아래 경로에서 os에 맞는 git 설치 파일을 다운로드 해주세요. https://git-scm.c

bamdule.tistory.com

4. Git clone

1) 생성한 git repository의 주소를 복사합니다.
ex) https://github.com/Bamdule/myRepo.git

2) 원하는 경로에서 git bash를 실행시켜줍니다.

마우스 우클릭

3) git clone (git주소)를 입력해 줍니다.

5. git push

1) clone한 디렉토리로 이동하여 아무 파일이나 만들고 git bash에서 새로 만든 디렉토리로 이동해줍니다.

해당 디렉토리로 이동한 후 마우스 우클릭 > Git Bash Here 버튼을 눌러도 됩니다.

2) git add .

새로 생성한 파일을 add 해줍니다.

3) git commit -m "commit message"

commit 메시지를 입력해줍니다.

4) git push orgin

git 원격 저장소로 소스파일을 업로드합니다.

'IT > git' 카테고리의 다른 글

[Github] GitHub Gist 사용하기  (1) 2021.03.31
[Git] Github를 이용해서 무료 웹페이지 만들기  (0) 2020.12.02
[git] git 설치하기  (0) 2020.06.15
[Git] git Source File Status  (1) 2020.01.01
[Git] git을 이용한 소스코드 관리  (0) 2019.12.31

1. Stream 이란

프로그램은 외부에서 데이터를 읽거나 외부로 데이터를 출력하는 작업이 빈번하게 일어납니다.
이때 데이터는 어떠한 통로를 통해서 데이터가 이동되는데, 이 통로를 Stream 이라고 합니다.

자바에는 이러한 기능을 수행하기 위해 InputStream와 OutputStream이 존재하며 단일 방향으로 연속적으로 흘러갑니다.
InputStream과 OutputStream은 추상 클래스이며 추상 메소드를 오버라이딩해서 다양한 역할을 수행할 수 있습니다. 
(예 : 파일, 네트워크, 메모리 입출력)

자바에서 기본적으로 제공하는 I/O 기능은 java.io 패키지에서 제공됩니다. 
InputStream은 외부에서 데이터를 읽는 역할을 수행하고, OutputStream은 외부로 데이터를 출력하는 역할을 수행합니다.       

 

2. InputStream

바이트 기반 입력 스트림의 최상위 추상클래스입니다. (모든 바이트 기반 입력 스트림은 이 클래스를 상속받습니다.)
파일 데이터를 읽거나 네트워크 소켓을 통해 데이터를 읽거나 키보드에서 입력한 데이터를 읽을 때 사용합니다. 
InputStream은 읽기에 대한 다양한 추상 메소드를 정의해 두었습니다.
그리고 InputStream의 추상메소드를 오버라이딩하여 목적에 따라 데이터를 입력 받을 수 있습니다.

3. InputStream의 기본 메소드

public abstract int read() throws IOException;
    public void read() throws IOException {
    
        byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        InputStream is = new ByteArrayInputStream(bytes);
        int data;
        while ((data = is.read()) != -1) {
            System.out.print(data);
        }
        
    }
입력 스트림에서 1 바이트 씩 읽고 읽은 바이트를 반환합니다. 
데이터를 모두 읽었다면 -1을 반환합니다. 
출력
------------
1234567891011

    public int read(byte buffer[]) throws IOException {
        return read(buffer, 0, buffer.length);
    }
    public void read() throws IOException {
        byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        InputStream is = new ByteArrayInputStream(bytes);

        int len = 3;
        int readCnt = 0;
        byte[] buffer = new byte[len];
        while ((readCnt = is.read(buffer)) != -1) {

            for (int index = 0; index < readCnt; index++) {
                System.out.print(buffer[index]);
            }

            System.out.println();
        }
    }
입력 스트림에서 byte buffer[] 만큼 읽고 읽은 데이터 수를 반환합니다.
여러 바이트 씩 읽기 때문에 한 바이트 씩 읽는 것 보다 더 빠릅니다.
  
데이터를 모두 읽었다면 -1을 반환합니다. 

위 소스는 bytes에 있는 데이터를 buffer의 크기(3)만큼 읽어서 buffer에 넣고 콘솔에 출력하고 read(buffer)의 반환값이 -1이 될 때까지 반복합니다. 

read() 메소드와 다른 점은 read() 메소드의 반환 값이 읽은 데이터가 아니라 읽은 데이터 수 라는 점입니다.
읽은 데이터는 매개변수로 넘긴 buffer에 저장됩니다. 
출력
------------
123
456
789
1011

public int read(byte buffer[], int off, int len) throws IOException
    public void read() throws IOException {
        byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        InputStream is = new ByteArrayInputStream(bytes);

        int len = 4;
        int readCnt = 0;
        int offset = 0;
        byte[] buffer = new byte[1024];
        
        while ((readCnt = is.read(buffer, offset, len)) != -1) {
            offset += readCnt;
            for (int index = 0; index < offset; index++) {
                System.out.print(buffer[index]);
            }
            System.out.println();

        }
    }
입력 스트림에서 buffer[off] 부터 len개 만큼 buffer에 저장합니다.
read 메소드는 읽은 데이터의 개수를 반환하고 더 이상 읽을 데이터가 없다면 -1을 반환합니다.
만약 len개를 읽지 못하면 실제로 읽은 데이터 수를 반환합니다.

위 소스는 데이터를 4개씩 읽으며, 다시 읽을 때 배열의 처음 위치가 아닌 offset 위치 즉, buffer[offset] 부터 읽습니다.
offset은 읽은 데이터 수(readCnt) 만큼 증가합니다. 간혹 len만큼 증가하게 하는 경우가 있는데, 읽을 데이터의 수가 꼭 len 값으로 나누어 떨어지지 않기 때문에 offset은 읽은 데이터의 수(readCnt)만큼 증가 해주어야합니다.
보통 네트워크 통신할 때 많이 사용합니다.
출력
------------
1234
12345678
1234567891011

public long skip(long n) throws IOException
읽을 데이터 중 n 바이트를 스킵하고 실제로 스킵한 바이크 개수가 반환됩니다.

int available() throws IOException
읽을 데이터(바이트)가 얼마나 남아있는지 반환됩니다.

public synchronized void mark(int readlimit) {}
되돌아갈 특정 위치를 마킹하는 메소드 입니다.
readlimit은 현재 위치를 마킹하고 최대 몇개의 byte를 더 읽을 수 있는지를 의미합니다.

public synchronized void reset() throws IOException {
   throw new IOException("mark/reset not supported");
}
마킹한 지점으로 되돌아가는 메소드입니다.
기본적으로 지원되지 않으며, InputStream 추상클래스를 상속받은 클래스에서 오버라이딩해주어야 사용가능합니다.  

public boolean markSupported() {
   return false;
}
mark 메소드의 지원 유무를 확인하는 메소드입니다. 기본적으로 지원하지 않으므로 false를 반환합니다.

3. OutputStream

바이트 기반 출력 스트림의 최상위 추상클래스입니다.
모든 바이트 기반 출력 스트림 클래스는 이 클래스를 상속 받아 기능을 재정의 합니다.

 

4. OutputStream의 기본 메소드 

 public abstract void write(int b) throws IOException;
 
 public void write(byte b[]) throws IOException {
   write(b, 0, b.length);
}
    public void write01() throws IOException {
        byte[] bytes = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

        File file = new File("D://write_test.txt");
        OutputStream outputStream = new FileOutputStream(file);

        for (byte b : bytes) {
            outputStream.write(b);
        }
        
        //바이트를 한번에 넣을 수 있다.  
        //outputStream.write(bytes);
        
        outputStream.close();
    }
바이트 배열을 write_text.txt 파일에 write하는 예제입니다. OutputStream을 상속받은 FileOutputStream을 생성하고, 
한 바이트 씩 write하거나 여러 바이트씩 write 할 수 있습니다.

public void write(byte b[], int off, int len) throws IOException 
    public void write() throws IOException {
        byte[] bytes = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 7, 8, 7, 8, 5, 2, 4};
        int len = 3;
        int offset = 0;
        int total = bytes.length;

        File file = new File("D://write_test.txt");
        OutputStream outputStream = new FileOutputStream(file);

        while (total >= (offset + len)) {
            outputStream.write(bytes, offset, len);
            offset += len;
        }

        if (total - offset > 0) {
            outputStream.write(bytes, offset, total - offset);
        }
        
        outputStream.close();
    }
byte 배열 b를 offset부터 len만큼 write합니다.
    public void read() throws IOException {

        File file = new File("D://write_test.txt");
        InputStream inputStream = new FileInputStream(file);
        int b;
        while ((b = inputStream.read()) != -1) {
            System.out.print(b);
        }

    }
write_test.txt로 write한 데이터를 한 바이트씩 꺼내서 출력합니다.

public void flush() throws IOException {}
버퍼를 지원하는 경우 버퍼에 존재하는 데이터를 목적지까지 보냅니다.

public void close() throws IOException {
}
OutputStream을 종료합니다.

참조

https://lannstark.tistory.com/34

S3를 생성하지 않았다면 다음 글을 참고해주세요.
2020/11/17 - [IT/AWS] - [AWS] Amazon S3 생성 방법 (Amazon Simple Storage Service)
S3 용어를 알고 싶다면 다음글을 참고해주세요.
2020/11/17 - [IT/AWS] - [AWS] Amazon S3 (Simple Storage Service)란 무엇인가?
 

[AWS] Amazon S3 (Simple Storage Service)란 무엇인가?

1. Amazon S3란? Simple Storage Service의 약자로 내구성과 확장성이 뛰어난 스토리지 서비스입니다. 2. Amazon S3 용어 설명 bucket S3에서 생성되는 최상위 디렉토리이며 디렉터리와 객체를 저장하는 컨테

bamdule.tistory.com

1. pom.xml

...        
        <!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 -->
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.11.901</version>
        </dependency>
...        

 

2. AwsS3.java

아무나 S3에 파일을 업로드 하지 못하게 막으려면 IAM에서 accessKey와 secretKey를 발급 받아야 합니다.
만약 누구나 업로드가 가능하게 하려면 S3 권한 > 버킷 정책에서 해당 정책을 생성한 후 적용해 주어야 합니다.
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
import java.io.File;

public class AwsS3 {

    //Amazon-s3-sdk 
    private AmazonS3 s3Client;
    final private String accessKey = "IAM에서 발급받은 accessKey";
    final private String secretKey = "IAM에서 발급받은 secretKey";
    private Regions clientRegion = Regions.AP_NORTHEAST_2;
    private String bucket = "bamdule-bucket";

    private AwsS3() {
        createS3Client();
    }

    //singleton pattern
    static private AwsS3 instance = null;
    
    public static AwsS3 getInstance() {
        if (instance == null) {
            return new AwsS3();
        } else {
            return instance;
        }
    }

    //aws S3 client 생성
    private void createS3Client() {

        AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
        this.s3Client = AmazonS3ClientBuilder
                .standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withRegion(clientRegion)
                .build();
    }

    public void upload(File file, String key) {
        uploadToS3(new PutObjectRequest(this.bucket, key, file));
    }

    public void upload(InputStream is, String key, String contentType, long contentLength) {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(contentType);
        objectMetadata.setContentLength(contentLength);

        uploadToS3(new PutObjectRequest(this.bucket, key, is, objectMetadata));
    }

    //PutObjectRequest는 Aws S3 버킷에 업로드할 객체 메타 데이터와 파일 데이터로 이루어져있다.
    private void uploadToS3(PutObjectRequest putObjectRequest) {

        try {
            this.s3Client.putObject(putObjectRequest);
            System.out.println(String.format("[%s] upload complete", putObjectRequest.getKey()));

        } catch (AmazonServiceException e) {
            e.printStackTrace();
        } catch (SdkClientException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void copy(String orgKey, String copyKey) {
        try {
            //Copy 객체 생성
            CopyObjectRequest copyObjRequest = new CopyObjectRequest(
                    this.bucket,
                    orgKey,
                    this.bucket,
                    copyKey
            );
            //Copy
            this.s3Client.copyObject(copyObjRequest);

            System.out.println(String.format("Finish copying [%s] to [%s]", orgKey, copyKey));

        } catch (AmazonServiceException e) {
            e.printStackTrace();
        } catch (SdkClientException e) {
            e.printStackTrace();
        }
    }

    public void delete(String key) {
        try {
            //Delete 객체 생성
            DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(this.bucket, key);
            //Delete
            this.s3Client.deleteObject(deleteObjectRequest);
            System.out.println(String.format("[%s] deletion complete", key));

        } catch (AmazonServiceException e) {
            e.printStackTrace();
        } catch (SdkClientException e) {
            e.printStackTrace();
        }
    }


}
파일을 업로드하려면 PutObjectRequest 객체를 생성해야합니다. PutObjectRequest 객체를 생성하는 방법은 두가지가 있는데,
첫번째는 File 객체와 key값을 이용해 만드는 방법이고, 두번째는 InputStream과 key값 그리고 파일 정보(ContentType, file Length 등)를 이용해 만드는 방법입니다. 여기서 key 값은 버킷 내에서 객체를 찾기위해 사용되는 고유 식별자를 의미합니다.

 

3. Main.java

import java.io.File;

public class Main {

    public AwsS3 awsS3 = AwsS3.getInstance();

    public static void main(String[] args) {

        Main main = new Main();

        File file = new File("D://4.png");
        String key = "img/my-img.png";
        String copyKey = "img/my-img-copy.png";

        main.upload(file, key);
//        main.copy(key, copyKey);
//        main.delete(key);
    }

    public void upload(File file, String key) {
        awsS3.upload(file, key);
    }

    public void copy(String orgKey, String copyKey) {
        awsS3.copy(orgKey, copyKey);
    }

    public void delete(String key) {
        awsS3.delete(key);
    }

}

1. Amazon S3란?

2020/11/17 - [IT/AWS] - [AWS] Amazon S3 (Simple Storage Service)란 무엇인가?
 

[AWS] Amazon S3 (Simple Storage Service)란 무엇인가?

1. Amazon S3란? Simple Storage Service의 약자로 내구성과 확장성이 뛰어난 스토리지 서비스입니다. 2. Amazon S3 용어 설명 bucket S3에서 생성되는 최상위 디렉토리이며 디렉터리와 객체를 저장하는 컨테

bamdule.tistory.com

2. Amazon S3 생성하기

1) aws 계정 로그인

2) S3로 이동 후 버킷 만들기 클릭

3) 버킷 이름과 리전 선택

버킷 이름은 고유해야하고, 리전은 서비스 지역에 따라서 설정해주면 됩니다.

 

4) 퍼블릭 액세스 설정

외부에 S3를 공개할 경우 모든퍼블릭 액세스 차단 체크를 해제해주면 됩니다.
외부에 공개하지 않고 내부에서만 사용하려면 모든 퍼블릭 액세스 차단을 체크해주시면 됩니다. 
퍼블릭 액세스가 차단되었을 경우 IAM에서 AWSAccessKeyId와 AWSSecretKey를 발급받고 이를 이용해서 S3 객체에 접근할 수 있습니다.

 

5) 버킷 버전 관리 및 기본 암호화

버킷 버전 관리기능을 활성화하면 파일을 버전별로 관리 하기 때문에 비용이 더 들지만 사용자가 실수로 파일을 삭제해도 복원할 수 있습니다.

기본 암호화를 활성화 하면 버킷에 저장되는 모든 새 객체를 암호화합니다.
그리고 객체를 다운 로드할 때 암호를 해독해합니다.

모든 설정이 끝났으면 버킷을 생성해줍니다.

 

6) 퍼블릭 정책 활성화

bamdule-bucket이 생성된 것을 볼 수 있지만 아직 외부에서 접근할 수 없습니다.
버킷 정책 생성 URL
awspolicygen.s3.amazonaws.com/policygen.html

 

Select Type of Policy : S3 Bucket Policy

Effect :
Allow

Principal
: *

AWS Service
:  Amazon S3

Actions :
GetObject (원하는 만큼 더 선택해도 됩니다.)
조회만 가능하도록 GetObject 권한만 체크합니다.

Amazon Resource Name (ARN) :
arn:aws:s3:::bucket-name/*
다 입력되었다면 Add Statement를 눌러주세요.

입력 값을 확인 한 다음 Generate Policy를 눌러주세요.

정책이 명시된 JSON 값을 복사 한 뒤 버킷 정책에 입력해주세요.
권한 > 버킷 정책

변경 사항 저장 후 아래그림과 같이 액세스가 퍼블릭으로 변경되었다면, 외부에서 S3에 접근할 수 있는 상태입니다.

7) 테스트

버킷에 아무 파일이나 올린 후 해당 파일의 객체 URL을 브라우저 주소창에 입력하면 됩니다.

8) 액세스 키 생성

액세스키는 모든 퍼블릭 액세스를 차단했을 경우 필요합니다.
S3에 접근하려면 별도의 인증 과정이 필요한데, 이때 사용되는 것이  액세스 키 입니다.
액세스 키는 AWSAccessKeyId와 AWSSecretKey로 구성되어 있습니다.

IAM > 액세스 키 > 새 액세스 키 만들기

액세스 키를 생성하면 키 파일을 다운로드 받을 수 있고 해당 파일에 AWSAccessKeyId와 AWSSecretKey가 명시되어있습니다.  AWSAccessKeyId와 AWSSecretKey는 절때 외부에 노출되어서는 안됩니다.

자바를 이용해서 S3로 업로드, 복사, 삭제 하는 방법

2020/11/17 - [IT/AWS] - [AWS] JAVA S3로 파일 업로드, 복사, 삭제 하기

 

1. Amazon S3란?

Simple Storage Service의 약자로 내구성과 확장성이 뛰어난 스토리지 서비스입니다. 

 

2. Amazon S3 용어 설명

bucket
S3에서 생성되는 최상위 디렉토리이며 디렉터리와 객체를 저장하는 컨테이너입니다. 버킷의 이름은 S3에서 유일해야 하며, 버킷 단위로 region을 지정할 수 있고, 버킷 별로 접근 제어 설정을 할 수 있습니다.

Object
S3에 저장되는 데이터를 객체라고 하며, 파일과 메타데이터로 이루어져 있습니다.
객체의 크기는 최대 5TB 까지 허용됩니다.

Key
버킷 내에서 객체를 찾기 위해 사용되는 고유 식별자입니다.
보통 "디렉터리 + 파일명"으로 명명됩니다.

Region
버킷 생성 시 버킷의 위치를 지정할 수 있습니다. 버킷 위치를 어디에 지정하냐에 따라서 지연 시간 최적화, 비용 최소화 등이 결정됩니다.

 

3. Amazon S3의 장점

1) 일반적인 파일 서버는 사용자 트래픽이 증가하면 스토리지 증설 작업을 해야하지만 S3는 시스템 적으로 트래픽 증가에 대한 처리를 미리 해두었기 때문에 파일 서버 관리자는 별도의 처리를 해주지 않아도 됩니다.

2) 저장할 수 있는 파일 수의 제한이 없습니다.

3) 버킷 마다 인증 시스템을 설정할 수 있어서 보안이 좋습니다.

4) HTTP와 BitTorrent 프로토콜을 지원합니다.

5) REST, SOAP(HTTPS만 가능) 인터페이스를 제공합니다.

6) 버전관리 기능을 사용하면 사용자가 실수할 경우에도 복원이 가능합니다.

 

4. S3 사용 요금

S3는 사용자가 실제 사용한 만큼만 요금을 책정합니다.

참조:

https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/dev/Introduction.html

 

의존성 주입을 이해하기 전에 의존성에 대해서 먼저 알아보겠습니다.

1. 의존성이란?

의존의 사전적 의미는 "스스로 하지 못하고 누군가에게 도움을 받음" 입니다.

그렇다면 의존성은 무엇일까요? 

의존성이란
어떤 객체가 생성되기 위해 다른 객체가 꼭 필요한 상태를 의미합니다.
의존성은 new 연산자를 통해 발생합니다. 의존성이 높아지면 결합도 또한 높아집니다. 

결합도가 높으면 해당 클래스를 수정할 경우 참조하고 있는 다른 클래스도 함께 이해해야합니다.  
왜냐하면 무작정 수정했다가는 사이드 이펙트가 발생할 수 있기 때문입니다.

그리고 결합도가 높은 클래스는 재사용하기 힘듭니다. 

 

1) 의존성 예제

public class Windows {

    public void booting() {
        System.out.println("Windows booting !");
    }
}

public class Computer {

    private Windows os;

    public Computer() {
        this.os = new Windows();
    }

    public void booting() {
        os.booting();
    }
}
Computer 클래스가 Windows 클래스를 참조하고 있는 상태입니다.  

만약 Mac, Linux 등 다양한 OS 객체를 전달 받으려면 소스를 수정해야합니다.
이는 코드의 유연성을 떨어트리고 중복 소스가 생기며 가독성 또한 떨어트리는 원인이 됩니다.

이러한 문제를 해결하기 위한 방법 중 하나는 바로 의존성 역전(Dependency Injection)을 이용하는 방법입니다.

 

2) 의존성 주입(Dependency Injection) 예제

public interface OS {
    public void booting();
}

public class Windows implements OS {

    @Override
    public void booting() {
        System.out.println("Windows booting !");
    }
}

public class Linux implements OS {

    @Override
    public void booting() {
        System.out.println("Linux booting !");
    }

}

public class Computer {

    private OS os;
    //외부에서 객체를 주입받는다.
    public Computer(OS os) {
        this.os = os;
    }

    public void booting() {
        os.booting();
    }
}

public class Main {
    public static void main(String[] args) {

        OS windows = new Windows();
        Computer windowsComputer = new Computer(windows);

        OS linux = new Linux();
        Computer linuxComputer = new Computer(linux);
        
        windowsComputer.booting();
        linuxComputer.booting();
    }
}


단순히 생성자를 통해 외부에서 객체를 전달받았다고 의존성 주입이라고 하지 않습니다.
만약 Windows 객체를 생성자로 주입받았다면, 외부로 부터 객체를 주입받았지만, 결합도가 낮아졌다고 할 수 없습니다.
이전에 존재했던 문제를 똑같이 안고 가는 것 입니다.

제대로 된 의존성 주입을 하려면 추상화된 객체를 외부에서 주입 받아야 합니다.
Computer 클래스의 생성자는 외부에서 생성된 객체(OS 인터페이스를 구현한 객체)를 전달 받습니다. Windows 객체를 전달 받았을 때보다 결합도가 낮아 졌으며, OS가 새로 추가되더라도 Computer 클래스는 수정하지 않아도 됩니다.

 

2. 의존성 주입이란?

의존성 주입이란 추상화된 객체를 외부에서 주입받는 것을 의미합니다. 
(ex : OS 인터페이스를 구현한 Windows 또는 Linux)

의존성 주입은 생성자, setter, field 등 다양하게 구현할 수 있습니다.
의존성 주입의 장점

1) 테스트가 용이합니다.
2) 재사용성과 유연성이 높아집니다.
3) 코드의 중복이 없어지고, 단순해집니다.
4) 코드의 가독성이 좋아집니다.
5) 종속성과 결합도가 낮아집니다.

참조

https://engkimbs.tistory.com/602?category=767795
https://medium.com/@jang.wangsu/di-dependency-injection-%EC%9D%B4%EB%9E%80-1b12fdefec4f

+ Recent posts