REST란?

REST(Representational State Transfer)는 분산 시스템을 설계하기 위한 소프트웨어 아키텍처 스타일로, 특히 HTTP 프로토콜을 기반으로 한 웹 서비스 설계에서 주로 사용됩니다. REST는 클라이언트와 서버 간 통신에서 리소스의 상태와 표현(Representation)을 전송한다는 개념에서 이름이 유래되었습니다.

 

REST의 등장

REST는 미국의 컴퓨터 과학자인 로이 필딩이 2000년 박사 논문에서 처음으로 제안되었습니다.  웹의 확장성과 상호운용성을 극대화하기 위해 정의된 아키텍처 스타일입니다.

하나의 브라우저만 지원하면 되었던 이전과는 달리 여러 브라우저, 멀티 플랫폼, 멀티 디바이스 시대가 되며 플랫폼들에 범용적으로 사용될 수 있는 서버 디자인이 필요하게 되었고, 이를 해결할 수 있는 아키텍처로 REST가 사용되고 있는것입니다.

 

어떻게?

REST api는 Client side의 플랫폼에 제약을 두지 않아야합니다. 그래서 Server side에선 Client side를 전혀 고려하지 않고 메시지 기반, XML, JSON과 같이 Client에서 객체로 치환가능한 형태의 데이터 통신을 지향하면서 Server와 Client의 역할을 분리하게 됩니다.

 

REST의 구성

  • 자원(Resource) - URI
  • 행위(Verb) - Http Method
  • 표현(Representations)

 

1. 자원 (Resource) URI

모든 자원엔 고유한 ID가 존재하고, 이 자원은 Server에 존재합니다.

이 ID는 /product/3과 같은 HTTP URI의 형태로 구분합니다.

 

2. 행위 (Verb) - Http Method

Http프로토콜의 Method를 사용합니다.

Http Method는 POST, GET, PUT, DELETE가 있습니다.

 

3. 표현 (Representation of Resource)

Client가 자원의 상태(정보)에 대한 조작을 요청하면 Server는 이에 적절한 응답(Representation)을 보냅니다.

REST에서 하나의 자원은 JSON,XML,TEXT,RSS등 여러 형태의 응답을 받을 수 있습니다.

JSON혹은 XML을 통해 주고받는것이 일반적입니다.

 

REST의 제약조건

RESTful한 설계를 위해 아래와 같은 6가지 조건을 지켜야 합니다.

 

1) Client-Server(클라이언트-서버 구조) : 클라이언트와 서버를 명확히 분리하여 각자의 역할에 집중할 수 있도록 한다.

2) Stateless(상태 비저장성) : 서버는 클라이언트의 상태 정보를 저장하지 않는다. 각 요청은 독립적으로 처리되어야하며, 필요한 모든 정보는 요청에 포합되어야 한다.

3) Cacheable(캐시 처리 가능) : 서버 응답이 캐시될 수 있어야하며, 클라이언트는 이를 활용하여 네트워크 트래픽과 서버부하를 줄일 수 있다.

4) Code on demand(Optional) : 필요에 따라 서버가 클라이언트에 코드를 전송하여 실행할 수 있다. 예: Javascript, 플러그인 등

5) Uniform interface(인터페이스 일관성) : 일관된 인터페이스를 이용하여 모든 플랫폼에서 상호작용이 가능하도록한다. 특정 언어나 기술에 종속되지 않는다.

6) Layered System(계층화 시스템) : 클라이언트와 서버 간에 여러 계층을 둘 수 있으며, 각 계층은 독립적으로 동작한다.(예 :프록시 서버, 암호화 계층등)

 

RESTful API란?

Restful API는 REST의 설계 규칙을 잘 지켜서 설계된 API를 말합니다. 즉, REST API를 제공하는 서비스를 Restful 하다고 할 수 있습니다.

 

RESTful의 목적

이해하기 쉽고 사용하기 쉬운 REST API를 만드는 것, 일관적인 컨벤션을 통한 API의 이해도 및 호환성을 높이는 것이 주 목적입니다.

 

Reference

더보기

 

'Dev > Web' 카테고리의 다른 글

MVC(Model-View-Controller) 디자인 패턴  (0) 2024.07.06

이번주차 미션에서는 MVC패턴과 객체지향을 적용시키는 것을 최우선 목표로 잡고 진행하였다. 두가지를 이렇게 신경쓰면서 개발을 진행한것은 처음이었기 때문에 많은 어려움이 있었다.

 

어려웠던점

1. 객체 역할 분리

객체들의 역할을 지정하고 역할에 맞게 기능을 지정해주는 것이 어려웠다. 특히 사용자 입력검증에 대해서 하나의 객체에서 처리하고 싶었으나, 구조상 하나의 객체에서 처리되기 힘든경우들이 있었다. 초기 구조를 설계하는 과정에서 문제가 있었다고 생각한다. 특히 이번 과제는 에러를 발생시키고 종료하는것이 아닌 에러발생 지점부터 다시 값을 입력받아야하는 기능이 필요했기에 더욱 구현하기 어려웠다.

초기 설계가 부족하다 보니 구현을 해가며 그때그때 추가된 클래스들이 많이 있었고, 그렇다보니 객체간 역할의 분리가 제대로 이루어지지 않았다.

2. 메소드 기능 단순화

2주차 공통 피드백에서 메소드가 하나의 기능만을 수행하도록 최대한 단순히 작성하는것을 피드백해주었는데, 이때 15줄 이상을 넘지 않도록 하는것을 기준으로 잡았다. 이를 처음엔 의식하지 않고 코딩을 하다가 후에 확인을 해보니, 15줄이 넘는 메소드들이 매우 많았고, 하나의 메소드가 하는일이 다수 있는것을 확인했다. 그리고 확인했다 하더라도 이를 분리하는것도 생각보다 어려운 작업이었다.

3. enum사용하기

2주차 미션을 진행할 때, 값을 하드코딩한 경우들이 굉장히 많았는데, 2주차 공통피드백에서 하드코딩하지 말라는 얘기를 보자마자 아! 싶었다. 그래서 이번 주차 미션에선 java의 enum을 사용해보려 했는데, 상수값으로 필요한것이 무엇인지 바로바로 파악하기가 힘들었고, 변수명을 이해하기 쉬운 이름으로 짓는것도 생각보다 어려웠다.

4. MVC패턴적용

객체역할분리에서 겪은 어려움과 비슷한 어려움이다. model, view, controller의 역할을 처음 적용시켜가며 코딩을 해보았는데, 각 객체들이 어디까지 역할을 담당해야할지 정하는 것이 어려웠다. input view가 있다고 하면 input view는 사용자 입력값을 받는 역할만 해야하는가, 아니면 받은 값을 파싱하고 validation하는 일까지 해야하는가 정하는것이 애매했다.

 

배운점

1.  객체지향과 MVC 왜 써야할까?

객체지향은 하나의 큰 프로그램을 작은 객체들로 나누어 각 객체들이 작은일들을 나누어 하는 것이다.

그리고 MVC는 객체 지향 프로그래밍 설계를 할 때 자주 발생하는 문제들을 피하기 위해 사용되는 디자인 패턴으로, 개발을 하며 생길 수 있는 반복적인 문제들을 패턴을 통해 설계를 함으로써 미리 예방을 할 수 있게된다.

객체지향과 MVC를 사용하면 코드의 재사용, 가독성이 좋고, 유지보수가 쉬워지는 효과를 얻을 수 있게 된다.

실제로 이번 미션을 진행하며, 대부분 하나의 객체에서 모든것을 처리했던 저번 미션과는 달리 코드에 대한 가독성이 높아지는 것을 느낄 수 있었다.

2. 상수값은 하드코딩하지말고 enum을 적극적으로 활용하자

이번 미션에서 상수값으로 들어가는 값들을 enum으로 정의하여 진행하였는데, 정의한 상수값들이 생각보다 더 많이 쓰이게 되서 놀랐다. 확실히 유지보수에 쉬워보였고, 코드를 보았을 때 이 값이 어떤 것을 뜻하는지도 바로 파악이 되어 enum을 사용하는 것이 이리보나 저리보나 훨씬 좋아보였다.

3. 메소드는 최대한 단순하게

공통 피드백에서 각 메소드의 기능을 최대한 단순하게 하라고 하여 적용시켜보았다. 확실히 각 메소드가 어떤일을 하는지 이름으로 쉽게 바로 파악이 가능했고, 코드도 깔끔하게 정리되었다. 다만 처음 코드를 보는 입장에선 계속 왔다갔다 해야해서 조금 불편할 수도 있겠다는 생각은 들었다.

다른 사람들의 코드를 리뷰하면서 내가 짠 코드와는 많이 다름을 느꼈다. 나는 MVC패턴을 적용시킬 수 있을거란 생각을 못했는데, 다른 사람들의 코드를 보니 훌륭하게 적용시켜 정말 객체지향적인 코드를 짜는 것을 볼 수 있었다.

또 다들 상수값을 하드코딩한것이 아닌 상수선언을 하여 적용시킨것을 보니 코드의 가독성도 올라가고 유지보수도 훨씬 좋아보였다.

이번 주차 과제는 MVC패턴과 객체지향을 최대한 신경쓰면서 진행하는 것을 목표로 하려한다.

이번 2주차는 사실 1주차에 진행한 과제와 진행방식에 크게 다른점이 없었다. 시험기간과 겹치며 새로운 개발방식들을 공부하고 적용하기에 시간이 너무 부족했었다.

또 1주차가 끝나고 하려한 코드리뷰도 못했다. 다른 참가자들의 코드를 얼핏 보았을때, 깔끔하게 짠 코드들이 많아 참고해 내 코드에도 적용해 보고 싶었는데, 그 부분이 너무 아쉽고, 이번 주차가 끝난 이후 코드리뷰를 하는 시간을 많이 가져보려고 한다.

 

  • 지원서에 작성한 목표를 얼마나 달성하고 있다고 생각하나요? 그 이유는 무엇인가요?

1주차 과제를 진행하며 많은 것을 배우고 또 블로그에 글을 적으며 내것으로 만들었지만 2주차는 그렇지 못했다. 3주차부턴 조금 더 다른 사람들과 소통을 많이 하며 더 많은것을 배워가려고 한다.

  • 지원서에 작성한 목표를 변경해야 한다고 생각하시나요? 그렇다면 그 이유와 어떤 목표로 변경하고 싶으신가요?

1주차에 배운 것이 많았기에 아직 목표를 변경할 필요성은 느끼지 못하고 있다. 

  • 프리코스를 진행하면서 눈에 띄는 변화나 깨달은 점이 있나요?

깨달은 점

객체지향과 그에 맞는 설계를 위한 이해가 아직 부족하다. 코드를 짜며, 깔끔하지 못하다는 것을 스스로도 느끼고 있다.

MVC패턴과 같은 개발 패턴을 적용시켜보며 익숙해져가자

 

테스트 코드를 작성하는 것이 어렵고, 가독성이 좋지 않다. 코드 리뷰를 통해 개선해 나가야할 듯하다.

 

'우테코 7기 > 프리코스' 카테고리의 다른 글

[3주차] 로또 회고  (0) 2024.11.04
[3주차] 코드리뷰  (0) 2024.10.30
[1주차] 문자열 덧셈 계산기 회고  (0) 2024.10.20
[1주차] TDD(Test-Driven Development)란  (1) 2024.10.16
[1주차] Coding Convention이란  (0) 2024.10.16

1주차 미션을 수행하며 맨 처음 미션내용을 확인했을땐, 솔직히 쉽다고 생각했고 금방 끝날것이라고 생각했다. 실제로 프로그램의 로직 자체는 전혀 어려운것이 없었다.

그러나 그동안 학교에서 개인적으로 또는 팀으로 프로젝트를 했을때 아무런 규칙없이 진행했던 프로젝트들과는 굉장히 달랐다. 실제 현업에서 쓰이는 개념들(코딩 컨벤션, 커밋 컨벤션, 개발방법론, README, CHANGELOG 작성 등)을 적용해가며 진행해야했기 때문이다.

이 개념들은 나에게 굉장히 생소했고, 이해하고 적용하기까지 굉장히 오래걸렸다. 실제 코드를 짠 시간보다 이 개념들을 적용하는 시간이 3배이상 걸린것같았다. 특히 이번에 처음으로 TDD개발방법론을 접하면서, 테스트케이스를 만들고 실행하는게 가장 힘들었던것 같다. 하지만 이해하고 적응하기 시작하자 오히려 이런 체계적인 진행이 더 편하게 느껴졌고, 실제로 작성한 문서들과 코드가 가독성이 올라가고 이해하기 쉬워졌으며, 코드 테스트도 너무 편해졌다.

앞으로 남은 프리코스 기간에는 더 빨리 적용시킬 수 있을테니, 앞으로도 계속 적용해보며 온전히 나의 기술로 만드는 것을 목표로 할것이다.

'우테코 7기 > 프리코스' 카테고리의 다른 글

[3주차] 로또 회고  (0) 2024.11.04
[3주차] 코드리뷰  (0) 2024.10.30
[2주차] 자동차 경주 회고  (0) 2024.10.28
[1주차] TDD(Test-Driven Development)란  (1) 2024.10.16
[1주차] Coding Convention이란  (0) 2024.10.16

TDD란

테스트 주도 개발(Test Driven Development, TDD)은 익스트림 프로그래밍 개발방법론의 실천 방안 중 하나이다. 개발이 이루어진 다음 그것이 계획대로 잘 완성되었는지 테스트 케이스를 작성하고 테스트하는 타 방식과는 달리, 테스트 케이스를 먼저 작성한 다음 테스트 케이스에 맞추어 실제 개발 단계로 이행하는 개발방법론을 말한다.

테스트 케이스만을 완벽하게 수행하는 것을 목표로 하기 때문에 매우 빠르게 목표를 완료할 수 있다. 한편, TDD 자체가 하나의 테스트가 완전하지 않다는 것을 가정하고 있기 때문에 1차 테스트를 완료한 다음에 새로운 테스트 케이스를 확장해서 작성하고 그것을 통과하기 위한 개발에 들어가는 과정을 끊임없이 반복하여 큰 규모의 프로젝트를 완성해가는 것이다.

 

TDD를 사용해야 하는 이유

  • 코드의 유지보수가 용이해진다
    프로그래밍 개발에서는 처음 개발할 때보다 이미 개발한 코드의 버그를 수정하고, 최적화하고, 새 기능을 추가할 때 비용이 더 들어간다. 그런데 테스트를 작성하면 코드에 절대로 뒤떨어지지 않는 문서가 탄생하며, 다른 코드의 행위가 보증되므로 원하는 부분에만 신경을 쓸 수 있으며, 테스트하기 쉬운 코드는 자연히 품질이 높아지므로 다시 읽기도 편하다. 또한 테스트가 있으면 안심하고 코드를 리팩토링할 수 있다.
  • 프로그래밍 시간이 단축된다
    테스트를 작성하는 시간을 포함시키고도 오히려 전체 작업 시간은 줄어든다. 왜냐하면 프로그래밍에서 대부분의 시간이 디버깅에 투입되는데, 테스팅은 디버깅을 해야 할 범위를 단위 안으로 제한함으로써 디버깅에 들어가는 노고를 크게 줄여준다. 또한 유지보수 시에도 상술한 이유로 효율이 높아진다.
  • 뛰어난 프로그램 소스코드 기록
    테스트를 작성하는거 자체가 훌륭한 소스 코드의 기록이다. 소스 코드 중간중간의 주석은 왜 코드가 이렇게 짜여져 있는지를 기록한다면, 유닛 테스트는 코드가 어떻게 행동해야 하는지를 기록한다. 따라서 다른 프로그래머들이 쓴 (또는 과거의 자신이 쓴) 코드를 파악하고 프로그램을 수정, 확장하는데 시간과 비용이 크게 단축된다.

 

Unit Test의 중요성

테스트를 할 때 Unit test를 하는 것이 중요하다고 한다.

Unit Test란?

소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차다. 즉, 모든 함수와 메소드에 대한 테스트 케이스(Test case)를 작성하는 절차를 말한다.

Unit Test의 장점

Unit Test를 진행하게 된다면 하나의 기능을 독립적으로 테스트를 하며 코드 변경으로 인해 문제가 발생하여도 짧은 시간안에 해당 문제를 파악할 수 있다.

  • 새로운 기능 추가 시 수시로 빠르게 테스트 할 수 있다.
  • 리팩토링 시에 안정성을 확보할 수 있다.
  • 테스팅에 대한 시간과 비용을 절감할 수 있다.
  • 코드에 대한 문서가 될 수 있다.

좋은 Unit Test를 하는 방법

  • 1개의 테스트 함수에 대해서는 assert를 최소화해야한다.
  • 1개의 테스트 함수에는 1가지 개념만을 테스트하여야 한다.

좋고 깨끗한 테스트 코드는 FIRST라는 5가지 규칙을 따라야 한다.

  • Fast: 테스트는 빠르게 동작하여 자주 돌릴 수 있어야 한다.
  • Independent: 각각의 테스트는 독립적이며 서로 의존해서는 안된다.
  • Repeatable: 어느 환경에서도 반복 가능해야 한다.
  • Self-Validating: 테스트는 성공 또는 실패로 bool 값으로 결과를 내어 자체적으로 검증되어야 한다.
  • Timely: 테스트는 적시에 즉, 테스트하려는 실제 코드를 구현하기 직전에 구현해야 한다.

 

'우테코 7기 > 프리코스' 카테고리의 다른 글

[3주차] 로또 회고  (0) 2024.11.04
[3주차] 코드리뷰  (0) 2024.10.30
[2주차] 자동차 경주 회고  (0) 2024.10.28
[1주차] 문자열 덧셈 계산기 회고  (0) 2024.10.20
[1주차] Coding Convention이란  (0) 2024.10.16

우아한 테크코스의 프리코스 1주차를 진행하며 "자바 코드 컨벤션을 지키면서 프로그래밍한다" 라는 부분을 보며, 코드 컨벤션이라는 개념을 처음 접하게되었다.

그동안은 혼자 코드를 작성하는 일이 대부분이었고, 간혹 팀 프로젝트를 하더라도 소규모 또 유지보수할 일도 없었기에 크게 신경 안쓰던 부분이었다.

그러나 현업에선 다수의 개발자가 같이 협업을 하고, 유지보수 또한 작성한 사람이 아닌 다른 사람이 하게되는 경우가 많기에 이런 코딩 컨벤션을 지키는것이 중요함을 알게되었다.

코딩 컨벤션이란?

코딩 컨벤션이란 코드를 어떻게 작성할지에 대한 룰을 말한다. 탭의 스페이스 개수, 줄바꿈 ,조건문,반복문에서 중괄호는 어떻게 할것인지, import시에 wildcard를 쓰지 않기 등등이다.

 

코딩 컨벤션이 필요한 이유

위에서도 말했듯, 내가 쓴 코드를 다른 사람들이 보게되는 일이 많기에 코드의 가독성을 위해서 쓰인다.

  • 코드의 가독성이 좋아짐
  • 유지보수에 용이함

 

코딩 컨벤션 적용하는 법

 

XML 포매터를 다운받아서 위와 같이 적용하면 된다.

프리코스에서 사용하는 코딩 컨벤션

프리코스에서 사용하는 코딩 컨벤션은 Google java style guide를 따른다.

직접 번역해볼까도 했으나, 이미 번역을 해주신 선배님(감사합니다)가 계시기에 링크만 적어두겠다.

https://github.com/JunHoPark93/google-java-styleguide

https://newwisdom.tistory.com/m/96

'우테코 7기 > 프리코스' 카테고리의 다른 글

[3주차] 로또 회고  (0) 2024.11.04
[3주차] 코드리뷰  (0) 2024.10.30
[2주차] 자동차 경주 회고  (0) 2024.10.28
[1주차] 문자열 덧셈 계산기 회고  (0) 2024.10.20
[1주차] TDD(Test-Driven Development)란  (1) 2024.10.16

합병 정렬(Merge sort)이란?

  • 합병정렬(merge sort)은 정렬 알고리즘의 한 종류로, 폰 노이만이 개발한 알고리즘이다.
  • 이 정렬은 안정 정렬에 속하며, 분할 정복(divide and conquer) 알고리즘의 하나이다.

 

합병 정렬(Merge sort) 아이디어

https://en.wikipedia.org/wiki/Merge_sort

합병(Merge)라는 이름에서 알 수 있듯, 합병 정렬의 기본 아이디어는 정렬할 배열을 분할하여, 작은 조각으로 나눈 후 더 이상 나눌 수 없을 때(하나의 원소만 있을때) 다른 조각과 비교하며 합쳐 정렬하는 알고리즘이다.

과정

  1.  정렬되지 않은 리스트를 2개의 리스트로 나눈다.
    • 각 리스트의 길이가 1이 될때까지 반복한다(길이가 1인 리스트는 정렬된 것으로 간주한다.)
  2. 2개의 리스트의 값들을 처음부터 하나씩 비교하여 두 개의 리스트의 값 중에서 더 작은 값을 새로운 리스트로 옮긴다.
    • 둘중 한 리스트가 끝날 때까지 이를 반복한다.
    • 한 리스트가 끝나면, 나머지 값들은 새 리스트에 복사해서 넣어준다(이미 정렬되어 있으므로)
  3. 2번 과정을 하나의 리스트가 될때까지 반복한다

 

합병 정렬(Merge sort) 증명

Merge 과정은 문제없이 기능한다 가정

귀납적 증명(Proof by Induction)

1. Base Case (기본 단계):

배열의 크기가 1 또는 0인 경우

  • 배열의 크기가 0 또는 1이면, 이미 정렬된 상태이다.

2. Inductive Hypothesis (귀납 가정):

배열의 크기가 n 이하인 모든 배열에 대해 Merge sort가 올바르게 작동한다고 가정.


3. Inductive Step (귀납적 단계):

배열의 크기가 n+1인 배열에 대해서 Merge sort가 올바르게 작동함을 증명.

  • 크기가 n+1인 배열 A를 반으로 나누어 두 개의 하위 배열 L과 R로 나눈다고 가정하자. 각 하위 배열의 크기는 대략 n/2 또는 그와 비슷하다.
  • 귀납 가정에 따라, 배열 L과 배열 R에 대해 각각 Merge sort를 호출하면, L과 R은 각각 오름차순으로 정렬된다.
  • Merge 과정이 끝나면, L과 R의 모든 요소가 오름차순으로 정렬된 하나의 배열로 합쳐지고. 이 배열은 오름차순으로 정렬된 상태이다.

따라서 배열의 크기가 n+1일 때도 Merge sort는 올바르게 작동한다.

 

합병 정렬(Merge sort) 시간복잡도

$T(n)=2T(\frac{n}{2})+n$ (이때 n은 merge시 걸리는 시간)

$\ \ \ \ \ \ \ \ =2(2T(\frac{n}{4})+\frac{n}{2})+n=4T(\frac{n}{4})+2n$

$\ \ \ \ \ \ \ \ =4(2T(\frac{n}{8})+\frac{n}{4})+2n=8T(\frac{n}{8})+3n$

$\ \ \ \ \ \ \ \ ...$

$\ \ \ \ \ \ \ \ =nT(1)+log(n)*n$

$\ \ \ \ \ \ \ \ =n*log(n)$

 

합병 정렬(Merge sort) 구현

#include <iostream>
using namespace std;

// 두 개의 하위 배열을 병합하는 함수
void merge(int arr[], int left, int mid, int right) {
    int n1 = mid - left + 1;  // 왼쪽 하위 배열의 크기
    int n2 = right - mid;     // 오른쪽 하위 배열의 크기

    // 임시 배열 생성
    int L[n1], R[n2];

    // 원본 배열의 값을 각각 왼쪽과 오른쪽 임시 배열로 복사
    for (int i = 0; i < n1; i++)
        L[i] = arr[left + i];
    for (int j = 0; j < n2; j++)
        R[j] = arr[mid + 1 + j];

    // 두 배열을 병합하여 정렬된 상태로 원래 배열에 다시 삽입
    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k] = L[i];
            i++;
        } else {
            arr[k] = R[j];
            j++;
        }
        k++;
    }

    // 왼쪽 배열의 남은 요소 복사
    while (i < n1) {
        arr[k] = L[i];
        i++;
        k++;
    }

    // 오른쪽 배열의 남은 요소 복사
    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
}

// Merge Sort 알고리즘
void mergeSort(int arr[], int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2;

        // 왼쪽과 오른쪽 배열에 대해 재귀적으로 정렬
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);

        // 정렬된 두 배열을 병합
        merge(arr, left, mid, right);
    }
}

// 배열을 출력하는 함수
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++)
        cout << arr[i] << " ";
    cout << endl;
}

int main() {
    int arr[] = {12, 11, 13, 5, 6, 7};
    int arr_size = sizeof(arr) / sizeof(arr[0]);

    cout << "Given array is \n";
    printArray(arr, arr_size);

    mergeSort(arr, 0, arr_size - 1);

    cout << "\nSorted array is \n";
    printArray(arr, arr_size);
    return 0;
}

+ Recent posts