운영체제 역사(Operating System History)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
경성대학교 양희재 교수님 수업 영상을 듣고 정리하였습니다.


컴퓨터의 역사!

1. No operating System

처음 컴퓨터가 만들어진 때는 세계 2차대전 중 1940년대 말 즈음이다. 컴퓨터의 발전과 함꼐 하드웨어의 발전도 이루어졌고, 그에 따라 운영체제의 기술 또한 발전되었다. 제일 처음 발명된 컴퓨터의 크기는 너무 컸기 때문에 책상위에 올려둘 수도 없었고 아예 한 건물안에 컴퓨터 하나가 들어가있는 모습이었다.

그 건물에서 제일 큰 비중을 차지하는 것은 입력장치(카드리더)가 있는데, 이 카드리더에는 여러가지는 OCR에 적힌 내용을 읽어 처리기에 보내고 처리기에서 컴파일러 한 내용을 그대로 프린트(io)에 찍어보낸다.

이때의 컴퓨터는 일반인들은 사용 하지 못했고, 컴퓨터를 작동시키는 오퍼레이터라는 직업이 따로 있었다. 따라서 오퍼레이터(프로그래머)가 종이에 연필로 프로그램을 적어 전산실에 넘기면 전산실에서는 연필로 작성된 코드들을 OCR 카드에 구멍을 뚫어서 그 구멍을 통해 카드리더가 코드를 파악했다. 그럼 이 내용들이 처리기의 메모리에 적재되고 즉, 메모리가 프로세서에 올라가게되면 카드리더에 있던 파일은 삭제되고 이 메모리를 읽기 위한 컴파일러가 카드리더에 올라가 처리기로 옮겨지면서 처리기에는 메모리와 컴파일러가 올라가 있게 된다.

이 컴파일러는 이제 이 메모리를 번역하기 위해 기계어가 나오고 처리기는 기계어를 실행한다. 이때는 모니터가 없으니 그 결과는 프린터에 찍힌다.

그래서 처음의 컴퓨터에는 별도의 운영체제가 존재하지 않던 No operating system이었으며, 기술이 발전과 함께 컴퓨터 스스로 할 수 있는 운영체제가 만들어지기 시작했다.

2. Batch processing System

Batch: 꾸러미, 묶어서 프로세스를 처리를 한다 (일괄처리)

과거에 오퍼레이터가 했던 일련의 동작들을 이제는 메모리에 프로그램들을 넣어 컴파일 > 링크 > 로드하도록 하는, 즉 프로그램들을 메모리에 넣는 것 을 Batch processing system(일괄처리 시스템)이라고 한다.

이 메모리 안에 들어있는 작은 프로그램을 레지던트 모니터(resident monitor)라고 부른다. 메모리에 상주함으로써 일괄적인 일들을 한다고 해서 batch라는 단어를 붙였고 이를 최초의 운영체제로 본다. 그 후에 기술이 발전되어 메인 메모리 외에도 하드디스크(기억용량이 크고 속도도 빠름)도 만들어지고 그리고 이때의 메인메모리는 반도체 메모리가 아닌 진공관 메모리여서 이후 트랜지스터 등등이 생기면서 메모리가 굉장히 커지고, 프로세스 속도도 빨라지게 된다.

즉, 하드웨어 기술이 발전되며 os에도 변화 또한 굉장히 커졌다.

3. Multiprogramming System

os(운영체제)의 변화중에서도 가장 큰 변화인 멀티 프로그래밍(다중 프로그래밍)이다.

옛날에는 컴퓨터가 정말 비쌌고, 미국에도 많아야 5개가 안됐다.(우리나라에는 없었고) 그래서 사람들이 생각해보면 batch processing system도 좋았지만 단점도 존재했다.

  • 컴퓨터를 생각해보면 기본적으로 메모리에는 os와 유저 프로그램이 들어있다.
  • 다양한 유저 프로그램중에는 메모리에 하나만 올라갈 수 있었다.
    • 동시에 여러 프로그램이 메모리에 올라갈 수 없었다.

우리가 프로그램을 통해 어떤 연산을 할때에는 cpu를 사용하는데, 프린트를 통해 화면에 무언가를 입/출력할 때(io)에는 cpu를 사용하지 못한다. 즉 우리는 다양한 프로그램을 사용하고(cpu를 사용하고) 입/출력(io)를 하고싶은데 이를 동시에 진행하기가 어려운 것이다.

즉 시간경과에 따라서 cpu->io->cpu->io 이렇게 도는 것을 볼 수 있다.

더 나아가 batch processing system은 유저 프로그램이 하나 있었는데 처음 프로그램을 실행할때에는 cpu가 동작하지만, io가 실행할때에는 cpu는 io가 끝날때까지는 할일이 없다. 그래서 이때 cpu가 아무일도 안하고 놀게 되는데 이를 idle이라고 한다. (idle은 아무일도 안하고 빙빙 돌고있다는 뜻)

컴퓨터는 굉장히 비싼 자원이고 cpu의 연산속도는 무척 빠르지만 io의 속도는 느리고, 그렇다는 것은 io가 진행될때에는 cpu가 계속 놀고있게 되니 이를 해결할 방법을 마련한 것이 Multiprogramming system(다중 프로그래밍)이다.

메모리에 여러개의 프로그램을 돌리자!

cpu가 idle하지 않고 다른 프로그램(다른 유저 프로그램)으로 내려가게 된다.

그래서 원래 진행하고 있던 프로그램에서 io를 진행하고 있다고 하더라도 cpu는 계속해서 다른 프로그램으로 옮겨감으로써 일을 계속 하게될 수 있게된다. cpu는 되게 비싼 자원이기 때문에 이런식을 통해 메모리의 작업/프로그램을 수행하도록 한다. 어느 순간에도 cpu가 idle하지 않도록!

이 방식을 통해 idle 타임을 대폭 줄이고 cpu의 사용률이 올려버린다. 즉, 메인 메모리에 여러개의 프로그램을 올리는 것을 다중 프로그래밍 시스템이라고 한다.(프로그램이 여러개)

멀티 프로세싱 시스템을 채택하게 되면서 이제 우리는 단순하게 메모리에 프로그램을 여러개 올리는것만으로 끝나는게 아니라, 여러개의 생각해봐야 할 이슈가 생겼다.

  • CPU scheduling: 메인 메모리에 프로그램이 여러개 있으면 어떤 순서대로 cpu를 사용할 것인가?
    • 성능을 향상 시켜야 하니까, 성능이 더 좋은 방식으로!
  • 메모리 관리: 이제는 메모리의 유저프로그램들이 많아졌으니까, 유저 프로그램들을 각각 어디에 배치하는것이 좋을까?
    • 프로그램이 종료된다면 이 새로운 프로그램을 넣으려고 하면 비어있는 곳? 아니면 그 다음?
  • 보호: 다른 프로그램 영역까지 침범할 수 있으니 이를 막아햐 하잖아.

4. Time Sharing System

더 나아가, 60년대 후반 70년대로 오면서 모니터, 키보드가 생겨나게 되면서 컴퓨터와 사용자간의 interactive가 가능해졌다.

옛날에는 컴퓨터 한대의 값이 너무 비싸서 한사람이 쓰지 못하고, 하나의 컴퓨터에 단말기(terminal)를 연결해 각각의 컴퓨터와 키보드가 연결해 사용했다. 근데 이때의 컴퓨터 모양은 지금과 비슷해보이지만 조금 다르게 생겼다. 지금은 본체가 있어서 그 본체에 cpu와 메모리가 있지만 과거에는 그냥 단순히 모니터와 키보드로만 이루어진 입출력 장치에 불과했다.

그래서 옛날에는 하나의 컴퓨터에 수많은 단말기를 달아서 사용했다.

컴퓨터를 여러명이 사용하려다 보니, 처음 유저프로그램1을 실행을 하면 이 사이 유저2,3은 아무것도 실행하지 못한다.(cpu가 하나이기 때문에..) 하나의 컴퓨터를 여러명이 동시에 사용하려면 위에서 이야기했던 multiprocessor system을 사용하기는 힘들다.

이를 해결하기 위해서는 프로그램이 3개라고 한다면 1분에 1/100초 마다 cpu가 스위칭을 해줘야한다.

즉, io를 만날때마다 스위칭해주는게 아니라 아주 짧은 시간동안 계속해서 움직이게 한다. 그러면 유저가 3명이고 1/100초마다 스위칭이 된다면 한 사람마다 1초에 총 33번의 cpu가 할당되는 기회를 얻는다. 이렇게 되면 cpu는 워낙 빠르니까 유저는 혼자 컴퓨터를 사용하는 것처럼 느껴지게 된다.

이를 TSS(Time Sharing System)시공유 시스템이라고 한다. 일정 시간이 지나면 강제절환(Switching)하고 대화형 시스템이 가능해진다.(명령내리고 응답받고..)

  • 사용자가 여러명인데 다른 사용자에게 메시지를 보낼 수도 있음 (ex.카카오톡..)
  • 하나의 컴퓨터를 여러명이 쓰다보니까 서로 데이터를 주고받는것이 가능해짐
  • 프로세스간 통신이 가능해짐
  • 유저 1,2,3이 거의 동시에 실행되다 보니까 누가 앞서도 뒤서야하는지 알아봐야함(동기의 개념이 대두됨)
동기란?
싱크로나이즈 > 여러명이 짝을 이뤄 움직이는것
즉, 프로그램이 여러개 동시에 있다보니 누가 순서를 앞서도 뒤서야하는지를 해결해야하고, 이를 동기라고 한다.

늘어나는 유저상황에서 적은 메모리로는 어떻게 이를 유지할 수 있을까?

  • 새로운 기술이 나타남: 하드디스크가 보편화됨
    • 하드디스크의 일부를 메인 메모리인양 사용
    • 사실은 메인메모리가 아닌데, 하드디스크가 메인메모리처럼 보이게 함
    • 그래서 cpu가 보기에는 메인메모리가 크게 보이는것 > 가상메모리처럼..

운영체제는 성능향상을 시킨다고 했는데 바로 위에 저런 기능들을 통해서 성능향상을 시킬 수 있게 된것이다.

그래서 결론적으로 지금 우리가 사용하는 대부분의 운영체제는 TSS이다! 그 이후로는 os의 특별한 발전은 없었는데, 왜냐하면 거의 완성이 되었기 때문이다.

단일 cpu를 사용한 가장 최신의 운영체제가 되었고 unix, linux도 마찬가지고 mac, 윈도우 모든 TSS를 사용하고 있다.

os 기술의 천이

가장 강력한 컴퓨터는 무엇인가?

  • supercomputer: 가장 최강의 컴퓨터, 메모리용량도 크고 cpu도 빠르고 보조기억장치도 엄청나다.
  • mainframe: 한 컴퓨터에 수백대의 단말기를 달아 사용(수백명의 사람들이 동시에 사용하는 것)
  • minicomputer: 단말기가 수십대
  • micro: 작으면 한명정도..

이건 옛날 구별이고 이제는

  • supercomputer
  • server
  • work station
  • PC
  • handheld: 손에 들고다니는 컴퓨터 / 노트북, 태플릿, 스마트폰..
  • embedded: 어디에 파묻혀있다. 즉, 내장되어져있다.
    • 컴퓨터가 어디에 포함되어있다. 자동차안의 컴퓨터(엔진제어..), 전기밥솥 안의 cpu, 냉장고, 세탁기..
    • 우리 눈에는 안보이지만, 세탁기도 지능화되어야하니까 컴퓨터가 들어잇다.

이 모든 컴퓨터에는 모두 운영체제가 들어가 있다. 운영체제가 없으면 우리가 그것을 사용할 수가 없다. 그래서 아무리 간단해 보이는 컴퓨터라고 하더라도 모두 운영체제가 들어있다.

운영체제 서론(Operating System)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
경성대학교 양희재 교수님 수업 영상을 듣고 정리하였습니다.


Operating System 운영체제

컴퓨터를 제어하고 관리해주는 프로그램.
os: windowXP, linux, macOSX…

만약 이러한 os가 없는 컴퓨터는 어떤 상태일까?

  • 일반적으로 컴퓨터는 processor(처리기)memory(메인 메모리)로 구성이 되어있다.
  • 어떤 프로그램을 실행하기 전에 메모리에 명령들을 기록해놓는다.
    • (이때 명령들을 instuction이라고하고, 이 instuction의 집합을 프로그램이라고 한다.)
  • 이 프로그램들을 미리 메모리에 내장해두고 실행하기에 이런 구조의 컴퓨터를 프로그램 내장형 컴퓨터 라고 한다.(Stored program concept)

그런데 이러한 메모리에 아무런 운영체제가 깔려있지 않는다면?

  • 컴퓨터의 메모리에는 자기 멋대로의 임의의 값들이 들어있다.
  • 그래서 명령을 들고와서 실행을 하려해도 멋대로 명령이 들어오기에 할수 있는 일이 없다.

컴퓨터라고 하는 것은 전원을 키면 어떤 일이 일어나는가?

  • 휘발성 메모리: 전기를 끄면 그 내용이 다 사라짐 (램과 같음)
  • 운영체제가 없는 상태에서 전원을 껐다 키면 자기멋대로의 값이 있기 때문에 실행이 들어와도 자기 멋대로의 명령이 실행됨
  • 운영체제 없는 컴퓨터는 야생마 같다.

즉, 우리가 사용을 못한다.

운영체제가 하는일?!

  • 프로그램을 실행하기 위해 하드디스크 안에 들어있는 실행파일들을 메모리에 올려준다.
  • 하나의 프로세서(cpu)만으로도 여러개의 프로그램을 실행할 수 있도록 한다.(메모리에 동시에 올라가 실행할 수 있도록)
  • 컴퓨터의 파일을 프린트에 인쇄할 수 있도록 해준다.
  • 문서를 편집하고 하드디스크에 저장하는 것또한 가능하게 해준다. 등등등

운영체제가 있기 때문에 이 컴퓨터를 온전히 쓸수 있는것이고, 그게 없으면 그 컴퓨터는 그냥 폭주하는 컴퓨터, 제어가 불가능한 컴퓨터가 되는것.

즉, 컴퓨터의 하드웨어(프로세서, 프린트, 메모리, 하드디스크, 키보드, 마우스, 모니터, 네트워크, 스피커, 마이크 등)를 잘 관리해서

  1. Performance: 성능 향상(좋은 os를 설치하면 내 컴퓨터의 성능도 좋아진다.)
  2. Convenience: 사용자 편의 제공 (os가 있기에 우리가 원하는대로 사용이 가능한 것)

즉, 운영체제는 컴퓨터를 제어하고 관리해주는 프로그램 (Control progran for computer) 이다.

부팅(Booting)

막간, 컴퓨터 구조 지식)

  1. 컴퓨터 구조에 따르면 컴퓨터라는 것은 프로세서와 메인 메모리로 구성되어있다.
  2. 그 외에도 보통의 컴퓨터에는 하드디스크라는 보조기억장치를 가지고 있다.
  3. 메인메모리는 램과 롬으로 구성되어 있다.
  • 램(RAM): 메모리의 대부분을 차지하고 있는것 (우리 컴퓨터 메모리가 4GB라고 한다면 그것은 램을 의미하는 것) MB, GB -> 10의 9승
  • 롬(ROM): 극히 일부분이고 사이즈가 별로 없어도 되는데 KB 정도임 -> 10의 3승

우리가 전원을 껏다키면 램의 내용은 휘발성메모리이기에 다 날아가 버린다. 그렇기 때문에 전원을 껏다키면 메모리 안의 내용은 유지되지 않고 다 날아가버린다. 그런데 이 전원에 관계없이 계속해서 남아있는게 있는데 그게 하드디스크이다. 이 하드디스크와 메인메모리의 롬은 전원과 관계 없이 내용이 그대로 남아있다.

우리가 잘 아는 롬은 휴대폰 안에 들어있는 플래쉬메모리 또한 전원과 관계없이 내용이 남아있다.

컴퓨터의 전원을 키는 순간 컴퓨터에서 일어나는 현상들

  • 파워을 처음에 딱 껏다가 키면 프로세서는 롬 부분의 코드를 읽어온다. 즉, 롬 안의 instuction을 읽어와서 실행한다.
  • 이 프로그램에 제일 먼저 있는 내용은 POST(Power on self-test) 프로그램이다.
    • 전기를 키면은 컴퓨터가 모든 환경설정이 제대로 되어있는가를 확인
    • 키보드 연결되어잇는가, 메인 메모리는 얼마나? 프린트는? 이런것들을 테스트 > 셀프테스트
  • POST가 먼저 실행되고 내 컴퓨터 안에는 메모리가 얼마고, 하드디스크 용량은 얼마고를 확인하고
  • 그 다음으로는 boot load라는 것이 실행된다.
  • 이 부트로드를 통해서 하드디스크 안에 들어있던 os를 메인메모리로 가져오게 된다.

Boot Load

위에서 먼저 언급했던 것처럼 처음 전기를 키면 롬에 있는 코드가 실행되어 POST가 실행되고 boot load가 실행된다.

일반적으로 운영체제는 하드디스크 안에 설치가 된다.

하드디스크 안의 운영체제가 있고 boot load는 하드디스크를 뒤져서 운영체제를 메인메모리로 가져오는 역할을 한다.

부트로드라고 하는 작은프로그램이 하는 일은 하드디스크의 몇번째 어디에 운영체제가 있다는것을 알아서 메인메모리의 램 영역으로 가져오는 역할을 한다. 그래서 하드디스크에 있던 운영체제가 메인메모리로 올라오게 된다. 이렇게 하드디스크에 있던 운영체제가 메인메모리로 올라오는것을 부팅(booting)이라고 한다. 메인메모리로 운영체제를 들고오게되면 이제 더이상 롬의 프로그램은 실행될 것이 없다. 이렇게 롬의 역할은 끝나게 되는것이고 롬은 파워를 키는 그 순간에만 필요하고 그 이후에는 필요하지가 않다.

일단 운영체제가 메인메모리로 올라오게 되면, 우리가 친숙한 모니터에 익숙한 바탕화면이 나타나게 된다. 그러면 컴퓨터 모니터에는 바탕화면의 아이콘들이 모여잇는 초기화면이 나타나고 이떄, 바탕화면이 나타난다는 것은 운영체제가 메모리에 상주(residence)해서 이제 무슨 명령이든 받을 준비가 다 되어있으며 일을 시켜도 된다는 것을 의미한다. = 준비되어 제어가 된 상태 (사용자가 마음대로 제어할 수 있는 단계가 된 것.)

즉, 모든 제어를 운영체제가 해주기때문에 누구든 쉽게 사용이 가능하게 된다.

그리고 운영체제는 컴퓨터의 성능도 높여주는데, 이 운영체제가 사라지는 순간은 컴퓨터의 전기를 끄는순간 메모리에서 사라진다. 다른 일반 사용자 프로그램들은 메모리에 올라왔다가 사라지기를 반복한다. 만약 운영체제가 돌아가고 있는 상황에서 우리가 hwp를 사용한다고 하면 그게 메인메모리에 올라오게되고 해당 프로그램을 편집하고 종료하면 hwp 프로그램은 메모리에서 사라진다. 이렇게 다양한 프로그램들은 메모리에 올라왔다가 사라지고 그렇게 돌아가기를 반복한다.

그러나 os는 항상 그 자리에 잇음 = 메모리의 레지던트(상주한다)

즉, 운영체제는 컴퓨터가 꺼질때까지 메인 메모리에 상주한다.

따라서 운영체제라는 것은 결국…

  • 컴퓨터를 관리하는 프로그램 (사용자가 원하는 대로 제어 가능하도록 만들어주는 것)
  • 무엇을 관리? 여러 하드웨어 장치들을 관리

그런 운영체제는 크게 두가지로 나뉜다 - Kernel과 Shell(Command Interpreter)

컴퓨터 제일 내부에는 하드웨어가 있고 하드웨어를 제어하고 관리해주는 os가 하드웨어를 둘러싸고 있다.

  • 커널(Kernel): 핵심&핵, 하드웨어를 제어하고 관리하는 os의 부분, os에서 가장 중요한 부분
    • 메모리, 디스트, cpu등을 실질적으로 관리하는 프로그램
  • 명령해석기(command interpreter, shell): os의 껍질
    • 사용자가 어떤 명령을 내리면 그 명령을 해석해 결과를 화면에 보여주는 역할

컴퓨터에 윈도우를 깔면 여러개의 아이콘들이 모여있는데 이 아이콘들을 실행하려면 마우스를 들고가서 더블클릭을 해야한다. 이렇게 우리가 마우스를 들고가서 프로그램을 실행하려고 하는 행위, 내가 어떤 프로그램을 실행하기 위한 명령을 내릴 수 있도록 만들어 준것을 os의 command interpreter라고 한다. 일반적으로 윈도우는 그래픽 환경에서 명령을 내리고 리눅스는 텍스트를 기반으로 명령을 내리린다. 그래서 우리가 쉘에 명령을 내리면 그 쉘이 하드디스크를 뒤져서 해당 명령에 대한 결과를 보여준다.

리눅스 명령어 약간의 팁!

- ls(list): 현재 디렉토리에 존재하는 파일의 이름을 알고 싶을때
- who: 리눅스는 서버운영체제이기 때문에 한번에 여러명이 사용한다 ,누가 이 컴퓨터를 사용하는지 알아볼때
- df(disk free): 이컴퓨터의 하드디스크 용량은 얼마고 얼마를 사용햇는지 확인

즉, shell과 interpreter는 os의 바깥부분에 위치해서 사용자로부터 명령을 받고, 그 명령을 인터프리터를 통해 해석/번역하여 해당 명령을 실행하는 것을 의미한다.

그래서 커널은 실질적으로 우리 눈에는 보이지 않고 (관리하는 애니까) 우리는 주로 껍질을 보게 된다. 즉, 우리가 일반적으로 윈도우를 잘 안다고 하는것은 그 윈도우를 사용하는 법을 잘 안다는 것이고 그 사용법을 잘 안다는 의미는 이 껍질을 잘 안다는 뜻이다.

우리가 공부하는 운영체제는 껍질이 아닌 커널!

운영체제의 위치

컴퓨터는 하드웨어 > 운영체제(커널+쉘) > 애플리케이션 이렇게 구성되어있다.

이때 애플리케이션은 응용 프로그램으로(App, application)을 의미하고 이 앱들은 os위에서 실행되며 따라서 만약 os가 달라지면 이 프로그램(앱)들은 사용이 불가능하다. 하드웨어가 같음에도 불구하고 사용이 불가능한 이유는 os가 다르기 때문이다. 애플리케이션은 하드웨어 위에서 도는게 아니라 os 위에서 돌고있기에 한 프로그램을 돌게 하기 위해서는 반드시 os가 반드시 필요하다.

즉, 컴퓨터의 제일 밑에는 하드웨어가 있고, 이런 하드웨어들이 컴퓨터의 하드웨어를 이루고 있고 이 하드웨어들을 제어/통제해주는 프로그램이 운영체제이다. 운영체제 위에는 어플리케이션 프로그램이 있고 프로그램들은 하드웨어 자원을 사용하고 있지만, 하드웨어 자원을 직접적으로 사용하는게 아니라 os가 중간에 관리해주는대로 하드웨어 자원을 사용하고 있다.

  • 하드웨어 예: cpu, 메모리, 프린터, 모니터, 키보드, 마우스, 램카드, 스피커, 마이크 등등
  • 어플리케이션(프로그램) 예: ms word, hwp, 게임, 데이터베이스, 인터넷 익스플로어, mp3, 비디오 플레이어 등등

운영체제 vs 정부

운영체제는 정부와 비슷하다. 즉, os도 여러가지 부서가 있다.

  • process management: cpu 즉 프로세를 관리
  • memory management: 메인 메모리를 관리
  • io management: 입출력
  • file management: 하드 디스크의 파일들 관리
  • network management: 네트워크 관리
  • security/protection management: 컴퓨터의 보안을 관리

하드웨어를 자원이라고 하고 이 자원들을 관리하는 것이 os!
os의 다른 이름은 resource manage라고 한다.
하드웨어 자원을 애플리케이션에 할당해주는 것을 os가 하는 일이다.

git merge conflict - fast-forward와 3-way-merge

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


문제상황

지금까지 git을 통한 협업 시 merge conflict(병합충돌)은 같은 파일의 같은 라인을 수정하면 무조건 일어나는 것이라고 생각했다. 그런데 병합 충돌이 일어나지 않는 경우를 발견했다.

merge를 하는 방식에는 fast-forward3-way-merge 두 가지가 있다.

fast-forward

우선 fast-forward방식은 우선 아래의 그림에서부터 출발해본다.

여기서 C는 커밋(Commit)을 의미한다. 작업을 진행하며 위와같은 커밋이 진행되었고 현재 C2에 master가 존재하고 있다.

이때 이슈가 생겨 iss53이라는 브랜치를 생성하면 위와 같은 그림처럼 형성이 된다. 당연하게 iss53 브랜치에서 하는 행위 그 어떠한 것도 master에는 영향을 주지 않는다.

iss53 브랜치에서 이슈를 다 해결하고 커밋을 날리면 위와 같이 커밋 히스토리가 있을 것이다. 즉, master는 C2에 있지만 iss53은 C3를 가리키고 있다.

중요한 포인트가 뭐냐하면, C3의 커밋에는 C2까지의 내용이 모두 담겨있다는 사실이다. 이 상태에서 master로 merge를 하는 것은 단순히 master의 포인터를 최신 커밋을 가리키고 있는 C3로 옮기는 것을 의미한다.

현 브랜치가 iss53 브랜치 일 것이기에,

git ckeckout master
Switched to branch "iss53"

git merge iss53

Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

이렇게 merge 메시지에서 fast-forward가 보일 것이다.

C3 커밋이 C2커밋에 기반한 브랜치이기 때문에 브랜치 포인터는 merge 과정없이 그저 최신 커밋으로 이동을 한다. 이런 방식이 fast-forward 방식이다.

  • A와 B 브랜치가 있다.
  • A->B를 머지하려고 한다.
  • B가 A 이후의 커밋을 가리키고 있다. (B의 조상커밋이 A이다.)
  • A는 단순히 B와 동일한 커밋을 가리키도록 이동한다.

즉, 단순히 포인터를 최신 커밋으로 옮기는 것을 fast-forward 방식이라고 한다.

3-way-merge

이제 git에서 협업시 가장 많이 이루어지는 3-way-merge를 살펴보겠다.

다시 master 브랜치에서 이슈가 발생해 iss53 브랜치를 생성해 이슈를 해결하고 커밋을 날린 상황으로 돌아가 보겠다.

그런데 이때 master 브랜치에서 급하게 해결해야 될 핫 이슈가 발생했다.

그래서 master에서 hotfix 브랜치를 생성해서 급히 생긴 이슈를 해결하고 commit을 날린 후 master에서 merge를 했다.

즉, 이 상황은 아래와 같다.(iss53 시점에서부터 시작하겠다.)

git ckeckout master # iss53브랜치에서 master로 이동

git branch hotfix # hotfix브랜치 생성
git checkout hotfix # hotfix 브랜치로 이동

# 이슈 해결 뒤

git add -A
git commit -m 'hotfix 해결'

git ckeckout master # master 브랜치로 이동

git merge hotfix

그러면 이제 위 그림과 같이 master는 C4에 있게 되고 현재 포인터가 C4를 가리키게 된다.

이제 hotfix를 해결했으니 해당 브랜치는 삭제한다.

git branch -d hotfix

이제 다시 우리가 개발하던 iss53으로 돌아가 작업을 완료하고 커밋을 날려 C5라는 커밋 히스토리를 남겨보자.

이때 fast-forward와 다른 점이 보일 것이다.

현재 가리키는 커밋(C4-master)가 merge할 브랜치(C5-iss53)의 조상(C3)가 아니기 때문에 fast-forward 로 머지를 하지 않는다.

git checkout master

git merge iss53

Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

즉, 3-way-merge는 각 브랜치가 가리키는 커밋 2개(C4, C5)와 공통의 조상 1개(C2)를 사용하는 것을 의미한다.

3-way-merge의 최종결과는 위와 같다.

3-way-merge의 결과를 별도의 커밋으로 만들고 해당 브랜치가 그 커밋을 가리키도록 이동시킨다. 그 커밋은 C6이고 해당 커밋의 부모는 여러개가 되어있는 것을 볼 수 있다.

이때, 3-way-merge에서 merge-conflict가 발생할 수 있는 것이다. merge하는 두 브랜치에서 같은 파일의 같은 부분을 동시에 수정하게 되면 git은 해당 부분을 merge를 하지 못한다.

일반적으로 git은 자동적으로 merge를 하지 못하기 때문에 새로운 커밋또한 생성되지 않는다. 변경사항의 충돌은 개발자가 해결해주지 않는 한 merge 과정을 진행할 수도 없다.

그동안 병합충돌은 어느 방식에서든 같은 파일의 같은 곳을 수정하면 무조건적으로 일어나는 것이라고 생각했었다. 근데 해당 충돌이 일어나는 방식은 3-way-merge에서만 발생하는 것이란걸 알게되었다..

사실 지금도 매우 놀랍고 이해가 안가는 부분도 있지만.. 일단 그렇다고 한다. 만약 제가 이해한 부분이 틀렸다면 언제든지 댓글을 남겨주세요.

CSRF 공격이란?

|

개인적인 연습 내용을 정리한 글입니다.
잘못된 내용이 있다면 편하게 댓글 남겨주세요!


CSRF

CSRF(Cross Site Request Forgery) 공격이란 웹 어플리케이션 취약점 중 하나로 인터넷 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만든는 공격이다.

이러한 CSRF를 통해 해커는 희생자의 권한을 도용해 중요 기능을 실행하는 것이 가능핟. 그치만 CSRF는 해커가 사용자의 컴퓨터를 감염시키거나 서버를 해킹해서 이뤄지는 공격은 아니다. 이러한 CSRF 공격이 이루어지려면 다음 조건이 만족되어야 한다.

  • 위조 요청을 전송하는 서비스에 희생자가 로그인한 상태
  • 희생자가 해커가 만든 피싱 사이트에 접속

이 두 조건을 모두 충족시키기는 어려워보이지만, 사실 그렇지도 않다. 예로들어 페이스북, 로그인과 같은 사이트에는 우리가 보통 자동 로그인을 해놓는 경우가 많다. 이렇게 자동 로그인이 되어있는 상태에서 해커가 만든 피싱사이트(메인, 음란 사이트 등)를 통해 접속을 하기만 하면 공격이 이루어지는 것이다. 또 사용자가 해커가 만든 피싱 사이트를 접속하지 않더라도 해커가 XSS 공격을 성공한 정상 사이트를 통해 CSRF 공격이 수행될 수도 있다.

CSRF 공격 방어

  • Referrer 검증
  • Security Token 사용(CSRF_token)

일반적으로 CSRF 공격 방어는 조회성 (HTTP GET Method) 데이터에는 방어 대상에 두지않고, 쓰기/변경이 가능한 POST, PATCH, DELETE Method에만 적용하면 된다. 물론 정말 중요한 데이터를 조회하거나 GET을 통해 쓰기/변경 등의 동작을 한다면 Get Method에도 방어를 해야할 수도 있다.

Referrer 검증

Back-end 단에서 request의 referrer을 확인하여 domain 이 일치하는 지 검증하는 방법이다.

일반적으로 referrer검증만으로 대부분의 CSRF 공격을 방어할 수 있다. 하지만 같은 도메인 내의 페이지에 XSS 취약점이 있는 경우는 CSRF 공격에 취약해질 수 있다. domain 단위 검증에서 좀 더 세밀하게 페이지 단위까지 일치하는 지 검증을 하면 도메인 내의 타 페이지에서의 XSS 취약점에 의한 CSRF 공격을 방어할 수 있다.

CSRF 토큰

Referrer 검증이 불가한 환경이라면, Security Token을 활용할 수 있다. 우선 사용자의 세션에 임의의 난수값을 저장하고 사용자의 요청마다 해당 난수 값을 포함시켜 전송한다. 이후 Back-end 단에서 요청을 받을 때마다 세션에 저장된 토큰값과 요청 파라미터에 전달되는 토큰값이 일치하는 지 검증한다. 이 방법 또한 같은 도메인 내에 XSS 취약점이 있다면 CSRF 공격에 취약해 진다.


<form>
    {% csrf_token %}
    <input type="text" name="text"/>
    <input type="submit" value="확인"/>
</form>

Django 에서는 자체적인 템플릿을 통해 {% csrf_token %}이라고 form에 넣는 것만으로도 토큰을 주고받을 수 있도록 쉽게 사용이 가능하다.

클라이언트에서 해당 페이지를 접속하게 되면 Django에서 자동으로 csrf 토큰을 클라이언트로 보내어 cookie에 저장하고, POST로 전송할 때 cookie의 csrf 토큰이 함께 전송되어 인증하는 방식이다.


XSS 공격이란?

XSS(Cross-site Scripting)는 웹 상에서 가장 기초적인 취약점 공격방법의 일종으로, 악의적인 사용자(권한이 없는 사용)가 공격하려는 사이트에 스크립트를 넣는 기법을 말한다. 공격에 성공하면 사이트에 접속한 사용자는 삽욉된 코드를 실행하게 되며, 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰 등의 민감한 정보를 탈취한다. (대부분 자바스크립트를 사용하여 공격하는 경우가 많다.)

공격 방법이 단순하고 가장 기초적이지만, 많은 웹사이트들이 XSS에 대한 방버조치를 해두지 않아 공격을 받는 경우가 많다. 여러 사용자가 접근 가능한 게시판 등에 코드를 삽입하는 경우도 많으며, 경우에 따라서는 메일과 같은 매체를 통해서도 전파가 된다.

XSS 공격은 주로 CSRF 공격을 하기 위해 사용되기 때문에 혼동되기가 쉬운데, CSRF는 특정한 행동을 시키는 것이고 XSS는 자바스크립트를 실행시키는 것으로 이해하면 된다.

git flow 사용해보기

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


git flow install

  • 홈페이지: git flow install
  • macOS: brew install git-flow-avh
  • linux: apt-get install git-flow

Git-flow 구성 살펴보기

git-flow에는 5가지 종류의 브랜치가 존재한다.
항상 유지되는 메인브랜치(master, develop)과 일정 기간동안만 유지되는 보조브랜치(feature, release, hotfix)

master

master 브랜치에 merge된 내역은 새로운 버전이 갱신되었다는 것을 의미한다. 즉, master 브랜치에 변경된 내역이 생기면 최종 버전인 Tag를 통해 Production에 배포된다.

develop

hotfix를 제외한 모든 변경내역이 출발하는 지점이다. develop브랜치의 코드가 안정화되고 배포할 준비가 되면 master를 통해 배포 버전의 태그를 단다.

feature

feature 브랜치는 배포하려고 하는 기능을 개발하는 브랜치다. 기능을 개발하기 시작할 때는 언제 배포할 수 있을지 알수 없다. 기능을 다 완성할 때까지 유지하고 있다가 다 완성되면 develop 브랜치로 병합한다.

  • 브랜치가 생성되는 대상: develop
  • merge 대상: develop

release

release 브랜치는 실제 배포할 상태가 된 경우에 생성하는 브랜치이다.

  • 브랜치가 생성되는 대상: develop
  • merge 대상: develop, master

hotfix

미리 계획되지 않은 브랜치다. 기본적인 동작방식은 release와 비슷하다. 배포 이후에 생긴 치명적인 버그는 즉시 해결해야하기 때문에 문제가 생기면 master 브랜치에 만들어둔 태그 tag로 부터 긴급 수정을 위한 브랜치를 생성한다.

  • 브랜치가 생성되는 대상: master
  • merge 대상: develop, master

즉, 처음에는 master와 develop 브랜치만 존재한다. 이때 develop 또한 master에서부터 시작된 브랜치이다.

새로운 기능에 대한 추가 작업이 있는 경우 develop에서 feature브랜치를 생성하고 해당 feature브랜치에서 새로운 기능을 개발한다. 즉, feature 브랜치는 항상 develop브랜치에서부터 시작하게 된다. 기능 추가 작업이 완료되었다면 feature브랜치는 develop 브랜치로 merge를 하게된다.

develop 브랜치에 feature 브랜치에서 만든 기능들이 merge 되었다면 QA를 하기 위해 develop브랜치에서부터 release 브랜치를 생성한다. QA를 진행하면서 발생한 버그들은 모두 release 브랜치에서 수정이 된다. QA를 무사히 통과했다면 release 브랜치를 master와 develop 브랜치에 merge를 한다.

마지막으로 출시된 master 브랜치에서 버전 태그를 추가하면 최종적으로 우리가 개발하고자했던 모든 기능들은 master 브랜치에 포함됨으로써 해당 기능을 출시할 수 있게 된다.

git flow 흐름 살펴보기

git flow

이미지원본: 우아한형제들 기술블로그

  • Upstream Remote Repository: 개발자들이 공유하는 저장소, 최신 코드가 저장되어 있는 원격저장소
  • Origin Remote Repository: Upstream Repository를 Fork한 원격 개인 저장소
  • Local Repository: 내 컴퓨터에 저장되어있는 개인 저장소

git flow 간단하게 시작해보기

  • Local Repository에서 작업을 완료한 후 작업 브랜치를 Origin Repository에 push
  • Github에서 Origin Repositorydp push한 브랜치를 Upstream Repository로 merge하는 pull request 생성
  • 코드리뷰를 거친 뒤 merge
  • 다시 새로운 작업을 할때 Local Repositorydptj Upstream Repository를 pull
1. Upstream Repository를 나의 Origin Remote Repository에 Fork
2. 해당 git url을 clone

git flow init

# 기본 설정이 develop에 되어있을 것
git flow feature start [생성할 branch name]
git merge develop
git flow feature finish [삭제할 branch name]

# release
git flow release start [생성할 release name]

# release를 master, develop에 merge
# tag로 master의 버전 확인
git flow release finish [완료할 release name]


git pull origin develop #이 상황 무한 반복

feature 브랜치에서의 참고사항

  • feature 브랜치에서 작업을 하는 동안은 develop 브랜치의 변경사항을 자주 동기화해준다.
  • 반대로 feature 브랜치의 변경사항은 develop 브랜치로 merge하는 경우는 기능 구현이 끝났을때, 딱 한번이다.
  • 작업을 완료한 feature브랜치는 삭제해도 괜찮다.

release 브랜치에서의 참고사항

  • release의 수정사항들은 develop으로 자주 동기화해준다.
  • 하지만 release 브랜치 생성 후의 develop 브랜치의 수정사항은 동기화 하지 않는다.
    • 해당 develop 브랜치의 변경사항은 다음 배포 버전에 대한 것이기 때문에 다음 release 생성까지 merge하지 않는다.