Linux 계열의 운영체제는 EXT 라는 파일시스템 구조를 사용한다.


* EXT(Extended file system) : 리눅스 용으로 개발된 파일시스템으로 Minix 파일시스템의 한계를 극복하고자 만들어졌다.


* EXT2 

 : Linux 의 초창기 파일시스템 표준이다. TIMESTAMP 의 제약이 있으며 장애 발생시 파일 시스템 복구를 위한 fsck 도구를 갖고 있다.


- EXT2 inode : inode 는 파일 시스템의 가장 기본이 되는 단위이다. 

각각을 구분할 수 있는 고유번호를 가지고 파일의 데이터가 어느 블록의 어느 위치에 저장되어 있는지, 파일에 대한 접근권한, 파일의 최종 수정시간, 파일의 종류 등의 정보를 inode 테이블에 저장한다.

저장되는 정보는 모드, 소유자 정보, 크기, Timestamp, 데이터블록이다. 


- EXT2 super block : 슈퍼블록은 해당 파일 시스템의 기본적인 크기나 형태에 대한 정보를 저장한다. 슈퍼블록에 저장되는 항목은 다음과 같다.


 (1) Magic number : 마운트하는 소프트웨어에게 EXT2 파일 시스템의 슈퍼블록임을 확인하게하는 값이다.


 (2) Revision level : major level과 minor level 로 구성되어 있으며, mount 시스템이 file system 에서 지원되는지에 대한 버전 정보 확인을 위해 사용된다. 

 또한 이 정보를 이용해 호환성을 판단할 수 있다.


 (3) Mount count : 마운트 횟수와 최대마운트 횟수를 저장한다. 마운트가 실행될 때마다 카운트가 증가하며 이 값을 이용해 시스템 전체를 검사할 필요가 있는지 확인한다.


 (4) Block group number : 블록 그룹번호는 슈퍼 블록 복제본을 갖고 있는 블록 그룹의 번호를 나타낸다. 


 (5) Block size : 블록 크기는 File System 의 블록크기를 바이트 단위로 표시한다.


 (6) Blocks per group : 그룹에 속한 블록 수를 저장한다.


 (7) Free block : 파일 시스템 내부적으로 존재하는 프리블록 수를 나타낸다.


 (8) Free inode : 파일 시스템 내부적으로 존재하는 free inode 수를 나타낸다.


 (9) First inode : 리눅스 시스템의 첫번째 inode는 "/" 디렉토리 엔트리를 나타낸다.


- EXT2 group descriptor : 블록그룹에서 블록의 할당 상태를 나타내주는 비트맵이다. 블록을 할당하거나 해제할 경우 참조되는 정보로, block bitmap, inode bitmap, inode table 을 구성요소로 갖는다.

inode 비트맵은 블록 그룹에서 inode 할당상태를 나타내주는 비트맵으로 그 수는 블록 비트맵과 같은 block 의 수와 동일하다.


- EXT2 directory : EXT2 파일 시스템에서 디렉토리는 파일에 대한 접근 경로를 생성하고 저장한다.

directory 는 entry 의 list로 나타내어 지며, 엔트리 리스트에는 inode, 이름길이, 이름 정보가 저장된다.



* EXT3

 : 저널링을 지원하는 호환성 높은 파일시스템 구조이다. 온라인 상태에서 파일시스템을 확장 가능하며, directory 에 대한 tree 기반 indexing 을 제공한다.

쓰기 실행중 fsck 가 불가능한 단점이 있다.


 - 저널링(Journaling) 기술

기존의 EXT2는 시스템에 문제가 생기는 경우 파일시스템이 손상될 수 있는 문제점을 갖고 있었고, 이를 해결하기 위해 fsck(File System Check) 라는 도구를 사용하였다.

하지만 복구에는 시간이 오래걸리고, 복구하는 동안 시스템의 사용으 불가능한 단점이 있었다. 

EXT3는 이 단점을 해결하기 위한 저널링(Journaling) 기능을 사용하며, 이를 통해 파일 시스템의 무결성과 복구 기능을 갖추게 되었다.

저널링 기술은 파일 수정 이전에 로그에 내용을 저장하고, 로그를 바탕으로 수정 내용을 처리하는 Replay 과정을 거치며, 이런 파일 시스템의 특성을

Logging File System 이라고 한다.


 - 저널링(Journaling) 파일 시스템의 구조

저널링을 수행하기 위한 로그영역과 일반 파일 시스템 영역으로 나뉜다. Log는 Rolling File 형태의 구조로 관리되며, 이는 전용 스레드가 처리한다. 

로그에 대한 트랜잭션이 별도로 관리되며, 트랜잭션 내의 레코드 I/O 를 바탕으로 파일시스템이 관리된다.



* EXT4

 : Linux 파일시스템 표준으로, Timestamp 가 나노초단위로 개선되어 있다. 

 ext2, ext3 를 ext4 로 마운팅 가능하며 호환성이 뛰어나다. 다음과 같은 특징들을 지닌다.


 (1) 대형 파일 시스템 : 최대 1 Exabyte 까지의 볼륨을 지원한다.


 (2) Extent : 전통적인 Block mapping 을 대체하기 위한 extent 방식을 사용한다. inode 에 최대 4개의 extent를 할당해서 물리적으로 인접한 블록들을 묶어서 관리한다.


 (3) Allocate on flush : 데이터가 디스크에 실제로 쓰여지기까지 블록 할당을 지연시키는 기술이다. 하나의 파일에 대해 블록의 분산을 막을 수 있고 디스크 이동을 최소화시킬 수 있다. 다만 장애 시 충돌 가능성이 존재한다.


 (4) 디렉터리 제한 변경 : 하위 Directory 에 대한 제한이 32000개에서 64000개까지 늘어났다. 




참조 : http://egloos.zum.com/nix102guri/v/392605




운영체제는 시스템의 Disk partition 상에 파일들을 연속적이고 일정한 규칙을 갖고 저장하는데, 이러한 파일을 관리하는 규칙을 File System이라 한다.


FileSystem 의 구조


Unix/Linux 계열의 운영체제는 Tree 형태의 계층적인 파일구조를 구성한다. 다음은 File System 을 구성하는 요소들이다.


- Super block : 슈퍼블록은 FileSystem에 의존하는 정보를 가지며 FileSystem 의 크기 등과 같은 File System 의 전체적인 정보를 포함한다.


- inode(Index node) : 아이노드(inode)는 파일의 이름을 제외한 해당 파일의 모든 정보를 갖고 있다.

갖고있는 정보로는 파일의 소유권, 권한(Permission), 실제 데이터가 있는 물리적 주소, 파일의 형태, 크기, 링크 수, 수정/사용 시간 등이 있다.

파일 이름은 inode 의 번호와 함께 directory 안에 저장된다.

각 파일들은 1개씩의 inode를 갖고 있으며, 파일 시스템 내에서 파일의 이름을 key 로 식별되는 inode 숫자를 통해 식별 가능하다. (즉, inode는 파일 시스템 내에서 유일하다.)


- data block : 데이터블록은 inode 에 포함된다. inode 는 몇개의 data block 을 포함하고 있으며, 각 데이터 블록은 파일들의 데이터를 실제로 저장하고 있다.


- Directory block : 파일 이름과 inode 번호를 저장한다.


- Indirection block : 간접 블록은 추가적인 데이터 블록을 사용하기 위한 포인터들이 할당되는 공간이다. 

실제로 inode 는 적은 수의 데이터블록을 갖고 있으며 더 많은 데이터블록이 필요할 경우 이를 동적으로 가리킬 포인터가 저장된다.


- Hole : 홀은 inode 나 간접 블록 안의 데이터 블록의 주소로 특별한 값을 저장한다. 

hole 을 파일 안에 구조화되지만 hole 을 위한 실질적인 disk 공간은 할당되지 않는다. 단지 0바이트가 파일 안에서 특정 공간을 차지하고 있다고 가정하는 것이다.


위의 개념들 중에서 중요하고도 특징적인 개념은 Inode 의 개념이다.

파일시스템은 inode 를 참조하여 파일의 정보를 다룰 수 있다.


( * 참고로 현재 파일시스템 내의 Total Block / Free Block, Total Inode / Free Inode 정보는 [stat -f "파일이름"] 명령어를 통해 조회가능하다.)


또한 위의 내용들을 자세히 이용하기 위해서는 Nix 계열의 파일시스템인 EXT에 대해서도 알아야 한다. EXT에 대해선 다음 포스팅에 추가한다.




먼저 <div> 태그와 <span> 태그의 차이점을 알아보자.


사용하는데 있어서 차이를 알아내긴 어렵지만 이는 생각보다 간단한데 단순히 div 는 block element 이고, span 은 inline element 라는 점이다.


좀더 설명하자면, div는 Document 의 부분들을 감쌀 수 있도록 설계되어 있지만, span 은 small portion(text, image 등)에 해당하는 작은 부분만 감싸게끔 설계되어 있다.


여기서 Block Level Element 와 Inline Level Element 라는 다소 생소한 분류가 등장한다.


* Block Level Element 와 Inline Level Element 의 차이점


 : Block Level Element 들은 <body> 요소 안에서만 표현되도록 정의되어 있다. 또한 Block Level element 들은 

 감싸고 있는 표현 전후를 분리시켜주는(개행) 특징을 가진다. 즉, 이 영역은 앞 뒤 영역과 구분된 독자적인 영역이 된다.

 또한 Block Level Element 들은 Inline Level Element 들을 포함할 수 있다.


 : Inline Element 는 Tag 가 시작된 라인에서 바로 시작하며 이전과 이후를 구분(개행)하지 않는다. HTML5 이전의 일반적인 Inline Element 는 Block Element 를 포함하지 못한다.



 HTML5가 되면서, 몇몇 Block Element 들이 Inline Element 안에 포함이 가능하게 되면서, 차이점이 조금 불분명해졌다.


그럼에도 Span 은 Phrasing content 만을 안에 포함시킬 수 있고, div 는 flow content 를 포함시킬 수 있다는 차이점이 있다.

여기서 flow content 와 phrasing content 는 부가적인 분류 카테고리이다. 

flow content 는 마크업으로써 표현되는 컨텐츠 자체를 의미하며, phrasing content 는 해당 요소가 강조 하거나 꾸며주는 역할을 하는 도구로써의 Element 일 경우를 말한다.


HTML이 모던해짐에 따라 element 들은 복수의 역할을 수행할 수 있도록 진화하고 있으나, 그건 HTML 초기 디자인이 의도한 바가 아니다.

가령 <p> 태그는 paragraph 를 위해 만들어진 태그이며, <li> 는 list item 을 위해 만들어진 태그이다.

HTML 은 모던해짐과 동시에 혼용될 수 있는 역할에 따른 사용을 방지하기 위해 의미없는 차이임에도 태그를 나누는 경우들이 있다.






IAM(Identity and Access Management)이란 AWS 리소스에 대한 접근을 안전하게 제어할 수 있는 서비스이다.

프로비저닝된 서비스들에 대한 인증 및 권한을 관리하는 또하나의 클라우드 서비스로 이해하면 간단하다.



AWS 서비스를 이용 시, AWS 리소스에 대한 사용 권한을 설정할 수 있다. 즉 아무나 자신의 리소스를 관리할 수 없도록 하는 보안 장치같은 것이다.



이를 위한 방법으로는 다음과 같은 방법들이 있다.


(1) AWS 계정을 직접 생성하여 해당 계정을 통해 직접 AWS 리소스에 접근하는 방법이 있다.


(2) IAM 계정 생성을 통해 해당 리소스에 접근하는 방법이 있다.



위 방법들에 대한 간략한 설명은 다음과 같다.


처음 AWS 에 계정을 생성하면 Root User Credential 이라는 자격증명을 받게 되고, 이를 루트 사용자 권한이라 한다.

이를 이용하면, AWS 의 모든 리소스에 무제한으로 접근 및 제어가 가능하지만, 이 Credential 은 계정과 직접적으로 연결되어 있기 때문에 일반적인 Access 시나 협업을 할 때에는 사용하지 않는 것이 좋다. (1번 방법)


보통은 Root User Credential 을 이용해 서비스에 알맞게 IAM Credential 을 생성하여 사용자를 인증하고 리소스에 접근할 수 있도록 한다. (2번 방법)



IAM 은 계정에 대한 인증 및 권한 부여를 제어하는 데 필요한 인프라를 제공한다. IAM 인프라에는 다음과 같은 요소들이 포함되어 있다.


- Principal(보안 주체) : AWS 리소스에 대한 작업을 수행할 수 있는 개체를 말한다. AWS 계정 루트 사용자, IAM 계정 사용자 및 IAM 역할 사용자 등이 있다.


- 요청 : 보안 주체가 AWS Management Console, AWS API 및 CLI 를 사용하려고 할 때의 요청이다. 


- 인증 : 보안 주체는 리소스를 사용하기 위해 요청을 만들 때, 인증 과정을 거치게 된다.


- 승인 : 인증된 보안주체의 요청을 허가할지 말지 승인 과정을 거치게 된다. 각 리소스별로 정책을 명시하고 이 정책에 부합하는지를 확인한다.


- 작업 또는 연산 : 인증된 요청의 승인이 완료된 후 서비스가 실행된다. 주로 AWS 리소스들에 대한 CRUD 가 제공된다.


- 리소스 : 작업을 통해 리소스에 반영 및 조회가 가능하다. 



이렇게 생성된 IAM 자격 증명을 통해 IAM User가 AWS 계정의 리소스들에 접근하고 사용할 수 있다.


이러한 IAM User 들에 대한 관리는 IAM Policy 라 하는 일종의 정책으로 관리가 되는데, 정책을 통해 어떤 리소스의 어떤 Credential 들에 대해 허용(Allow) 또는 비허용(Disallow) 할지 결정한다.


IAM Policy 는 IAM User 들을 개별 관리할 수도 있지만 IAM Group 의 형태로 묶어서 권한을 할당할 수도 있다. 혹은 Role 을 정해서 Role 에 적합한 권한들만을 부여한 뒤, 해당 자격증명을 통해 관리하게 할 수도 있다.

이처럼 IAM 을 사용하면 보안과 권한 관련 설정들에 대해 인프라 담당자에게만 권한을 부여하거나 해당 팀원들에게만 최소한의 권한을 부여하도록 할 수 있다.



자세한 내용은 AWS 공식 문서를 참조하면 잘 설명 되어 있다.

(출처 : https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/introduction.html)



Data Replication은 데이터를 물리적으로 다른 서버 공간에 복제하는 일이다. 

이를 잘 이용하면 부하 분산 및 고가용성, 버전 테스트 등 멋지게 사용할 수 있는 방안이 많아진다. 

일반적으로 하나의 Master와 여러 개의 Slave로 이루어진 구조에서 Read Only인 Slave 노드들에 Write 가능한 Master의 데이터가 업데이트되면 동기화시키는 방향으로 복제가 이루어진다.


Database Replication 은 기본적으로 비동기(Asynchronous)로 이루어진다.


Replication 은 대게 Writable 한 Master Node 에서 Readonly인 Slave로 이루어진다.


Replication 으로 인한 이점들에는 다음과 같은 것들이 있다.


- Scale out solution : Replication 을 통해 Read 요청에 대한 분산을 여러 Slave 로 나눔으로써 병목현상을 해결할 수 있다. 


- Data security : 데이터가 Slave로 복제됨에 따라서 마스터 서비스에 대한 영향 없이 데이터에 대한 백업이 가능하다.


- Analytics : 서비스에 영향을 미치지 않고 데이터 분석이 용이하다.


- Long-distance data distribution : Data를 여러 지리적 Location 혹은 Local에 Copy 를 만들 수 있다. 이는 자연적 재해나 지리적 장애에 대한 대응책이 될 수 있다.



MySQL 의 Replication은 로그 기반으로 비동기적으로 데이터를 복제한다. 


마스터에서는 데이터가 변경되면 Binary Log라는 곳에 이력을 기록하는데, 실행된 SQL을 그대로 기록하거나(Statement-Based), 변경된 행을 Base64로 인코딩하여 기록하거나(Row-Based), 적절히 혼합한형태(Mixed Type)로 동기화를 수행한다. 


(1) Master에서 데이터 변경이 일어나면 자신의 데이터베이스에 반영한다.


(2) Master에서 변경된 이력을 Binary Log에 기록한 뒤 관련 이벤트를 날린다.


(3) Slave IO_THREAD에서 Master 이벤트를 감지하고 Master Binary Log의 Relay Log에 기록한다.


(4) Slave SQL_THREAD는 Relay Log를 읽고 자신의 DB에 기록한다.



마스터에서는 여러 세션에서 데이터 변경처리가 가능하지만 Slave에서는 오직 SQL Thread에서만 데이터 변경처리가 이루어질 수 있기 때문에 Master의 데이터 변경 트래픽이 과도할 경우 동기화 시간 차이가 크게 날 수도 있다.


동일한 Database 소스를 여러 군데에 분산시키는 점은 개발자가 API 를 구현할 때에도 신경써주어야 하는 부분이다.


WAS 레벨에서 어떤 DB를 바라볼지에 대한 문제는 보통 Web Framework 레벨에서 지원해주는 경우가 많다. 가장 간단한 방법으로는 서로 다른 커넥션 풀을 만들어 쿼리를 날릴때마다 직접 분기해주는 방법이지만 이는 비효율적이며 비생산적이다.


먼저 Spring을 사용하면 @Transactional(readOnly=true) 라는 어노테이션에서 readOnly 옵션을 이용해서 트랜잭션 설정 하나로 서로 다른 데이터 소스로 연결시킬 수 있다. 

또한 Spring의 AbstractRoutingDataSource 클래스는 여러 개의 DataSource를 하나로 묶고 자동으로 분기처리해주는 Spring 기본클래스이다. 이를 이용해서 @Transactional 과 잘 연계하면 쉽게 분기처리가 가능하다.


참고로 Spring의 @Transactional 처리는 TransactionManager 선별 -> DataSource에서 Connection 획득 -> Transaction 동기화 순으로 일어나기 때문에 커넥션을 동기화 이후에 얻는 Lazy 한 방식을 사용해야 함을 명심한다.



본 포스팅에서 언급한 내용은 Master-Slave Replication 이지만, 경우에 따라 Master-Master Replication 을 구조로 구성하기도 한다.

Master-Master replication 구조를 고려할 때에는 Master 간 Conflict 및 데이터베이스에서의 ACID 성질의 유지가 힘들기 때문에 신경쓸 부분이 조금 더 많다. 

그렇기 때문에 Master-Master Replication 의 경우 Active Directory / LDAP 과 같은 Directory Service Server 나 Data 의 Conflict 우려가 적고 Accessibility 가 중요한 서비스의 경우 고려된다.

(참조 : https://stackoverflow.com/questions/3736969/master-master-vs-master-slave-database-architecture)



클라우드 환경이 도입되면서 Multi A-Z 에서의 Replication 전략도 눈여겨 봐야하는데, 보통 하나의 Master 를 한 Availability Zone 에 두고 Read-only Slave 들을 같은 Zone 및 다른 AZ 에 배치시켜두는 형태를 취한다. AWS 에서는 이를 Read-Replica 라는 서비스로 제공한다.




 NoSQL RDBMS의 한계를 극복하기 위하여 만들어진 새로운 형태의 Database 패러다임이다

기존의 관계형 데이터베이스와 다르게 고정된 스키마 및 JOIN이 존재하지 않으며 트랜잭션의 개념이 존재하지 않는다.


NoSQL은 초당 데이터가 수십만개씩 쌓이는 소셜 서비스들 및 Massive 한 규모의 트랜잭션을 다루는 웹서비스들이 많아지면서 그 사용량이 많아지고 있다.

기존의 RDBMS의 경우 Read 집약적인 서비스에서 강하지만 큰 규모의 서비스임에도 Write가 많은 서비스의 경우 성능 저하가 눈에 띄게 되고 이는 서비스의 불안정을 초래할 수 있다


NoSQL은 스키마 자체를 없애면서 데이터의 정형성은 보장하지 못하는 대신 데이터의 정형성을 위해 RDBMS가 희생하는 분산처리의 장점을 살린다

(RDB의 경우 규격화된 스키마 때문에 ACID 를 고려한 분산이 쉽지 않다.)


NoSQL 모델의 종류로는 Key/Value Store, Wide Column Store, Document Store 가 있다.


-  Key/Value Store 는 거의 모든 종류의 NoSQL 이 지원하는 개념으로 Key에 대한 Value를 저장하는 개념이다. Value Primitive 타입이 될 수도 있지만 Column Family라 불리는 Column, Value 페어의 컬렉션이나 Object가 된다. Redis가 이러한 모델이다.


-  Ordered Key/Value Store Key/Value Store와 데이터 저장 방식은 동일하나 내부적으로 Key Sorting한다. HBase, Cassandra 가 있다.


-  Document Key/Value Store  Key/Value Store와 같지만 Value 값에 Object와 같은 복잡한 형태가 들어갈 수 있다. MongoDB, CouchDB등이 있다.



NoSQL RDB로 대표되는 SQL의 장점을 흡수하기 위한 테크닉들이 있다

이는 아무리 NoSQL 이 기존 RDB의 한계를 뛰어넘고자 고안된 모델이라 할지라도 관계형 데이터베이스가 갖는 데이터의 무결성과 관계지향 모델이 갖는 장점을 무시할 수 없다는 것을 의미하기도 한다.


(1)  Atomic aggregation : 두개 이상의 테이블을 업데이트할 때 트랜잭션 관리가 트랜잭션이 없는 NoSQL에서는 문제가 될 수 있다. 이럴 때 NoSQL을 사용하는 테크닉은 기능별로 테이블을 묶는 것이다. 예를들어 유저 정보를 갱신할 때 유저의 주소 정보와 프로필 정보를 동시에 갱신을 한다면 주소 정보와 프로필 정보를 유저 하위로 밀어넣어서 한번에 처리하게끔 한다.


(2)  Index : 일부 NoSQL 제품의 경우 Index를 지원하지만 그렇지 않은 경우 Key에 대한 Value를 검색하는 경우가 아니라면 Full Scan을 하게 된다. 이를 해결하기 위한 테크닉으로 인덱스를 위한 별도의 인덱스 테이블을 만드는 방법이 있다. 알고자 하는 항목에 대한 Key를 인덱스 테이블에 담아두어 한번에 참조가능하게 할 수 있다.


(3)  계층형 구조 : 데이터 모델링을 하다보면 Tree와 같은 계층형 모델이 필요한 경우가 있다. NoSQL에서는 이를 해결하기 위해 몇가지 설계를 이용한다.

     첫번째는 계층형 구조 자체를 아예 별도의 테이블 형태로 관리하는 것이다.

     ((ex) key : root – {parent: NULL, child: test}, key: test – {parent:root, child:NULL} => 이 경우 Tree 구조 순회에 많은 IO를 소모한다.) 

     또는 키 자체를 경로로 잡는 경우가 있다. ((ex) key: root -  value: object, key: root/test – value : object2 => 가장 무난하다.) 

     혹은 Leaf Node에만 데이터를 저장하고 줄기 노드에는 경로만을 저장하는 Nested Set 방식이 있다.


 위와 같이 NoSQL은 간단한 사용 인터페이스와 Insert에서의 이점 및 분산환경에서의 손쉬운 이식이라는 장점을 얻는 대신 데이터 모델링이 작업의 주가 된다

웹서비스에 새로운 시스템으로 NoSQL을 도입하고자 한다면, 기존의 전통적인 개체 지향 모델링에서 쿼리 지향 모델링으로 변경해야 하고 정규화를 역정규화로 바꾸는 노력이 필요하다


구조가 단순하지만 부족한 부분이 분명 있기 때문에 실무에서는 데이터의 정합성이 중요하고 복잡한 처리가 필요하거나 SELECT 집약적인 데이터에 대하여 RDB Cache 솔루션과 같이 사용하고, 분산처리 및 INSERT 집약적인 확장성 요청이 많은 경우 NoSQL 을 고려한 설계를 통해 혼용해서 쓰는 것이 Best이다.



* NoSQL은 분산형 구조를 띄고 있는 만큼(Schemeless) CAP의 특성을 지닌다.


Consistency : 분산된 노드 중 어느 노드로 접근하더라도 데이터 값이 같아야 한다는 기능적 특징이다.


- Availability : 클러스터링된 노드 중 하나 이상의 노드가 실패하더라도 정상적으로 요청을 처리할 수 있어야 한다.(Failover)


- Partition Tolerance : 클러스터링 노드 간의 네트워크 장애가 나더라도 정상적으로 서비스가 수행가능해야 한다.

 


 


 SQL Injection 은 웹에서 DB에 접근하는 쿼리 자체에 공격을 가하는 것으로 해커들이 많이 이용하는 기법 중 하나이다

주로 학부과정의 컴퓨터 보안 시간에 기본적으로 다루는 내용이지만, 실제로 볼 일이 많이 없다가 대응해야할 일이 생겨서 정리해보았다. 


SQL Injection 을 이용해서 대표적으로 다음과 같은 방식의 공격이 사용된다.


(1)  인증 우회(Auth Bypass)

 : SQL 쿼리문의 TRUE/FALSE 논리 연산 오류를 이용해서 인증 쿼리문이 무조건 TRUE가 나오게끔 하는 방식이다. Select count(*) from member where uid=’입력된 아이디’ and pw = ‘입력된 비밀번호에서 입력된 아이디부분에 ‘ or 1=1# 과 같은 내용을 삽입하면 뒤의 내용이 주석처리 되면서 무력화 시킬 수 있다.


(2)  Data disclosure (데이터 노출)

 : 서버가 반환하는 Error 등을 참고해 정보를 파악해서 각 Column과 자료형을 알아내는 방식이다. www.example.com?idx=1’ having 1=1# 과 같은 방식으로 날리는 쿼리 파라미터를 분석한 뒤, 위와 같이 요청했을 때 반환되는 에러메시지를 분석해서 테이블을 유추한다. Error Based / Union Based 와 같은 공격이 이런 방식을 이용한다. 에러 메시지가 뜨지 않는 경우 Delay 함수등을 Inject 하여 응답시간으로 동작을 유추한다.

 : 그 외에도 Procedure 호출 이나 명령어 삽입 등의 공격도 있다.



 위의 내용은 SQL Injection 의 원론적인 부분이고 실무에서 쓰는 프레임워크들은 대부분 SQL Injection 에 대해 방어코드가 기본적으로 되어있다

하지만 그래도 개발자로써 기본적으로 숙지해야할 보안의 기본적인 원칙들은 다음과 같다.


(1)  Validation : 자유롭게 입력가능한 값에 대한 Validation 이 필수적이다.


(2)  Parameter : 특히 API등에서도 Parameter 는 특수문자나 SQL 명령어가 입력될 수 없도록 필터링이 필요하다. 물론 더 문제인건 입력받는 Parameter를 바로 DB로 전달하는 것이다


(3)  Prepared : SQL 입력이 되는곳은 Prepared Statement 를 통한 처리나 ORM 등을 통해 매핑시켜서 사용하는 것이 안전하다.


(4)  권한 : 데이터 다루는 권한은 최소한으로 부여한다.


(5)  에러메시지는 노출하지 않는다.


(6)  동적 SQL의 사용은 지양한다.

 



Software 를 다루는데 있어서 Proxy 는 흔히 접할 수 있는 단어이다.

많은 IT에 대해 잘 알지 못하는 사람들도 "우회" 를 목적으로 운영되는 프록시 서버에 대해 알고 있으며, Software 공학에 있어서 Proxy 는 상식처럼 알아두어야할 개념 중 하나이다. 

크게 많이 사용되는 Proxy 용어의 의미는 Proxy 서버, Proxy Design Pattern 등 다양하지만, 본 포스팅에서는 프록시 서버에 대해 다룬다.


Proxy 란 대리 혹은 중계 Agent 로써의 의미를 지니며 프록시 서버란 대리자 역할을 하는 서버를 말한다.


즉, 웹브라우저에서 Request를 보냈을 때 내 IP가 아닌 Proxy 서버의 IP로 웹서버에 접근하여 요청과 응답을 처리한 후 Proxy 서버에서 나에게 응답을 해주게 된다.


이렇게 프록시 서버를 사용하는 목적은 3가지 정도가 있다.


목적에 따른 분류


(1) 익명성과 우회접근


 : 서비스형태로 제공하는 Proxy 가 주로 이 범주에 속하며, IP를 숨기는 것이 주 목적이다. 요청을 대신 수행해주는 프록시 서버를 통해 우회하여 서버에 접근이 가능하다. 

IP 를 숨긴 채 모든 사용자가 접근가능하도록 허용하는 Open Proxy 형태가 있다.



(2) 서버의 부하를 줄여주기 위한 Filter 이자 Cache


 : Proxy 를 도구로써 사용하는 가장 대표적인 예시이다. 프록시 서버가 서비스 서버에 작업하는 위치와 네트워크 구성에 따라서 Forward Proxy / Reverse Proxy 로 구분된다.


 - Forward Proxy : 일반적인 프록시 서버를 말하며, 요청하는 Client 와 Service Server 사이에 위치하여 중간에서 요청을 중계한다. 가령 서버에 요청이 들어왔을 때, 요청은 Proxy를 거쳐 서버에 전달되며 이 과정에서 별도 작업을 처리해서 Service Server로 전달하거나, Cache 로써의 역할을 한다.


 - Reverse Proxy : 마찬가지로 Client 의 요청이 실제 Service Server의 도메인으로 이루어지는 것이 아닌 프록시 서버로 이동한다. 

Forward Proxy 와는 다르게, Service Server 들이 대게 내부망으로 구성되며 프록시에서만 연결을 허용하게 만들어 서비스를 위한 보안 채널을 구축하는 역할을 한다. 

이런 경우 Client 가 Service Server 에 직접 접근이 불가능하므로 Reverse Proxy 에서 요청을 좀 더 적극적으로 중계하는 Load Balancing 의 역할을 수행하기도 한다.


 : 이렇게 서버 측에 위치한 Cache 를 위한 Proxy 외에도 클라이언트 네트워크 쪽에서 프록시와 캐싱을 함께 수행하는 서버가 따로 존재한다. (Squid와 같은 서버가 예이다.) 

 : 이 때 캐싱 시에는 HTTP 헤더에 Cache-control : no-cache 옵션이 주로 작용하며 주로 포털 사이트에서 해당 헤더를 사용하는 경우를 볼 수 있다.

(Cache-control 옵션에 대해 얘기하자면, no-cache로 지정할 경우 캐싱을 사용하지 않고 실 서버까지 도달한다. 

그렇기 때문에 사용하려면 max-age=3600, must-revalidate 와 같이 지정해야 한다.)



(3) 서버 접근 작업 자체를 담당하는 서버


 : 다소 특수한 케이스로 주로 모니터링 및 데이터 분석을 위해 요청 자체를 기록하고 다루는 형태의 서버 엔진이 있다. 보안, ACL(Access Control List), Log / Audit 등을 위해 사용된다.



웹서비스를 구현하는 데 있어서 보통 사용되는 프록시 서버의 형태는 (1)번과 (2)번으로 Reverse Cache 의 형태가 가장 보편적이라고 할 수 있다.




stdafx.h 란 자주 쓰이는 헤더들 여러 개를 한꺼번에 미리 컴파일 해놓아서 나중에 다시 컴파일하지 않고 그냥 다시 쓰겠다는 헤더이다

이렇게 미리 컴파일된(Precompiled) 파일이 .pch 파일이다

프로젝트의 크기가 커지고 헤더들의 크기가 커지거나 숫자가 많아지면 유용하게 써야할 필요가 있다


프로젝트 속성에서 Precompiled Header의 사용을 Enable 하게 해줘야한다

보통 Wizard로 프로젝트를 생성하는 경우 기본으로 stdafx.hInclude 되어 있는데, 여기서 stdio.hInclude 하면 중복이 되거나 헤더가 엉키는 현상이 발생해서 Unexpected File End 가 발생하게 된다


stdafx.h 를 사용할 때는 모든 cpp 파일이 이를 Include 해야 하며 가능한 깔끔하게 구조를 잡고 가는게 좋다.



'Programming Language > C&C++' 카테고리의 다른 글

[Old] C++Type Casting 정리  (0) 2018.09.25
RAII 의 개념 정리  (0) 2018.08.08


주의) 오래전 Effective C++을 바탕으로 보관한 자료이기 때문에 최신 C++ Trend 가 전혀 반영되어있지 않은 포스팅입니다.


 C++C에서의 Type Casting 보다 확장되고 안정성 있는 Type casting 기법 4가지를 제공한다.


(1) static_cast

 : 크게 implicit castexplicit cast로 나뉜다.



Expressionstatic_cast<type>(expression)으로 표현된다.

 

(2) dynamic_cast

 : 상속 관계를 가로지르거나 하향시킨 클래스(파생 클래스) 타입으로 캐스팅할 때 사용된다. 상속 계층 간에만 사용해야하며 가상 함수가 없는 타입에 적용시킬 수 없고 상수성 제거에도 적용할 수 없다.

dynamic_cast<type>(expression)


-> 일반적으로 사용하는 캐스트는 static_cast이다. 하지만 다형성을 이용하려는 경우에는 얘기가 다르다. 런타임에 다형성을 이용한 모호한 캐스팅이 이루어질 경우 static_cast는 문제가 됨에 반해, dynamic_cast는 실제 Instance를 조사하기 때문에 런타임 오류가 발생하지 않는다. 예를 들어 BC의 부모 클래스일때,



일 때는 다형성의 정의에 의하여 BC의 포인터를 가리킬 수 있으므로 문제가 안되지만,



의 경우에는 BC의 타입으로 변환될 경우에 문제가 생기게 된다

그런데 static_cast로는 타입체크를 하지 않기 때문에 변환되서 문제가 되는 값이 넘어가게 된다. 반면에 dynamic_cast로 변환시에는 NULL값으로 변환된다.

 

(3) reinterpret_cast

 : 연관성이 없는 포인터 타입을 변환하기 위해서 사용된다. 예를 들어


이 경우 위와 같이 static_cast로 변환을 시도하는 경우, 문법적으로 불가능하지만, reinterpret_cast를 이용하면 연관성 없는 두 포인터간 캐스팅이 가능하다

하지만 논리적으로 불안정하며 포인터에 대한 캐스팅만 수행이 가능하고 const 타입에 대한 캐스팅이 안된다.

 

(4) const_cast

 : 포인터 타입과 참조형에 대해서만 사용되는 캐스팅이며 동일 타입 내에서만 사용이 가능하다

그 외에는 is a 관계를 포함한 어떤 관계를 맺고 있더라도 불가능하다. 일반적으로 상수목적으로 지정된 객체 등에 대해서 변수목적으로 사용하고자 할 때 이용한다

또한 volitile 타입 한정자를 지닌 volatile 타입 객체를 참조형으로 변환하고자 할 때도 사용된다. Effective C++에서 이에 대해서 많이 다루고 있으니 참조하자.

 

'Programming Language > C&C++' 카테고리의 다른 글

Stdafx.h 란?  (0) 2018.09.25
RAII 의 개념 정리  (0) 2018.08.08

+ Recent posts