1. 객체 지향 프로그래밍이란?

 

객체 지향 프로그래밍(Object-Oriented Programming), 줄여서 OOP.

프로그램을 어떻게 설계해야 하는지에 대한 일종의 개념이자 방법론.

 

프로그램을 단순히 데이터와 처리 방법으로 나누는 것이 아니라, 

프로그램을 수많은 '객체'라는 기본 단위로 나누고 이 객체들의 상호작용으로 서술하는 방식이다. 

 

객체를 데이터의 묶음으로만 착각하기 쉬운데, 그보다는 하나의 '역할'을 수행하는 메소드와 데이터의 묶음으로 봐야 한다.

 

1.1 절차적 프로그래밍 방식

 

입력을 받아 명시된 순서대로 처리한 다음, 그 결과를 내는 것

어떻게 어떤 논리를 어떤 순서대로 써나가는 것인가로 간주되었다. 

즉, 프로그램 자체가 가지는 기능에 대해서만 신경을 썼지, 이 프로그램이 대체 어떤 데이터를 취급하는 것인가에는 

그다지 관심이 없었던 것이다.

 

1.2 구조적 프로그래밍 방식

 

절차적 프로그래밍 방식을 개선하기 위해 나온 방식으로

프로그램을 함수(procedure) 단위로 나누고 

프로시져끼리 호출을 하는 것이 구조적 프로그래밍 방식이다. 

프로그램이라는 큰 문제를 해결하기 위해 그것을 몇개의 작은 문제들로 나누어 해결하기 때문에 

하향식(Top-down) 방식이라고도 한다.

 

1.3 객체 지향 프로그래밍 방식

 

구조적 프로그래밍 박식을 개선하기 위해 나온 방식으로

객체 지향 프로그래밍이다. 

큰 문제를 작게 쪼개는 것이 아니라, 먼저 작은 문제들을 해결할 수 있는 객체들을 만든 뒤, 

이 객체들을 조합해서 큰 문제를 해결하는 상향식(Bottom-up) 해결법을 도입한 것이다. 

이 객체란 것을 일단 한번 독립성/신뢰성이 높게 만들어 놓기만 하면 그 이후엔 

그 객체를 수정 없이 재사용할 수 있으므로 개발 기간과 비용이 대폭 줄어들게 된다.

 

OOP를 사용하면 코드의 중복을 어느 정도 줄일 수 있고 입력 코드, 

계산 코드와 결과 출력 코드 등 코드의 역할 분담을 좀 더 확실하게 할 수 있어서 가독성이 높아질 수 있다.

 

 

2. 

객체 지향 프로그래밍 요소

 

2.1 캡슐화

 

캡슐화는 프로그램의 세부 구현을 외부로 드러나지 않도록 특정 모듈 내부로 감추는 것이다. 

캡슐화는 객체지향 언어를 구성하는 주요 요소이지만 객체지향 언어에서만 사용되는 개념은 아니다. 

내부의 구현은 감추고(=정보 은닉) 모듈 내에서의 응집도를 높이며, 외부로의 노출을 최소화하여 

모듈 간의 결합도를 떨어뜨리는 개념은 거의 대부분의 언어에 녹아있다.

 

많은 객체지향 언어에서 사용되는 클래스를 기준으로 보면, 

클래스 외부에서는 바깥으로 노출된 특정 메소드에만 접근이 가능하며 클래스 내부에서 

어떤 식으로 처리가 이루어지는지는 알지 못하도록 설계된다.

 

일반적으로 세 종류의 접근 제한이 사용된다.

 

public : 클래스의 외부에서 사용 가능하도록 노출시키는 것이다.

 

protected : 다른 클래스에게는 노출되지 않지만, 상속받은 자식 클래스에게는 노출되는 것이다.

 

private : 클래스의 내부에서만 사용되며 외부로 노출되지 않는다.

 

 

2.2 상속

 

상속은 자식 클래스가 부모 클래스의 특성과 기능을 그대로 물려받는 것을 말한다. 

기능의 일부분을 변경해야 할 경우 자식 클래스에서 상속받은 그 기능만을 수정해서 다시 정의하게 되는데, 

이러한 작업을 '오버라이딩(Overriding: 재정의)'이라고 한다. 

상속은 캡슐화를 유지하면서도 클래스의 재사용이 용이하도록 해 준다.

 

 

2.3 다형성

 

하나의 함수명 등이 상황에 따라 다른 의미로 해석될 수 있는 것을 말한다. 

이를 '오버로딩(Overloading: 중복 정의/다중 정의)'이라고 한다.

 

함수 오버로딩

C++과 C#, Java에서는 함수 오버로딩을 통해 동일한 이름의 함수를 매개변수에 따라 다른 기능으로 동작하도록 

할 수 있다.  함수 오버로딩을 너무 자주 사용하면 해당 함수가 어디서 오버로딩되었는지 찾기 어려워질 수 있으므로, 

지나친 남발은 자제하는 것이 좋다.

 

 

2.4 장점

 

이 OOP 특성 덕분에 개발시간 단축(잘 만들어진 클래스는 재사용성을 보장한다) 

정확한 코딩(구현 목적을 위해 클래스를 나눌 수 있으니 구현 단위와 목표가 뚜렷해진다.)이 가능하다.

 

 

3. 객체지향의 원칙[ 5원칙(SOLID) ]

 

객체지향에서 꼭 지켜야 할 5개의 원칙을 말한다. 

일단 한번 보면 개념은 알아 듣긴 하지만 막상 실현하려면 생각보다 어려움이 따른다. 

이 5개의 원칙의 앞글자를 따서 SOLID라고도 부른다.

 

 

3.1 SRP(Single Responsibility Principle) : 단일 책임 원칙 

 

객체는 오직 하나의 책임을 가져야 한다. (객체는 오직 하나의 변경의 이유만을 가져야 한다.)

사칙연산 함수를 가지고 있는 계산 클래스가 있다고 치자. 이 상태의 계산 클래스는 오직 사칙연산 기능만을 책임진다. 

만일 프로그램이 대대적으로 공사를 들어가게 되더라도 계산 클래스가 수정될만한 사유는 누가 봐도 사칙연산 함수와 

관련 된 문제 뿐이다.  이처럼 단일 책임 원칙은 클래스의 목적을 명확히 함으로써 구조가 난잡해지거나 수정 사항이 

불필요하게 넓게 퍼지는 것을 예방하고 기능을 명확히 분리할 수 있게 한다.

위의 원칙이 제대로 지켜지지 않으면 어떻게 될까? 

어떤 프로그래머가 위의 계산 클래스를 통해 GUI를 가지는 계산기 프로그램을 개발하고 있다. 

그런데 중간에 귀찮다고 GUI 관련 코드를 계산 클래스에 넣어버렸다. 

이렇게 되면 계산 클래스는 계산과 GUI라는 두 가지 책임을 지게 되는데 만일 GUI 관련 수정 사항이 발생하게 되면 

별 상관도 없어보이는 계산 클래스를 고치게 된다. 

이처럼 하나의 클래스가 두 가지 이상의 책임을 지니게 되면 클래스의 목적이 모호해지고 기능을 수정할 때 

영향을 받는 범위도 커져서 유지보수가 힘들어지며[1] 결국 작성한 본인조차도 이게 정확히 뭐하는 클래스인지 

명확히 설명할 수가 없는 스파게티 코드가 되어버린다.

 

 

3.2 OCP(Open-Closed Principle) : 개방-폐쇄 원칙

 

객체는 확장에 대해서는 개방적이고 수정에 대해서는 폐쇄적이어야 한다는 원칙이다. 

즉, 객체 기능의 확장을 허용하고 스스로의 변경은 피해야 한다.

 

예를 들면 도롱뇽과 개구리가 있다. 당신은 이런저런 공통사항을 생각하며 메소드와 필드를 정의한다. 

둘다 이동속도는 다르지만 기본 이동은 도룡뇽은 기어다니고 개구리는 기어다니며 점프하고를 반복한다.

하지만 개구리 같은 동물의 움직임을 구현할 때 애로사항이 있을 것 같다.

 

이동 메소드에서 이동 패턴을 나타내는 코드를 별도의 메소드로 분리하고, 구현을 하위 클래스에 맡긴다. 

그러면 개구리 클래스에서는 이동 패턴 메소드만 재정의하면 동물 클래스의 변경 없이 

기어다니며 점프하는 움직임을 보여줄 수 있다! '동물' 클래스의 '이동' 메소드는 수정할 필요조차 없다(수정에 대해선 폐쇄). 

그냥 개구리 클래스의 이동 패턴 메소드만 재정의하면 그만인 것이다(확장에 대해선 개방).

 

 

3.3 LSP(Liskov Substitution Principle) : 리스코프 치환 원칙

 

자식 클래스는 언제나 자신의 부모 클래스를 대체할 수 있다는 원칙이다. 

즉 부모 클래스가 들어갈 자리에 자식 클래스를 넣어도 계획대로 잘 작동해야 한다는 것. 

상속의 본질인데, 이를 지키지 않으면 부모 클래스 본래의 의미가 변해서 다형성을 지킬 수 없게 된다.

 

또다시 예를 들면, 컴퓨터용 '마우스' 클래스가 있다고 치자. 

컴퓨터에 있는 ps/2 포트나 usb 포트를 통해 연결할 수 있고, 마우스를 바닥에 대고 움직이면 

컴퓨터가 신호를 받아들인다는 것을 안다.  사용 면에서는 왼쪽과 오른쪽 버튼, 그리고 휠이 있어 사용자가 

누르거나 굴릴수 있을 것이다.  마우스가 볼마우스든 광마우스든, 아니면 GPS를 이용하건 간에 아무튼 

사용자는 바닥에 착 붙여 움직일 것이고, 모든 마우스는 예상대로 신호를 보내 줄 것이다. 

 

또한 만약 추가적인 특별한 버튼이 있는 마우스(상속)라도 그 버튼의 사용을 제외한 다른 부분은 

보통의 마우스와 다를 바 없으므로 사용자는 그 마우스의 그 버튼이 뭔 역할을 하던간에 문제 없이 잘 사용한다. 

여기까지 나온 마우스들은 LSP를 잘 지킨다고 볼 수 있다.

 

하지만 오른쪽/왼쪽 버튼 대신 옆쪽 버튼을 사용하는 펜마우스를 처음으로 접하게 되면 사용자는 

평소 보던 버튼을 누를 수 없다며 이상을 호소할 것이다. 이런 경우 LSP를 전혀 지키지 못 하는 것이다.

 

 

3.4 ISP(Interface Segregation Principle) : 인터페이스 분리 원칙

 

클라이언트에서 사용하지 않는 메서드는 사용해선 안된다. 그러므로 인터페이스를 다시 작게 나누어 만든다. 

OCP와 비슷한 느낌도 들지만 엄연히 다른 원칙이다. 하지만 ISP를 잘 지키면 OCP도 잘 지키게 될 확률이 

비약적으로 증가한다.

 

게임을 만드는데 충돌 처리와 이팩트 처리를 하는 서버를 각각 두고 

이 처리 결과를 (당연히) 모두 클라이언트에게 보내야 한다고 가정하자. 

그러면 아마 Client라는 인터페이스를 정의하고 그 안에 충돌전달()과 이펙트전달(이펙트)를 넣어놓을 것이다. 

그리고 충돌 서버와 이펙트 서버에서 이 인터페이스를 구현하는 객체들을 모아두고 있으며, 때에 따라 적절히 신호를 보낸다. 

하지만 이렇게 해두면 충돌 서버에겐 쓸모없는 이펙트전달 인터페이스가 제공되며, 

이펙트 서버에겐 쓸모없는 충돌전달 인터페이스가 제공된다.  이를 막기 위해선 Client 인터페이스를 쪼개 

이펙트전달가능 인터페이스와 충돌전달가능 인터페이스로 나눈 뒤, 충돌에는 충돌만, 

이펙트에는 이펙트만 전달하면 될 것이다. 

또한 Client 인터페이스는 남겨두되 이펙트전달가능과 충돌전달가능 이 둘을 상속하면 된다.

 

 

3.5 DIP(Dependency Inversion Principle) : 의존성 역전 원칙

 

추상성이 높고 안정적인 고수준의 클래스는 구체적이고 불안정한 저수준의 클래스에 의존해서는 안된다는 원칙으로서, 

일반적으로 객체지향의 인터페이스를 통해서 이 원칙을 준수할 수 있게 된다. 

(상대적으로 고수준인) 클라이언트는 저수준의 클래스에서 추상화한 인터페이스만을 바라보기 때문에, 

이 인터페이스를 구현한 클래스는 클라이언트에 어떤 변경도 없이 얼마든지 나중에 교체될 수 있다..

 
 

 


1. PL/SQL이란?


- PL/SQL 은 Oracle’s Procedural Language extension to SQL 의 약자 이다.

- SQL문장에서 변수정의, 조건처리(IF), 반복처리(LOOP, WHILE, FOR)등을 지원하며,

오라클 자체에 내장되어 있는 Procedure Language 이다.

- DECLARE문을 이용하여 정의되며, 선언문의 사용은 선택 사항 이다.

- PL/SQL 문은 블록 구조로 되어 있고 PL/SQL자신이 컴파일 엔진을 가지고 있다.


2. PL/SQL의 장점


- PL/SQL 문은 BLOCK 구조로 다수의 SQL 문을 한번에 ORACLE DB로 보내서 처리하므로 수행속도를 향상 시킬수 있다.

- PL/SQL 의 모든 요소는 하나 또는 두개이상의 블록으로 구성하여 모듈화가 가능하다.

- 보다 강력한 프로그램을 작성하기 위해서 큰 블록안에 소블럭을 위치시킬 수 있다.

- VARIABLE, CONSTANT, CURSOR, EXCEPTION을 정의하고, SQL문장과 Procedural 문장에서 사용 한다.

- 단순, 복잡한 데이터 형태의 변수를 선언 한다.

- 테이블의 데이터 구조와 컬럼명에 준하여 동적으로 변수를 선언 할 수 있다.

- EXCEPTION 처리 루틴을 이용하여 Oracle Server Error를 처리 한다.

- 사용자 정의 에러를 선언하고 EXCEPTION 처리 루틴으로 처리 가능 하다.



3. 오라클 프로시저 샘플로 만들기


다음은 새직원의 대한 연차를 +1씩 업데이트치는 루프를 프로시저로 만든 예제이다.


1
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
28
29
CREATE OR REPLACE PROCEDURE INTRANET.JOB_AUTO_VAC_NEW_EMPLOYEE
IS
    --FOR문을 위한 커서 생성
    CURSOR EMP_VAC_CUR IS
     SELECT * FROM(
        SELECT EMP_NO
                 , EMP_NM
                 , VAC_TOTAL_CNT
                 , JOIN_DT
                 , TO_CHAR(TRUNC(A.JOIN_DT, 'DD'),'YYYY') AS JOIN_YEAR
          FROM EMP_EMPLOYEE A
       ) A1
      WHERE A1.JOIN_YEAR = TO_CHAR(TRUNC(SYSDATE, 'DD'),'YYYY');
      
    total_cnt VARCHAR2(10);
BEGIN
    FOR EMP_VAC IN EMP_VAC_CUR LOOP
        
        -- 자신의 연차+1 을 변수에 저장
        total_cnt := EMP_VAC.VAC_TOTAL_CNT + 1;
        
        UPDATE EMP_EMPLOYEE A
              SET VAC_TOTAL_CNT =  total_cnt
         WHERE EMP_NO = EMP_VAC.EMP_NO;
 
    END LOOP;
END;
/
 
cs


1. CREATE OR REPLACE PROCEDURE 사용해서 프로시저를 만들거나 교체한다.

2. CURSOR를 만들고 만든 커서를 VAC_CUR을 가지고 BEGIN 과 END사이 FOR반복을 돌린다.

3. FOR반복을 돌며 EMP(직원)의 현재연차를 가져와 현재연차+1을 하여 변수에 저장한다.

4. UPDATE를 하나씩 쳐주면서 반복한다.

5. 반복이 끝나면 종료한다.



4. 프로시저 실행하기


1
EXECUTE INTRANET.JOB_AUTO_VAC_NEW_EMPLOYEE
cs



5. 오라클 잡 등록하기


오라클 잡(ORACLE JOB)을 등록하여 원하는날짜와 시간대에 프로시저가 실행될수 있게 스케쥴링 할 수 있다.


toad를 사용한다면 create job을 통해 실행될 날짜를 설정할수 있고 어떤 프로시저를 실행할지 명시할 수 있다.



오라클 잡을 생성하게 되면 다음과 같이 PL/SQL 문이 만들어지고 job에 대한 상세한 내용을 다시 확인할 수 있다. 




내용을 풀이하면 job의 간격은 매월 1일에 실행할 것이고 다음실행 날짜는 2019년 2월 1일에

INTRANET 프로시저를 실행하겠다는 것이다. 

이 job은 2019년 2월 1일에 실행되고 다음 실행날짜는 3월 1일로 설정된다.






1. EC2에서 우분투 인스턴스 하나를 생성한다.


2. putty로 원격 접속해 다음 cmd line을 이용해 실습환경을 셋팅한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1. 최신상태 업데이트
sudo apt-get update;
 
2. apache 설치
sudo apt-get install apache2
 
3. php 설치
sudo apt-get install php
 
4. MySQL 데이터베이스 서버 설치
sudo apt-get install mysql-server
 
5. MySQL 데이터베이스 클라이언트 설치
sudo apt-get install mysql-client
 
6. php와 mysql 연동
sudo apt-get install php-mysql;
 
7. 아파치 php 연동
sudo apt-get install libapache2-mod-php
 
8. 아파치 재시작
sudo service apache2 restart;
cs


3. 명령어를 통해 다 설치가 되면 웹브라우저를 열어 퍼블릭 DNS(IPv4) 를 입력한다.


 3.1 웹서버 아파치가 제대로 설치되었다면 ubuntu 기본페이지가 잘나온다.




 3.2 index.php 파일을 하나 만들어 phpinfo(); 내장함수를 호출해 php정보가 잘 설치되었는지 확인한다.





4. AWS RDS를 생성한다.






mariadb를 선택하고 비용문제가 있으니 프리티어를 꼭 체크해준다.

프리티어를 체크하면 다음단계로 기본설정으로 셋팅되어 진행된다. 






db 인스턴스 이름을 정하고 db에 접근하기 위한 username과 password를 지정한다.(꼭 기억해야함)


기본적으로 자신이 사용하고 싶은 데이터베이스 스키마를 생성할수 있다.

데이터베이스 이름은 o2로 지정하고 생성한다.




RDS 설치가 완료되면 

원활한 테스트환경을 위해 보안그룹을 열어준다.

자신의 RDS의 보안그룹으로 들어가 Inbound를 위치무관으로 설정한다.





테스트 이후에 보안그룹을 재설정하면 된다.



5. mysql이 잘 설치 되었는지 확인하기 위해 접속해본다.




1
2
mysql -h 퍼블릭 DNS(IPv4) 주소 -u RDS계정 -p
mysql -h mydb1.ceczqdx83uhe.ap-northeast-2.rds.amazonaws.com -u sanghyun -p
cs




잘 접속되었다면 rds를 생성할때 기본으로 만들었던 o2 데이터베이스가 잘 만들어졌는지 확인하고

간단한 쿼리도 날려본다.




1
2
3
4
mysql에 접속이 되었다면 
show databases;
use o2;
select * from topic;
cs




6. GUI 환경에서 db를 보고싶으면 heidisql을 깔아 

호스트명에  RDS 엔드포인트를 넣고 마스터 username과 password를 넣고 자신이 생성한 데이터베이스까지 넣어 접속해본다.





7  데이터베이스 스키마의 테이블을 생성하고 샘플데이터를 몇개 넣어서 확인한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* 테이블 생성 */
CREATE TABLE `topic` (
`id` int(11NOT NULL AUTO_INCREMENT,
  `title` varchar(100NOT NULL,
  `description` text NOT NULL,
  `author` varchar(30NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY (id)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
/* 테이블 조회 */
select * from topic;
 
/* 샘플 데이터 삽입 */
INSERT INTO `topic` (`id``title``description``author``created`VALUES(1'harry potter','magic is power''sanghyun', now());
INSERT INTO `topic` (`id``title``description``author``created`VALUES(2'lord of the ring''ring is mine''sanghyun', now());
INSERT INTO `topic` (`id``title``description``author``created`VALUES(3'venom''black venom is fighter''sanghyun', now());
INSERT INTO `topic` (`id``title``description``author``created`VALUES(4'spiderman','spider is red''sanghyun', now());
cs






8. php파일 만들어 db 연결하기



1
2
3
4
5
6
7
8
9
10
11
// 경로 이동해
cd /var/www/html
 
// db.php 만든다.
sudo vi db.php
 
// rds.php 만든다.
sudo vi rds.php
 
// rds_receiver.php 만든다.
sudo vi rds_receiver.php
cs


db.php 내용은 다음과 같다.


1
2
3
4
5
<?php
// mysqli_connect("엔드포인트주소","사용자이름","비밀번호","db스키마명");
$write = mysqli_connect("mydb2.ceczqdx83uhe.ap-northeast-2.rds.amazonaws.com","sanghyun","abcdefg1234","o2");
$read = mysqli_connect("mydb2.ceczqdx83uhe.ap-northeast-2.rds.amazonaws.com","sanghyun","abcdefg1234","o2");
?>
cs



rds.php 내용은 다음과 같다.



1
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
28
29
30
<!DOCTPYE>
<html>
 <head><meta charset="utf-8"></head>
  <body>
  <form action="rds_receiver.php" method="post">
       <p>
         제 목 :
         <input type="text" name="title">
       </p>
       <p>
         본 문 :
         <textarea name="description">
         </textarea>
       </p>
       <p><input type="submit"></p>
   </form>
   <ul>
<?php
include('db.php');
$sql="SELECT * FROM topic";
$result=mysqli_query($read,$sql);
 
while($row=mysqli_fetch_assoc($result)){
 $title=mysqli_real_escape_string($read,$row['title']);
 print("<li>{$title}</li>");
}
?>
    </ul>
   </body>
</html>
cs



rds_receiver.php 내용은 다음과 같다.



1
2
3
4
5
6
7
8
<?php
include('db.php');
$title = mysqli_real_escape_string($write$_POST['title']);
$description = mysqli_real_escape_string($write$_POST['description']);
$sql = "INSERT INTO topic(title, description, author, created) VALUES('{$title}','{$description}','sanghyun',NOW())";
mysqli_query($write,$sql);
header("Location: rds.php");
?>
cs



결과를 확인하면

select와 insert 모두 잘 되는 것을 확인할 수 있었다.






--------------------------------------------------------------------------------------------------------------------------



9. AWS server characterset 변경하기


데이터에 한글을 넣으면 ?나 특수문자 등 깨지는 현상 발생한다면 charset을 utf8로 바꿔줘야한다.





Server characterset과 Db characterset을 utf로 바꾸려면 aws rds의 파라미터그룹으로 접근해

파라미터 편집을 통해 캐릭터셋을 변경해줘야한다. 파라미터 그룹에서 






utf8로 바꾼뒤 db파라미터구성을 수정하여 DB 인스턴스를 재부팅하면 잘 적용되어 나온다.







출처 : https://opentutorials.org/course/2717/11268







1. 구글에 aws marketplace라고 검색하여 공식사이트에 들어가서 wordpress를 검색한다.






2. 환경설정으로 진입해






3. 버전을 확인하고 지역을 서울로 맞추고 launch한다.





4. launch 방법으로는 EC2를 선택하여 진행한다.





5. AWS AMI 선택이 완료된 이후이므로 

인스턴스 타입, 구성, 스토리지, 태그, 보안 그룹을 설정하여 시작한다.

(https://shlee0882.tistory.com/180?category=777755 참고)





6. WordPress 웹서버가 구축되면 퍼블릭 DNS와 IP로 접근이 가능하다.




7. 이제 워드프레스 관리자가 되어야한다.


사용설명서에 /wp-admin 을 붙여서 관리자로 진입하라고 안내하고 있다.

기본 서버 관리자는 'user'이고 비밀번호는 어떻게 얻는지 링크를 통해 안내하고 있다.




웹브라우저에서 ip주소/wp-admin 을 붙여서 url 이동하면 관리자 화면이 나오는데 username은 'user'

password를 알아야한다.





EC2 인스턴스 설정에서 > 시스템 로그 가져오기 




로그를 통해 암호를 확인한다.





아이디와 비밀번호를 넣고 접속하면 성공






이후 관리자의 여러기능을 활용해 수정하고 포스팅하여 자신의 블로그를 운영할 수 있다.








출처 : https://opentutorials.org/course/2717/11268





1. AWS 프리티어로 가입 한다. 






가입은 매우 간단하며 자신의 카드를 등록해야하고 인증과정에서 1달러가 결제된다.

카드 등록시 visa, mastercard인지 확인해야 한다. 본인은 체크visa카드로 가입을 진행하였다.



2. AWS > EC2 > 인스턴스 시작 


가입을 완료하고 AWS 많은 서비스 중 EC2 서비스를 선택하여 인스턴스 시작부분으로 진입한다.






3. 우분투 서버 만들기




1단계 우분투 이미지 선택 후





2단계 인스턴스 유형을 선택한다.







3단계 인스턴스 세부 정보 구성은 기본셋팅구성을 가져간다.






4단계 스토리지도 프리티어에서 사용할수 있는 기본 셋팅 되어있는 설정 그대로 가져간다.  


다음을 눌러 태그추가 단계에 들어오면






5단계 태그 추가를 통해 서버의 키(Name)와 값(Value)를 넣어준다.

 





6단계 보안 그룹 구성에 진입하면 SSH는 기본으로 잡혀있고 내 IP만 접속가능하게 설정하고

HTTP 추가를 하고 위치무관하게 잡아준다.






7단계는 지금까지 셋팅한 인스턴스를 어떻게 만들지 점검하고 생성을 누른다.






인스턴스 시작을 하면 키페어 생성 팝업이 나타난다.

키페어 이름은 원하는 것으로 정하고, 키페어 다운로드를 통해 암호화된 비밀번호를 다운받는다.

이미 만들어 놓은 키페어가 있다면 기존 키페어를 사용해도 된다.






다음과 같이 running 상태가 나타나면 서버가 잘 구동된 것이다.






생성한 ubuntu_server를 마우스 우클릭으로 연결하면



r



인스턴스에 연결하는 정보가 뜨게 된다.

퍼블릭 DNS를 가지고 putty나 xshell을 이용해 원격접속하여 제어할 수 있다.




3.1 xshell을 이용해 접속하는 방법



xshell을 실행해 세션의 퍼블릭 DNS의 내용을 호스트 값에 채워넣고





사용자 인증 탭의 사용자 키 부분을 연결시켜준다.






정보를 저장후 연결을 하면 원격으로 ubuntu_webserver가 잘 연결된 것을 확인 할 수 있다.






3.2 putty를 이용해 접속하는 방법



putty를 깔게되면 PUTTYgen이라는 프로그램도 같이 깔리게 된다.


자신의 인스턴스에서 지정한 키페어 이름을 확인하고 

키페어 암호를 파일형식으로 다운받아 


PUTTYgen을 실행시키고 Load를 눌러 다운받은 키페어 파일을 지정하고

Save private key를 눌러 재저장한다. 





ppk파일 형식으로 바뀐 파일을 PuTTY를 실행시켜 SSH > Auth > Browse 에 지정해주고




퍼블릭 DNS를 Host Name에 넣어준다.






연결을 하게 되면 ubuntu 로 로그인하여 접속한다.









-------------------------------------------------------------------------------------------------------------------------------------



3.3 우분투 서버 접속 방법



putty나 xshell을 이용해 접속이 되었다면 cmd명령어를 사용한다.


sudo apt-get update; 

cmd명령어를 통해 최신 업데이트 목록을 갱신시키고




sudo apt-get install apach2;

명령어를 넣어 웹서버 구동에 필요한 아파치2를 설치 한다.

설치 후 서버를 자동으로 실행시켜주는데 

웹브라우저에서 퍼블릭 DNS나 IP주소를 넣어 접속하면 apach2 기본 페이지가 잘 뜨는것을 확인할 수 있다. 



cd /var/www/html

명령어를 이용해 경로로 이동한뒤 sudo rm index.html 로 파일을 지우고 sudo nano index.html 로 파일을 재생성하여 코딩한다.





잘 반영되었는지 확인한다.









--------------------------------------------------------------------------------------------------------------------------------------------





4. 윈도우 서버 만들기




1단계에서 윈도우 서버 이미지를 선택하고






2,3 단계는 기본 설정으로 가져가고

4단계에서 윈도우 서버 기본크기가 30GB 이상인지 확인한다.






5단계에서 서버의 이름을 설정하고






6단계에서 보안그룹 설정을 통해 http가 위치 무관하게 어디든 접속 가능하게 설정한다.






7단계를 통해 인스턴스가 생성된 후 마우스 오른쪽 버튼 연결을 누른다.






생성한 키페어를 불러와 인스턴스에 연결시켜준다.










암호해독을 눌러 암호를 디코드한다.






원격 데스크톱 파일다운로드를 눌러 실행하면 






윈도우 서버로 연결된다.


윈도우 서버에서 Server Manager를 찾아서 실행 시킨뒤 Local Server에서 IE 보안 관련설정을 OFF해준다.






Service Manager에서 Manage > Add Roles and Features 를 눌러






Web Server(IIS) 를 설치해준다.






설치가 완료되면 Service Manager에 IIS가 생기게 되고 IIS Manager를 실행한다.





explore를 눌러







해당 위치에 메모장을 사용하여 index.html 파일을 간단하게 만들어 저장한다.







윈도우 서버컴퓨터에서 http://localhost/index.html 접속하면 잘나오는것을 확인했다.





로컬위치가 아닌 퍼블릭 DNS에서도 잘나오는지 확인이 필요해 AWS 콘솔에서 DNS주소에 index.html 붙여서 접속한다.







잘 반영되어 나오는 것을 확인할 수 있다.







출처 : https://opentutorials.org/course/2717/11268







1. EC2 인스턴스란?


EC2 인스턴스는 aws 컴퓨터를 임대하여 할당받는 것을 말한다.

물리적 컴퓨터 기계 위에 가상머신을 올려 

현재는 구성할 수 없는 저렴한 컴퓨터부터 강력한 비싼 컴퓨터까지 탄력적으로 만들 수 있다.  



2. aws ami


aws에서는 인스턴스를 생성할때 웹서버로 구성할 운영체제를 선택할 수 있다.

linux, ubuntu, window server 등 자신이 원하는 운영체제를 가상머신위에 올릴수 있다.



웹서버를 선택하여 처음부터

자신이 만들고 싶은 사이트를 설치 및 구성 하는 것은 시간도 많이 소요되고 어려운 일이다.


그래서 aws에서는 구글마켓플레이스처럼 

사용자가 원하는 사이트를 바로 구축하여 운영할 수 있게 

기본 셋팅을 이미지 형태로 제공하고 있다.

자신이 블로그를 만들고 싶다면 대표적으로 워드프레스를 검색하여 인스턴스로 바로 만들수 있다.

 


3. scale up 전략




예전 전통적인 모델 같은 경우 웹 서버를 구축하여 운영할 시 

사용자의 컴퓨터 서비스적 수요가 늘어나면 공급업체에서는 그 서비스를 원활히 운영하기 위해

더 좋은 컴퓨터로 업그레이드하여 서비스적 자원의 공급을 늘렸다.


그 과정에서 공급보다 수요가 많아지면 사용자의 서비스 품질 저하와 공급의 문제점이 발생한다.

또한 수요가 항상 많다가 갑자기 적어질 경우 불필요한 공급으로 인해 공급비용이 낭비되는 문제가 생긴다.


aws 클라우드 컴퓨팅 모델의 경우 변화하는 수요에 따라 탄력적으로 공급이 가능하다.



4. Elastic Ips 


aws에서는 한정된 ip주소를 가지고 있어 ( 0.0.0.0~255.255.255.255 ip주소가 한정적 )

사용자가 running한 인스턴스가 종료하게 되면 할당한 ip주소를  회수해 간다.

다시 인스턴스를 run하면 바뀐 ip주소를 부여해준다.


운영하던 인스턴스를 종료하고 다시 실행했을 시 

기존의 사용하던 ip주소가 바뀌면 문제가 생긴다.


이러한 문제로

사용자는 aws의 Elastic Ips (엘라스틱 아이피)를 할당받아 자신의 인스턴스에 부여하여 연결할 수 있다.


엘라스틱 아이피를 인스턴스에 연결하게 되면 인스턴스를 종료하고 다시 실행 했을 시

ip주소가 바뀌지 않는다.



5. 확장성을 위한 부하 테스트


aws 인스턴스 2대를 running하여

1대는 자신이 운영하고 있는 인스턴스

1대는 공격하려는 인스턴스

로 구성하여


우분투에서 ab -n 400 -c 100 http://ip주소/ 명령어를 사용하여

테스트를 진행한다.(요청은 400 , 동시접속 100 , 접속할 주소 http://)


결과를 통해 자신의 인스턴스를 확장해야 할지 말지 결정할 수 있다.



6. scale-up 방법


스케일 업 하려는 기존의 인스턴스를 이미지로 만들어

확장하려는 유형의 자원을 할당하여 인스턴스를 생성한다.

엘라스틱 아이피를 할당한다.


7. scale-out 방법


판도라는 숲의 특성은 뿌리가 하나여서 숲은 하나의 나무이다.

하나의 뿌리를 공유하고 있는 뿌리가 나무의 개체를 결정한다고 한다면

하나의 거대한 나무가 숲을 이루고 살아간다.


scale-out은 여러대의 컴퓨터가 협력하여 동일목표를 달성을 위해

일하는 컴퓨터들의 사회를 만드는 것이다.


사용자가 많아져 서비스 이용이 많아지면 


web server : 아파치, 엔진엑스

middle ware : php, jsp, spring

database : mysql, oracle

웹서버, 미들웨어, 데이터베이스 에 부하가 생긴다. 


이 부하를 1대의 컴퓨터가 아닌 3대의 컴퓨터로 일을 처리할 수 있고


ELB(elastic load banlancecr 부하분배기)로 여러개 인스턴스를 사용해서 부하를 감당한다.


8. auto scaling


서비스 이용이 많아지면 컴퓨터를 자동으로 생성해서

바로 서비스를 시작하게 했다가


서비스 이용이 적어지면 컴퓨터를 자동으로 삭제해서

과금발생 안하게함


인스턴스의 생성과 삭제를 auto로 반복한다.




출처 : https://opentutorials.org/course/2717/11268






프로젝트에서 sts를 사용해보았는데 익숙하지 않아 

간단하게 mysql을 이용해 data에 접근하는 방법을 알고 싶었다.

다행히도 자세하게 가이드가 된 문서(https://spring.io/guides/gs/accessing-data-mysql/)

가 있어 블로그에 정리하게 되었다.


sts를 이용해 mysql의 data를 접근하는 방법



1. STS 설치 후 패키지 익스플로러로 workspace 생성한다.



2. 다음과 같이 패키지 구조가 생성되었다면



lombok.jar를 다운(https://projectlombok.org/download)

받아 자신이 사용하는 sts나 eclipse 위치를 지정해주고 설치한다.




3. pom.xml 을 열어 다음과 같이 수정한다.


1
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>org.springframework</groupId>
    <artifactId>gs-mysql-data</artifactId>
    <version>0.1.0</version>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>        
 
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.23.1-GA</version>
        </dependency>
        <dependency
            <groupId>org.projectlombok</groupId
            <artifactId>lombok</artifactId
            <scope>provided</scope
        </dependency>
    </dependencies>
 
    <properties>
        <java.version>1.8</java.version>
    </properties>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-surefire-plugin</artifactId>
                  <version>2.19.1</version>
            </plugin>            
        </plugins>
        
    </build>
 
</project>
cs


pom.xml 수정이 완료되면 

MySQL 8.0 Command Line Client - Unicode 라는 터미널을 실행시켜

db 루트 비밀번호를 입력하고



아래 커맨드라인을 입력하여 db_example 이라는 db 스키마를 생성하고 user를 만들고 비밀번호와 권한도 준다.


1
2
3
mysql> create database db_example; -- Create the new database
mysql> create user 'springuser'@'%' identified by 'ThePassword'-- Creates the user
mysql> grant all on db_example.* to 'springuser'@'%'-- Gives all the privileges to the new user on the newly created database
cs


4. 다음 hello 패키지 안에 class파일을 생성한다.

총 3개 ( MainController.java, User.java , UserRepository.java)



다음과 같이 구성되었다면 안의 내용을 아래와 같이 넣어준다.


4.1 MainController.java


1
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
28
29
30
31
32
33
34
35
package hello;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
 
@Controller    // This means that this class is a Controller
@RequestMapping(path="/test"// This means URL's start with /demo (after Application path)
public class MainController {
    @Autowired // This means to get the bean called userRepository
               // Which is auto-generated by Spring, we will use it to handle the data
    private UserRepository userRepository;
 
    @GetMapping(path="/add"// Map ONLY GET Requests
    public @ResponseBody String addNewUser (@RequestParam String name
            , @RequestParam String email) {
        // @ResponseBody means the returned String is the response, not a view name
        // @RequestParam means it is a parameter from the GET or POST request
 
        User n = new User();
        n.setName(name);
        n.setEmail(email);
        userRepository.save(n);
        return "Saved";
    }
 
    @GetMapping(path="/all")
    public @ResponseBody Iterable<User> getAllUsers() {
        // This returns a JSON or XML with the users
        return userRepository.findAll();
    }
}
cs


4.2 User.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package hello;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Data;
 
@Entity // This tells Hibernate to make a table out of this class
@Data
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;
    private String name;
    private String email;
 
}
cs


4.3 UserRepository.java


1
2
3
4
5
6
7
8
9
10
11
12
package hello;
 
import org.springframework.data.repository.CrudRepository;
 
import hello.User;
 
// This will be AUTO IMPLEMENTED by Spring into a Bean called userRepository
// CRUD refers Create, Read, Update, Delete
 
public interface UserRepository extends CrudRepository<User, Integer> {
 
}
cs


5. 다음으로 /test/src/main/resources/application.properties 파일을 찾는다.


application.properties 파일은 비어있을텐데 이 부분에 다음과 같이 db정보를 입력해준다.


1
2
3
4
5
#spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/db_example
spring.datasource.username=springuser
spring.datasource.password=ThePassword
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
cs


6. 패키지를 잡고 다음과 같이 Update Maven Project를 한다.



7. 패키지를 잡고 다음과 같이 Maven install을 한다.




8. 빌드가 성공하면 서버를 올리고 웹브라우저를 열어 http://localhost:8080/test/all 를 입력해본다.


 



mysql workbench 실행하여



UserName을 springuser

password는 ThePassword를 입력하여 접속한다.



데이터가 없는것을 확인했으니 새로 넣어보자.


9. http://localhost:8080/test/add?name=sanghyun&email=shlee0882@gmail.com 을 입력하면



다음과 같이 데이터가 들어가게 된다.



데이터 조회를 해보면 json형식으로 나온것을 확인할 수 있다.



sts와 mysql을 이용하여 데이터 조회(select)와 입력(insert) 기능을 구현하였다.


소스첨부 : 

test.z01

test.z02

test.zip


출처 : https://spring.io/guides/gs/accessing-data-mysql/




1. SQL EXPLAIN 정리


1.1 부서 테이블


1
2
3
select * 
  from dbadev.dept
;
cs



부서테이블에는 4개의 행 ( 4rows returned )


1.2 직원 테이블


1
2
3
select * 
  from dbadev.emp
;
cs





직원테이블에는 14개의 행 ( 14rows returned )


1.3 부서와 직원 테이블을 내부조인



1
2
3
4
5
6
7
8
9
10
11
SELECT a.deptno
     , a.dname
     , a.loc
     , b.empno
     , b.ename
     , b.job
  FROM dbadev.dept as a
 INNER JOIN dbadev.emp as b
    ON a.deptno = b.deptno
 WHERE a.deptno= '20'
;
cs




1.4 EXPLAIN을 사용한 부서테이블과 직원테이블 내부조인 쿼리 실행결과


1
2
3
4
5
6
7
8
9
10
11
12
EXPLAIN
SELECT a.deptno
     , a.dname
     , a.loc
     , b.empno
     , b.ename
     , b.job
  FROM dbadev.dept as a
 INNER JOIN dbadev.emp as b
    ON a.deptno = b.deptno
 WHERE a.deptno= '20'
;
cs





MySQL 실행 계획 항목 설명


1. id

쿼리의 실행 순서대로 1부터 순차적으로 값을 부여. 즉 쿼리의 실행 순서라고 봐도 무방함.

다만 join 의 경우엔 하나의 구문에서 두개 이상의 테이블을 참조하기때문에 모든 테이블에 같은 순번이 부여됨.



2. select_type

select 구문의 실행 타입.


 속성값

 내용

 SIMPLE

 단순 select 구문으로 별다른 조인이나 서브쿼리가 없음.

 PRIMARY

 서브쿼리를 이용할 경우 서브쿼리의 부모가 되는 select 쿼리

 union을 사용할 경우 union 의 첫번째 select 쿼리.

 UNION

 union을 사용한 쿼리에서 첫번째를 제외한 나머지 select 쿼리.

 DEPENDENT UNION

 UNION과 기본적으로 동일하나 외부쿼리에 영향을 받음

 UNION RESULT

 UNION 쿼리의 결과

 UNCACHEABLE UNION

 UNION과 기본적으로 동일하나 공급되는 모든 값에 대해 UNION 쿼리를 재처리

 SUBQUERY

 서브쿼리 또는 서브쿼리를 구성하는 첫번째 select 구문

 DEPENDENT SUBQUERY

 SUBQUERY와 기본적으로 동일하나 외부쿼리에 영향을 받음

 UNCACHEABLE SUBQUERY SUBQUERY와 기본적으로 동일하나 입력 값에 의한 캐싱을 이용할 수 없음


3. table


테이블명. 약칭(Alias)을 사용할 경우 약칭이 표시됨


4. type


단일 테이블만 사용된 쿼리일 경우 : 테이블 access 형태

두 개 이상의 테이블이 조인된 SQL 일 경우 : 테이블 간의 조인 형태

아래 목록의 순서는 성능이 좋은 것 부터 나열되어 있음 


 속성값

 내용

 sytem

 테이블에 row가 1건이라 매칭되는 row도 1건인 경우.

 const

 옵티마이저가 unique/primary key를 사용하여 매칭되는 row가 1건인 경우.

 eq_ref

 1:1의 join 관계

 unique/primary key를 사용하여 join을 처리함.

 ref

 1:n의 join 관계

 non-unique 인덱스가 사용되거나, 복합키로 구성된 인덱스 중, 

 일부 컬럼만 이용하여 조인될 경우

 ref_or_null

 ref와 동일하나 null 값에 대한 최적화가 되어있음.

 fulltext

 fulltext 인덱스를 사용

 index_merge

 동일한 테이블에서 두개 이상의 인덱스가 동시에 사용됨.(fulltext 인덱스는 제외)

 unique_subquery 서브쿼리에서 unique한 값이 생성되는 경우
 index lookup function이 사용됨.(서브쿼리 최적화)
 index_subquery unique_subquery와 비슷하나 결과값이 unique하지 않은 경우
 range 주어진 범위내의 row를 스캔함
 범위내의 row가 많으면 많을수록 성능이 저하됨
 index 인덱스를 사용하긴 하나 전체 인덱스 block을 스캔함.
 즉 인덱스를 사용하긴 하나 all 타입과 흡사함
 all 전체 데이터 block을 스캔.(full table scan)


5. possible_keys

옵티마이저가 쿼리 처리를 위해 고려한 인덱스 후보. 즉 사용가능한 인덱스들의 리스트.

possible_keys와 key값은 항상 같지 않다. 즉 옵티마이저가 인덱스를 고려했지만 사용하지 않을수도 있음.


6. key

옵티마이저가 실제로 사용한 인덱스 키.

type값이 index_merge 일때 key값은 사용된 모든 인덱스 키를 출력함.



7. key_len

옵티마이저가 사용한 인덱스 키의 길이값. key컬럼에서 인덱스가 언급되지 않았다면 null값.

key_len값으로 옵티마이저가 실제 복수 컬럼키중 얼마나 많은 부분을 사용할 것인지 알수 있다.


8. ref

행을 추출하는데 키와 함께 사용된 컬럼이나 상수값.



9. rows

쿼리를 수행하기 위해 검색해야 할 row의 개수. 인덱스와 조건을 최적화 해서 row의 개수를 줄이면 줄일수록 퍼포먼스가 향상됨.



10. extra

옵티마이저가 쿼리를 해석한 추가적인 정보를 출력함





위쪽에 정리된 표를 바탕으로 EXPLAIN 실행결과



1번째 row를 해석하면


id가 1 (쿼리의 실행 순서가 1번째임)

SIMPLE (단순 select 구문)

테이블명은 dept 테이블을 alias로 명시한 a로 표시

const (옵티마이저가 unique/primary key를 사용하여 매칭되는 row가 1건인 경우 표시, a.deptno = 20으로 명시했으므로)

옵티마이저가 쿼리 처리를 위해 고려한 인덱스 후보는 PRIMARY

옵티마이저가 실제로 사용한 인덱스 키 PRIMARY

옵티마이저가 사용한 인덱스 키의 길이값 4

행을 추출하는데 키와 함께 사용된 컬럼이나 상수 4

쿼리를 수행하기 위해 검색해야 할 row의 개수 1


2번째 row를 해석하면


id가 1 (쿼리의 실행 순서가 1번째임)

SIMPLE (단순 select 구문)

테이블명은 emp 테이블을 alias로 명시한 b로 표시

ALL 전체 데이터 block을 스캔.(full table scan)

쿼리를 수행하기 위해 검색해야 할 row의 개수 14

Using where : where절이 다음 조인에 사용될 row나 출력될 row의 개수를 제한하는 경우 나온다.



+ Recent posts