Level : 13,717 WORDPRESS BOOK LINKEDIN PATENT Send Mail 동냥하기 윤지오

Digital Nomad

설명이 부족한 공식 문서 때문에 실무 개발자가 궁금해할. 내가 궁금하니 

내용 중 하나.

https://docs.swift.org/swift-book/ReferenceManual/Patterns.html#grammar_value-binding-pattern

공식문서의 내용에서 쓰는 let point는 튜블 패턴이다.


그런데 튜플은 튜플대로 사용하면 되는데 굳이 switch 문에 다시 바인딩을 시키는 것이 의아하다. 왜냐면 switch 문은 다양한 case에 따라 if 문의 개수를 줄이는데 유용하고 C언어에서 어셈블리로 변화했을 때 switch case문이 다중 if문에 비해 속도가 빠르듯이 더 나은 성능을 위해 switch를 쓰는데 하나의 case문이라면 의미가 없기 때문이다.


인자 개수에 따라 처리가 가능하다면 유용할 텐데 그러지 않다. switch 문의 인자 개수는 동일해야 한다. 만약,


let point = (3, 2, 4)


switch point {

// Bind x and y to the elements of point.

case let (x, y):

    print("The point is at (\(x), \(y)).")

case let (x, y, z):

    print("The point is at (\(x), \(y), \(z)).")

}


이런 예제라면 에러 난다. 그러면 상수값과 섞어 쓸 때 의미가 있게 된다.


        let point = (3, 2)


        switch point {

        // Bind x and y to the elements of point.

        case (3, let y):

            print("The point is at  \(y).")

        case (let x, 2):

            print("The point is at \(x).")

        default:

            print("default")

        }


혹은, 

        let point = (3, 2)

        let point 2 = (3, 8)

        let points = (point, point 2)


        switch points {

        // Bind x and y to the elements of point.

        case ((3, 2), let y):

            print("The point is at  \(y).")

        case (let x, (0, 0)):

            print("The point is at \(x).")

        default:

            print("default")

        }

이런 식이다.  swift는 break문이 필요하지 않아 상위 case에서 참이 되어 버리면 하위 case는 쓸모가 없게 되긴 하지만 튜플 패턴에서 일정 값만 거르고 해당 값을 binding 해서 쓸 때는(굳이 binding 안 하고 써도 되겠지만) 써도 된다는 뜻.


여기서 let을 var로 바꾸었을 때 바딩 된 값이 ref 값인지 copied 값인지 궁금해진다. 


        let point = (3, 2)

        var point 2 = (3, 8)

        let points = (point, point 2)


        switch points {

        // Bind x and y to the elements of point.

        case ((3, 2), var y):

            print("The point is at  \(y).")

            y = (4, 4)

            print("The point is at  \(y).")

        case (let x, (0, 0)):

            print("The point is at \(x).")

        default:

            print("default")

        }


        print("point 2 = ", point 2)


The point is at  (3, 8).

The point is at  (4, 4).

point 2 =  (3, 8)


복사본이 전달된다. call by reference로 볼 수 있는데 call by assignment 방식 때문에 객체의 경우도 따로 조사를 해봐야 한다. swift에서 class init 후 전달되는 모든 값은 참조형으로 작동하기 때문에라도 한번 더 봐야 한다. 이 말은 3년간 Objective-C 할 때는 함수 포인터보다는 NSNotificationCenter를 통하여 각기 다른 객체(여기서는 파일이라고 생각하면 되겠다)에 메시지를 전달하여 해당 함수를 동작시켰다. 파라미터 전달 방식은 프로그램이 커지고 빌더 패턴이 하나라도 끼인 상태라면 전달이 상당히 복잡해져서 요구사항이 바뀐 경우 그냥 노티피케이션센터에 메시지 하나 더 정의해서 전달했다는 뜻이다. 물론, 안드로이드로 치면 해당 액티비티가 가진 멤버 자료들이 resume 되는 시점에 제대로 복구되는지 상관 않고 기능 구현만 했다는 뜻이다. 대부분 블랙박스 검증이니까 얼추 잘되면 그냥 오케이다. 그러나 의료 앱을 만드는 지금은 웬만한 자료는 가지고 있지 않는다. 함수형 프로그램의 철학대로 데이터의 흐름에만 집중을 한다. 가끔 저렇게 요구사항은 바뀌고 급하게 검증을 돌려야 하는 상황이면, Call by Reference를 십 분 활용하여


var pDashboard : DashboardScrollView? = nil


이렇게 꼭 필요한 자료가 있는 싱글톤에 정의하고, 


GS.s.pDashboard = self


만든 객체를 넣고


GS.s.pDashboard?. topScroll()


어디서든 호출할 수 있게 한다. 참고로  swift에서 싱글톤은

private init()

static let s

으로 만든다. 사실, 나의 실무 프로그래밍 책에 쓴 것럼 동시성을 체크해야 하지만 네트워크 상황에서도 DispatchQueue 를 전혀 쓰지 않고 있기 때문에 문제는 없어 보인다. closure를 이용하면 된다. (더블클로저를 이용한 프로그래스바 참조) 물론, 운영체제 혹은 프로세서의 멀티 프로세싱에서 앱이 따로 thread를 만들지 않으면 앱 실행 순서는 리니어 하다는 것을 가정해야 하는 위험이 있긴 하지만 다른 안정 장치로 의료용 앱을 보호해야 한다.


자 다시, call by assignment 로 돌아가자. 튜플은 값을 주고, 튜플도 객체니 그냥 call by reference로 믿어도 되겠지만 결국 책임은 실무 프로그래머에게 있으니 의심해 볼 수 밖에 없다.


class dummy {

    var A : Int = 3

}


더미 class를 만들자.


        var a = dummy()


        switch a {

        case var b :

            print("a.A = \(a.A)")

            print("b.A = \(b.A)")

            b.A = 2

            print("a.A = \(a.A)")

            print("b.A = \(b.A)")

        default:

            print("defult")

        }


        print("a.A = \(a.A)")


a.A = 3

b.A = 3

a.A = 2

b.A = 2

a.A = 2


바뀐다. 그럼 이 경우는?


        var a = dummy()


        switch a.A {

        case var b :

            print("a.A = \(a.A)")

            print("b = \(b)")

            b = 2

            print("a.A = \(a.A)")

            print("b = \(b)")

        default:

            print("defult")

        }


        print("a.A = \(a.A)")


a.A = 3

b = 3

a.A = 3

b = 2

a.A = 3


안바뀐다.


결국, 파이썬처럼 call-by-assignment 로 동작하는 것을 볼 수 있다.


이제 switch 바인딩의 의미가 값 결정에 있지 않고 단순 커넥션이며, 객체에 따라 다르게 assignment로 동작한다는 것을 알 수 있다. swift는 직관적 리딩을 위해 파라미터 까지도 생략하려면 _(under score)를 써야 하게 해놨는데 복잡하게 프로그래밍 하는 것보다는 직관적으로 알 수 있게 하는게 나을 것이다.


그러나, 난 어렵게 프로그래밍 하는 것을 추천한다. 거대한 switch 문을 만들길 바란다. 대한민국은 프로그래머보다 경영자가 우대받는 사회니까. 우리팀이 이기길 바라는 것은 팀원으로 당연한거니까.


띄워쓰기가 맘에 안들수도 있겠다. 귀차니즘에 의해 Xcode의 ^I 정렬 방식을 따르고 브런치의 맞춤법 검사를 필터링 없이 돌린다.(소스에도 걸리는 것을 보니 ...)


혹 구독자를 위해 요약하면,


Swift의 value-binding pattern은 call by assignment 로 동작한다는 것. 물론, siwft 4.2 기준이며 5가 되었을 때도 공식문서에 별다른 말이 없으면 다시 확인해야 한다. product랑 가까운 개발자 일수록 이런 말 못할 고민은 늘어간다. 비트 하나 차이로 사람이 죽을수도 있으니... 늘 낮은 자세로 탐구하고 고민하고 책임져야 한다. ㅠㅠ

Comment +0

막 쓰지만... 누군가에겐 도움이 되겠지 하고 또 일정 기간 동안 올려본다.(구독자들은 알겠지만 그냥 지울 때도 있고 블로그로 올릴 때도 있다. 순수하게 떠들고 싶은 마음으로 쓰는 경우라...)


리액티브, Redux, 패턴 이야기를 해 볼까 한다. 내용은 구리다. 나는 바쁘니까.

그래도 정말 삽질하지 말라고 하고 싶다. 이미 제품을 만든 다른 사람이 이야기를 좀 해줬으면 좋겠다. 네가 한 말이 틀렸다고. 너무 제품에만 집중해서 시간을 보내다 보니(정치/사회도 관심이 많아서) 정말 맥북 모니터만 뚫어져라 보는 것 같다. 최근 하이와 여행 때도 밤에는 늘 노트북만 쳐다보고, 행사 있을 때마다 맥북을 들고 다녔다. ㅠ 너무 바쁘면 시야가 좁아진다. 그래서 누가 틀렸다고 이야기해줬으면 좋겠다는 말이다. 브런치의 자동 수정 기능을 믿고 그냥 클릭만 할 거기에 이상한 게 있어도 지적 바란다.


프로젝트를 3개 진행 중이다. 모두 돈을 받는 일이다.


1. 우선, react 하지 마라. 망한다. 간단한 앱 만드는 것은 괜찮은데 IoT 들어가거나 코어 그래픽 들어가면 쓰지 마라. 왠지 설계자가 개발자 출신이 아니라면 그냥 처음부터 쓰지 마라.


2. 리액티브 처음에는 괜찮은데 프로젝트 커지면 오히려 디버깅이 안된다. 적당한 프로젝트에 쓰길 바란다.


3. Reswift는 좋다. 마음껏 써라. 프로젝트 하나는 그걸 쓴다. 그런데 패턴으로도 구현 가능하다. 내가 썼던 글...(더블 클로저)로 구현해도 되는데 프로젝트 커지면 가독성 떨어지는 게 사실이다. 그럴 때 GS.swift, BR.swift를 만든다. 


브로드 캐스트를 담당하는 BR.swift 는 이런 형태다. 뭐, 이미 다 말했지만... 정말 개발 해보니 이거면 되서 ... 다시 쓴다.


import UIKit


//MARK: protocols titled by weird name to find related modules easily. -hjh-

protocol gamcho {

    func updateText()

}


protocol trendpopup {

    func updateText()

}


protocol snowboard {

    func updateGraph()

}


class BR {


    static let s = BR()


    var BRtendency3 dots = [gamcho]()

    var BRtrendpopup = [trendpopup]()

    var BRsnowBoard = [snowboard]()


    private init() {

    }


    func attachBRtendency3 dots(observer : gamcho) {

        BRtendency3 dots.append(observer)

    }


    func attachBRtrendpopup(observer : trendpopup) {

        BRtrendpopup.append(observer)

    }


    func attachBRdashboard(observer : snowboard)  {

        BRsnowBoard.append(observer)

    }




    //MARK: notify to update    BR_ prefix

    func BR_snowBoard(andThis : ()->()) {

        if(GS.s.bSemaphore) {

            GS.s.bSemaphore = false

            for woman in self.BRsnowBoard {

                woman.updateGraph()

            }

            GS.s.bSemaphore = true

        } else {

            print("Busy")

        }

        andThis()

    }


    func BR_tendency3 dots() {

        for homme in self.BRtendency3 dots {

            homme.updateText()

        }

    }


    func BR_trendpopup() {

        for woman in self.BRtrendpopup {

            woman.updateText()

        }

    }

}


글로벌 세팅인 GS.swift는 이런 형태

class GS {


    static let s = GS()


    var bSemaphore : Bool = true

    let queue = DispatchQueue(label: 


.

.

  var lp1 : InsidePanel? = nil

    var rp1 : InsidePanel? = nil

    var lp2 : InsidePanel? = nil

    var rp2 : InsidePanel? = nil

.

.

    func elapsedTime() -> TimeInterval {

        return abs(self.startTime.timeIntervalSinceNow)

    }

.

.

   private init() {

                logLevel =. all


.

.

.


특이한 것은 내가 안드로이드 할 때도 항상 싱글톤은 하나 놔두고 status를 저장하고 썼었다. 삼성에서 안드로이드 프레임웍 만들 때 큐와 BR 구조를 짜다 보니 객체를 등록하고 for 문을 돌면서 메시지를 보내는 BR 구조(옵서버 패턴+ for 문)에 대해 알게 되고 그 이후로는 무조건 썼는데. 나중에 리액티브라는 것을 접하니 큐와 구독(옵저BR구조)에 스케쥴러까지 결합한 형태라는 것을 알게 되었다. 이게 본인이 직접 안 짜고 라이브러리의 힘을 빌면 다양한 디바이스와 커뮤니케이션에서 디버깅이 제대로 될까 했는데... 아니나 다를까 개고생을 해야 했다. 라이브러리는 정말 기본적으로 도와주는 것만 써야 한다고 생각했다. 깃 헙을 보면 reacrokit 보다 snapkit에 star에 10배가 많은 것도 그 이유겠다. 물론, 만든 분을 좋아하긴 하지만... 오래도록 RTOS 프로젝트와 커널을 했던 나로서는 앱 단에서 구현된 스케쥴러가 그리 반갑지는 않다. 프로세스 자체도 운영체제 때문에 오차가 생기는데 그 위에 도는 스레드는 또 어떻고 그 스레드 위에서 도는 앱이 구현하는 스케쥴러도 어쩌리... 펌웨어 하다 보면 라즈베리 파이임에도 불구하고  POSIX 타임 틱도 구려서 커널 time 함수도 그때그때 다시 만드는 상황에... 말이다.(저번 에트리 강의 때 시그널 제작했었는데 time 함수 다시 짰다 [내가 강사임...])


믓튼, iOS 기준으로 일전에는 노티피게이션센터를 썼는데 클러저 덕분에 REST API 동기화는 쉬웠고, 프로그램 전역에는 BR.swift 하나면 충분했다. MVP, MVVM, MVC에 싱글톤과 BR 가능한 옵서버 패턴을 붙이면 두려울 게 없었다. 다만... ReSwift의 경우 데이터 흐름을 고려했다는 점에서 새롭게 도입해서 프로젝트를 잘 마무리하게 되었다.


BadgeSwift, SnapKit, JTAppleCalendar, SwiftNotification, SwiftMessages, lottie-ios  등 UI 라이브러리를 마음대로 써도 된다. View에만 영향을 미치니까. REST는 Alamofire 가 최고다. Pitaya 쓰면 분산되는데 알라모퐈여 쓰면 클해스 하나에 REST를 몰아넣을 수 있다. 막일 방지해주는 SwiftDate, FileKit, SQLiteSwift3, SwiftKeychainWrapper, SwiftyJSON 등 좋다. Firebase 같이 무조건 쓸 수밖에 없는 라이브러리를 제외하고는 SwiftLint, ReSwift 추천한다. 그래프 라이브러리 성능 보니 믿음이 안 가서(프로젝트에서 원하는 성능으로 커스터마이징 하려고) 만들었더니 프로젝트의 1/4을 차지한다. 거대해졌지만 이렇게 커도 GS, BR로 충분하다. 물론, 하나에 다 때려 넣으면 너무 커져서 GV(Global Variable), VD(Volatile Datas) 등으로 이원화해서 쓰기도 했다. 

 하드웨어 제어하는 IoT 기능(BLE, WiFi, socket.io) 코어 그래픽 라이브러리와 위에 언급한 라이브러리 등을 다 넣어도 데이터 꼬임 없는 산출물이 나왔다.


그냥... 카톡만큼 크진 않지만  3개 돈 받는 거 말고 전자 지갑도 만들어 보고(블로그에도 올림) 텔레그램도 하고 있으니 카톡만큼 키우는 게 어렵진 않을 것 같다.


따로 하는 게임이 잘돼서 빠른 시일 내에 법인이 만들어지면 좋겠다.



추가... 내가 쓰는 옵셔널 코드조각



self.vDashboard?.center = tempt

---

static func worldLine(context : CGContext?, _ x1 : CGFloat, 


---

class jhGraphBuilder<T> {

    private var superScene : T?


---

print("ctime in jhType22graphPanel<T> = ", (self.superScene as? jhSceneTimeLine)?.currentTime)


---

class jhPanel<T> : jhDraw, observer_p {

    

    internal var superScene: T?


---

    internal var mAllofCountOfDatas : Int {

        get {

            return eoDataCenter.eoDatasDashboard[jhPanelID]?.d.count ?? 0

        }

    }



---

class jhGuideLine : CALayer {

    

    var layer_size : CGSize = CGSize.init(width: 0, height: 0)

    var lineX : CGFloat

    var lineY : CGFloat

    var lineWidth : CGFloat

    

    init?(x: CGFloat, y: CGFloat, lineWidth: CGFloat, layer:Any) {

        if GS.s.logLevel.contains(.graph2) { print("jhGuideLine_init") }



---

        for woman in 0..<4 {

            for man in 0..<(jhDatas[woman]?.d.count ?? 0) {


---

            ctime = (self.superScene as? jhSceneTimeLine)?.currentTime ?? Date()

            etime = (self.superScene as? jhSceneTimeLine)?.endTime ?? Date()


---

        guard var jhDatas : [Int : hjh] = eoDataCenter.eoDatasDashboard else {

            print("currentPoint.x", currentPoint.x)

            fatalError("guard var jhDatas : hjh = eoDataCenter.mDatas[0] else {")

        }


---

        scene!.createPanels(s: scene!, withHeightRatios: ratioNtype(ratio: 5.10, type: graphType.TYPE1), ratioNtype(ratio: 2.93, type: graphType.TYPE2), ratioNtype(ratio: 1.96, type: graphType.TYPE3))



---


    override func createPanels(s : jhScene, withHeightRatios: ratioNtype...) {

        

        var panel : jhPanel<jhSceneTimeLine>? = nil



---

   panel = jhGraphBuilder<jhSceneTimeLine>()

                .type(rnt.type)

                .frame(0, GS.s.jhSceneHeight!, jhSceneFrameWidth*4, vHeight)

                .scene(self)

                .build()



보너스 삼항연산자


            let xOffset = contentSize.width < bounds.width ? 0 : (contentSize.width - bounds.width)/2


Comment +0

"-K"는 제목 글자 수 제한 때문(본디 kernel이다.)



현재 커널을 본다.

eddie@ubuntu:~/Downloads/linux-4.17.10$ uname -a

Linux ubuntu 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux


http://kernel.org 의 최신 커널 버전이 자신의 커널 버전보다 높다면,...

에서 바닐라 커널을 받는다.


압축을 풀어 준다.

tar xvf linux-4.17.10.tar.xz


현재 커널 설정을 복사한다.

eddie@ubuntu:~/Downloads/linux-4.17.10$ cp /boot/config-4.15.0-20-generic ./.config


빌드 패키지를 설치한다.

sudo apt-get install build-essential libncurses-dev flex libssl-dev libelf-dev -y


빌드한다

make -j5

커널 업이 되면서 생긴 신규 옵션에 대해서 물어본다. 디폴트 설정이 되도록  엔터친다.

make -j5 modules


모듈을 설치한다.

sudo make modules_install

확인

eddie@ubuntu:~/Downloads/linux-4.17.10$ ls /lib/modules/

4.15.0-20-generic  4.15.0-23-generic  4.15.0-29-generic  4.17.10


커널 설치

make install



Found linux image: /boot/vmlinuz-4.17.10

Found initrd image: /boot/initrd.img-4.17.10

.

.

.

Found memtest86+ image: /boot/memtest86+.elf

Found memtest86+ image: /boot/memtest86+.bin

done


reboot


eddie@ubuntu:~$ uname -a

Linux ubuntu 4.17.10 #1 SMP Fri Jul 27 08:49:56 PDT 2018 x86_64 x86_64 x86_64 GNU/Linux



리눅스 옵션을 잘 알려면

x86_64용으로 configration인 make defconfig로 기본 설정 후 비교하는 것 부터 시작하는 것이 좋다.

리눅스 커널 컴파일 옵션은 9000개며, 각 옵션 간의 의존성은 커널 컴파일하면서 배우는 수밖에 없다. 커널 패키징 하는데 8000번의 커널 컴파일이 요구된다. 청춘은 멍들고...


zImage는 1메가 한계로 요샌 bzImage만 쓴다. bzImage만 만들려면 Rygen 1700 + 8GB 램(가상)에서 

time sh -c 'make clean && make bzImage && make modules'

로 실행,


real159m12.270s

user139m15.018s

sys20m49.665s

시간이 소요되었다.



커널을 apt를 이용해 받으려면, 

/etc/source.list 에서 deb-src 의 주석 3개를 풀어준다.

apt-get update


이후 

sudo apt source linux-image-`uname -r`

오랜 리눅서는 소스 컴파일이 좋을 듯. 예전엔 패키지 관리자도 없어서 소스 컴파일이 기본이었기 때문.


그리고 기본기를 익히려면 결국 C와 Makefile로 돌아간다.

Comment +0

Basically tab bar provides the default case when the image is selected. sometimes we want to change its color or image. I was looking for changing image when it is selected. but A lot of information on the web is to change color.

here are the codes who like the same as I want.




class ViewControllerUITabBar: UITabBarController, UITabBarControllerDelegate {

    


.

.

.

  func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {

        GS.s.selectedTab = tabBarController.selectedIndex


   case 2:

            tabBar.selectedItem?.selectedImage =  imageLiteral(resourceName: "img_message_warning")


You have to change the image in the assets to be the original image if you want the icon remains as the same image.



Comment +0

Privacy - Analytics - Analytics Data



Comment +0



 다양한 이동 방법이 있다

iOS & Swift

 기본

  let storyboard  = UIStoryboard(name: "TabMenu", bundle: nil)

                    let VC = storyboard.instantiateViewController(withIdentifier: "settings_sharing_code"asSharingCodeController


1. 해당 네비게이션 바 컨트롤러 포인터를 싱글톤에 저장 후 다시 로드하여 이동


                    
self.navigationController?.pushViewController(VC, animated: true)



            let storyboard  UIStoryboard(name: "Message", bundle: nil)

            let VC = storyboard.instantiateViewController(withIdentifier: "MessageListViewController"asMessageListViewController

            GS.s.currentDashboard?.navigationController?.pushViewController(VC, animated: true)



2.윈도우에서 뷰 컨트롤러 뽑아내기



   self.window?.visibleViewController!.navigationController?.setNavigationBarHidden(true, animated: false)

        self.window?.visibleViewController!.tabBarController?.tabBar.isHidden = true

        self.window?.visibleViewController!.navigationController?.pushViewController(VC, animated: true)



이렇게도 됨

   self.window?.visibleViewController!.present(VC,animated: true,completion: nil)



끝, 끗 End. Fin.


 




Comment +0

USAGE:

var response: jhChart<Data>?


DECLARE:

public struct jhChart<Value> {

    public let result: Result<Value>

    public var value: Value? { return result.value }

...}



structure 의 장점


늘어나는 properties 를 하나에 때려넣을 수 있다.


struct jhData {




    internal var mValuesOfDatas : Array<CGFloat> = Array() {

        didSet {

            if GS.shared.logLevel.contains(.graph) {

                print("mValuesOfDatas.count has been changed to \(mValuesOfDatas.count) in jhPanel")

            }

        }

    }

    

    /// Axes

    var mCountOfaxes_view : Int = 1

    var mUnitOfHorizontalAxes : CGFloat = 100

    var mcountOfHorizontalAxes : Int = 3

    

    internal var mVerticalRatioToDraw_view : CGFloat = 1.0

    

    var axisDistance : CGFloat {

        get {

            return (jhDraw.maxR  mMargin * 2) / CGFloat(mCountOfaxes_view+1)

        }

        set(distance) {

            mCountOfaxes_view = Int(jhDraw.maxR  CGFloat(distance))

        }

    }


    var mCountOfDatas : Int

    var mMaxValueOfDatas : CGFloat

    var mMinvalueOfDatas : CGFloat

    

    internal var mMargin : CGFloat = 300 //1000.0

    //1000.0 is 13.3..%, margin between panel & graph area 0<=martgin<10000.0

    

    init() {

        mCountOfDatas = 0

        mMaxValueOfDatas = 0

        mMinvalueOfDatas = 0

    }

.

.

.



그리고 인자(인수, 파라미터, 로 넘길 때 편하다.


복잡하게 안 넘기고


 dataLayer = jhLayer(&jhClientServer.mValuesOfDatasself.data.axisDistanceself.data.mVerticalRatioToDraw_viewself.data.mMarginmPanelWidth ?? 0mPanelHeight ?? 0mFixedPanelWidthmFixedPanelHeight, layer: 0)



struct 만 넘기자.





Comment +0

사실 그 동안 많은 변화가 있었는데 수없이 많은 요구사항에 미친 듯이 UI를 찍어내다 보니 결국 기존 배웠던 지식과 융합이 되고 네이밍도 그와 비슷하게 되고 있다.



class InsidePanel1 : UIView {


    lazy var leftStackView : UIStackView = {

        let ret = UIStackView()

        ret.axis = .vertical

        ret.distribution = .equalSpacing

        ret.alignment = .center

        ret.spacing = 1

        return ret

    }()

    

    lazy var background_view : UIView = {

        let ret = UIView()

        ret.backgroundColor = UIColor.white

        return ret

    }()


    var item1 = UILabel()

    var img1 = UILabel()

    var item2 = UILabel()

    var item3 = UILabel()

    

    func entry() {

        self.addSubview(leftStackView)

        leftStackView.snp.makeConstraints {

            $0.width.equalToSuperview()

            $0.height.equalToSuperview()

            $0.top.equalToSuperview()

        }

        leftStackView.translatesAutoresizingMaskIntoConstraints = false


        item1.text =

.

.

.


Comment +0

snapkit을 쓰다보면 .top 혹은 .bottom, .left, .right 의 크기 조절에 실패하는 경우가 있다. 그럴 때 스택뷰를 이용하면 해당 constraints를 안 써도 되고 구문도 간결해진다.


    lazy var leftStackView : UIStackView = {

        let ret = UIStackView()

        ret.axis = .vertical

        ret.distribution = .equalSpacing

        ret.alignment = .center

        ret.spacing = 1

        return ret

    }()

.

.

.


   self.addSubview(leftStackView)

        leftStackView.snp.makeConstraints {

            $0.width.equalToSuperview()

            $0.height.equalToSuperview()

            $0.top.equalToSuperview()

        }

.

.

.



leftStackView.translatesAutoresizingMaskIntoConstraints = false


.

.


.



 self.leftStackView.addArrangedSubview(item1)

        self.leftStackView.addArrangedSubview(img1)

        self.leftStackView.addArrangedSubview(item2)

        self.leftStackView.addArrangedSubview(item3)

'블로그 항해 일지 > !A. Basics' 카테고리의 다른 글

swift generic struct  (0) 2019.02.03
viewDidLoad()없는 뷰 제작시 사용하는 func name = entry  (0) 2019.01.27
UIStackView  (0) 2019.01.27
viewController 안에 viewController 넣기  (0) 2019.01.26
UIView 가장자리를 둥글게  (0) 2019.01.24
swiftdate  (0) 2019.01.24

Comment +0

view controller를 수용하는 것은 container view이다.


화면 구성을 자유롭게 하기 위해서는 single view controller에 다른 뷰를 넣는게 좋다.


splitView 즉, master-detail view 도 넣을 수 있다.


master detail view로 프로젝트를 생성하면 다음과 같이 app delegate에 들어간다.

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Override point for customization after application launch.

        let splitViewController = self.window!.rootViewController as! UISplitViewController //에러

        let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController

        navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem


        splitViewController.delegate = self


그러나 일반적으로 didFinishLaunchingWithOption 에는 return true 밖에 없다.


@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {


    var window: UIWindow?



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Override point for customization after application launch.

        return true

    }



해당 구문 중 필요한 부분을 새로 만드는 singleView controller에 넣어준다.



class MainViewController : UIViewController, UISplitViewControllerDelegate {

    

    @IBOutlet var splitContainer: UIView!

    

    


    override func viewDidLoad() { let splitViewController = self.splitContainer.window!.rootViewController as! UISplitViewController



.

.

.


IB에서 container view의 기존 embed viewcontroller를 지우고 split view를 

embed 로 넣어주면 잘 들어간다.


왠만하면 코드로 다 그려주면 stroyboard를 하나로 유지하면서 모든 view 를 속도 저하 없이 볼 수 있다.


'블로그 항해 일지 > !A. Basics' 카테고리의 다른 글

viewDidLoad()없는 뷰 제작시 사용하는 func name = entry  (0) 2019.01.27
UIStackView  (0) 2019.01.27
viewController 안에 viewController 넣기  (0) 2019.01.26
UIView 가장자리를 둥글게  (0) 2019.01.24
swiftdate  (0) 2019.01.24
[이전] 브런치 정리 중  (0) 2019.01.22

Comment +0

코너를 둥글게 하는 마법의 주문




        self.layer.cornerRadius = 10

        self.clipsToBounds = true

'블로그 항해 일지 > !A. Basics' 카테고리의 다른 글

UIStackView  (0) 2019.01.27
viewController 안에 viewController 넣기  (0) 2019.01.26
UIView 가장자리를 둥글게  (0) 2019.01.24
swiftdate  (0) 2019.01.24
[이전] 브런치 정리 중  (0) 2019.01.22
브로드 캐스트 구조 만들기  (0) 2019.01.21

Comment +0

https://github.com/malcommac/SwiftDate

http://malcommac.github.io/SwiftDate/manipulate_dates.html


Region(tz: TimeZoneName.europeRome, cal: CalendarName.gregorian, loc: LocaleName.italianItaly) 아님...


주의


- `CalendarName` is now `Calendars` and its conform to the new `CalendarConvertible` protocol. All parameters (like `Region` inits function) takes now a generic `CalendarConvertible ` instance: this mean you can pass one of the enum values of the


https://github.com/malcommac/SwiftDate/search?q=calendarname&unscoped_q=calendarname


Timezone은 Zones

CalendarName은 Calendars

LocaleName은 Locales로 변경됨.



let regionSeoul = Region(calendar: Calendars.gregorian, zone: Zones.asiaSeoul, locale: Locales.korean)


var modifiedDate = try! DateInRegion(year: dt.year, month: dt.month, day: dt.day, hour: 0, minute: 0, second: 0, nanosecond: 0, region: GS.s.regionSeoul)

Comment +0


저자의 말 

프로그래밍을 업(業)으로 하시는 분들 중 종이책을 사서 정독하는 분은 많지 않습니다. 책을 정독하더라도 같은 IT Field에서 근무하는 특성상, 사용자에게 좋지 않은 책조차 크게 비판하지 않는 관습이 있습니다. 이에, 어떤 책이 좋은 책인지 모르는 경우가 많습니다. 백 그라운드(학력, 경력)가 좋은 사람이 저자가 되는 것도 당연했습니다. 그로 인해 독자는 프로그래밍의 어려움을 오롯이 자신을 탓으로 돌리게 되었습니다. 그러나 이런 개발자 문화가 잘못되었음을 알고, 근래에는 저자의 백 그라운드 대신 작가의 관심 분야에 대해 알려주는 책이 많아졌습니다.

프로그래밍을 배우고자 하는 사람에게도 입문서가 필요합니다. 기초 서적에 관한 목마름은 멘토링, 세미나, 강의를 꾸준히 하면서 체감했습니다. 다른 개발자의 목소리도 많이 들었습니다. 그래서 새로운 시도를 해 보기로 했습니다. 각기 한 권씩의 분량으로 나와야 제대로 전달할 수 있는 여러 내용들을, 단권에 모두 담아보자는 시도입니다. 이제 막 프로그래밍을 업으로 시작하려는 단계에서 길을 찾는 책을 써보자는 시도이기도 합니다. 이 책을 쓰기 전 저희는 ‘개발자가 알아야 할 비화’를 먼저 출판했습니다. 그리고 ‘개발자가 알아야 할 비화’에서 글로 모든 것을 전달할 수 없다고 말했습니다. 책으로 전달할 수 있는 것과 없는 것은 분명히 존재합니다. 이에, 저자 및 지인들이 내용을 제대로 전달하기 위하여 인터넷(youtube) 무료 강의도 병행합니다. 카페를 통하여 모르는 부분에 대한 피드백을 남겨 주시면 해당 주제에 대하여 가장 적합한 강사가 강의를 진행하기로 했습니다. 거대한 지식 창고인 위키피디아에서 얻을 수 있는 소스보다 더 잘 짜기 힘든 부분은 인용하는 것으로 기획되었습니다. 굳이 책의 테두리로 지식을 묶기보다 애플(Apple)이라는 회사가 보여준 것처럼 더 좋은 것이 있고, 더 잘하는 사람이 있으면 과감하게 자신의 것을 버리는 판단을 하기로 했습니다. 동영상 강의도 마찬가지입니다. 비록 독자라 할지라도 더 뛰어난 설명을 하는 분이 계시면 그분의 강의를 차용하려는 시도도 책을 쓰기 전부터 기획되었습니다. 이런 시도 외에도 한자어를 병행하거나 여러 용어를 섞어 쓰기도 합니다. 난해한 용어 때문에 프로그래밍을 어려워하시는 분들께, 다양한 방향의 내용을 쉽게 보여드리기 위함입니다. 전체 용어를 개수를 따져보면 몇 개 되지 않기 때문입니다. 여러분은 두꺼운 책 한 권 분량에 나오는 한자 룰 어렵게 생각하기보다 도전을 하게 될 것입니다. 하나의 개념에서 다양하게 쓰이는 어려운 용어들이 대부분 쉬운 용어로 통합되는 시도를 보고 자신이 알게 된 용어들을 합치고 분리하는 능력을 가지게 될 것이라 생각됩니다.

 좋은 책은 독자들 사이에서 만들어진다고 생각합니다. 저자들은 프로그래밍 서적을 읽는 독자였습니다. 우리가 잘못 만들어진 프로그래밍의 인식에서 벗어나, 창의성을 잃지 않기를 바랍니다. 이에, 새로운 시도를 모아 한 권의 책에 담았습니다. 모든 코드 스타일은 이클립스 자바 버전 혹은 CPP 버전을 이용하여 자동 정렬하였습니다. 이 역시 이 책에서 하는 새로운 시도 중 하나로, 각 기업에서 수많은 시간을 투자해서 만든 수백 장 분량의 코드 스타일은 향 후 필요 없어질 것임을 명시적으로 선언하는 것이라 하겠습니다. 대부분의 IT 서적은 5년 이상 읽히기 힘듭니다. 이 책은 꾸준히 읽힐 수 있도록 계속해서 새롭게 쓰고 또 더 새로운 시도를 하려고 합니다. 양자 컴퓨터 이전의 모든 프로그래밍 언어를 하나로 묶는, 이 책에서만 볼 수 있는 불변의 개념인 OLPP(Object Linked Programming Paradign)만은 변화시키지 않으며 말입니다. 프로그래밍으로 힘들어하셨던 분이 이 책을 통하여 이루어질 많은 토론과 논의를 통해 자신만의 프로그래밍 노하우를 가질 수 있기를 바랍니다.

2017 年

저자 일동

Chapter 1. 프로그래밍(Programming)

프로그래밍은 무엇인지? 어떤 분야가 있는지? 무엇을 공부해야 할지? 살펴보는 빠른 방법을 먼저 알려 드립니다. 취미로 프로그래밍을 하는 것이 아닌, 취업을 위해 프로그래밍을 공부하는 독자는 입사를 원하는 회사에서 필요한 ‘기술 스택’을 공부해야 합니다. 사람인(www.saramin.co.kr)에서 기업을 검색하고 원하는 직무를 보며, 요구하는 기술 스택을 보면 됩니다. 대부분의 개발자, 프로그래머는 취미로 개발하기보다는 일로 삼아 보다 많은 시간을 코드와 함께 보내고자 합니다. 이에, 이 책에서는 원하는 기업의 기술 스택 모두를 다루지는 않지만 실무에서 개발자들끼리의 소통을 위하여 여러 분야를 다룹니다. 다양한 분야를 넓게 공부하다가 마음에 드는 분야가 있다면 스스로 깊은 공부를 하셨으면 합니다.

무조건 쉽다고 생각하자

철수는 남자다.

영희는 여자다.

처럼 참/거짓을 알 수 있는 것을 ‘명제’라고 합니다. 누구나가 "아!" 할 명제를 이야기하려고 하면 우리가 사는 세상에서 데이터를 모으고, 가공해서 정보를 만들어야 합니다. 해당 정보를 통하여 지식을 만들고, 해당 지식에서 진리, 정리, 법칙을 만들어 냅니다. 실세계에서는 인식, 인지를 통하여 데이터를 만듭니다. 해당 데이터에는 노이즈가 많이 있습니다. 데이터를 잘 정리하면 정보가 됩니다. 정제된 정보를 체계적으로 만들면 지식이 됩니다. 지식을 이론화하면 진리나 법칙이 됩니다. 데이터와 정보를 간단히 ‘정보’라고 한다면 정리, 진리, 법칙, 지식은 모두 ‘지식’이라고 할 수 있습니다. 컴퓨터 프로그래밍을 처음 접하는 사람들이 힘들어하는 이유와, 컴퓨터 프로그래밍을 가르치는 사람들이 하는 실수는 모두 같은 곳에서 출발합니다. 바로 데이터와 정보를 가르치기 전에 진리, 정리, 법칙 혹은 지식을 먼저 가르쳐야 한다는 것입니다. 이에 ‘프로그래밍은 CPU와 메모리의 장난’이라는 진리부터 말하고자 합니다.

IT 비전공자, 흔히 말하는 ‘문과생’의 경우 스스로 컴맹이라고 생각하는 사람들이 많이 있습니다. 그 상태에서 프로그래밍이라는 것을 배워보려고 하니 어려운 용어에 답답함을 느끼고 프로그래밍을 배우는 것을 포기하는 분도 많습니다. 그러나 이 책을 펼친 지금부터는 이 한 가지만 알고 시작하시면 됩니다. 

프로그래밍은 CPU와 MEMORY의 장난입니다. 

CPU는 노트북이나 개인용 컴퓨터를 살 때 들어 보았던, i3, i5, i7, AMD 等(등, 한자지만 특정 기호라고 간주하시면 됩니다. 앞으로 等이 나오면 그간 복잡하게 쓰였던 용어를 쉬운 용어로 통합하는 기호라고 생각하시면 되겠습니다.) 용어입니다. RISC, CISC, SDRAM, RDRAM 等의 용어는 모르지만 컴퓨터 살 때 CPU와 메모리를 들어 본 적이 있다면 자신 있게 말할 수 있습니다. 작은 책에서 주장했다는 이유 하나로 자신 있게 말하기 힘들어하시는 분을 위해 조금 더 설명해 보겠습니다. 프로그래밍을 CPU와 MEMORY의 장난으로 알고 시작하는 것은, 수영을 할 줄 모르지만 수영이 무엇인지 아는 것과 같습니다. 실재(實在)는 거짓·상상이 아닌 현실적으로 존재하는 것을 말합니다. 수영은 실재하지만 코드는 실재하지 않습니다. 게임 아이템의 경우 가상공간에 존재하기 때문에 현물이냐 아니냐에 대한 갑론을박이 있었을 정도입니다. 프로그래밍 코드 역시 그렇습니다. 하드 디스크가 저장소이니 하드디스크에 있는 것 같기는 한데 실재(實在)하는지 애매모호한 것입니다. 코드는 실재라기보다 있는 사실을 일컫는 말인 실제(實際)로 써야겠습니다. 프로그래머가 프로그래밍을 해서 나오는 산출물인 코드라는 것은 부팅 전에는 어딘가(하드 디스크)에 존재하고 실행이 되어 무언가(프로세스, process)가 된 이후, 반도체 어딘가의 저장소(플립플롭)에 저장되어 있겠습니다. 그러나 올림픽의 “수영”처럼 눈으로 확인하기는 힘듭니다. 그래서 실재보다는 실제가 더 이해하기 편합니다. 그러나 이 책이 끝날 즈음 여러분은 실제와 더불어 실재하는 코드를 머릿속에 떠올릴 수 있게 될 것입니다. 실재와 실제처럼 말장난같이 느껴지는 수많은 IT용어의 뿌리 용어를 알게 됩니다. 왜냐면 프로그래밍은 단순합니다. 수영선수가 여러 가지 영법으로 목표지점까지 물속을 헤엄치는 것과 똑같이 프로그래머가 다양한 프로그래밍 언어를 통해 CPU와 MEMORY로 장난을 치는 것뿐이기 때문입니다. 지금까지 보이지 않는 CPU와 MEMORY 내부를 두고, 정확하게 설명하는 사람이 있는 반면, 나름대로의 설명 방법으로 혼돈을 주는 사람도 많았습니다. 두괄식 글이 이해하기 쉽듯이, 

프로그래밍은 씨피유와 메모리를 조작하는 것뿐

이라는 진리를 알고 시작해 봅시다.

프로그래밍이 어려웠던 이유

지식에는 전문지식, 해당 필드에서 통하는 경험의 법칙, 그리고 메타 지식이 있습니다. 컴퓨터에서 메타 정보라고 함은 흔히 정보를 제공하는 파일 자체의 정보를 말합니다. 이미지 파일의 EXIF가 좋은 예라고 할 수 있습니다. 우리가 타인에게 제공하려는 지식 자체에 대한 추가 지식. 즉, 메타 지식을 제공하면 다음과 같은 이점이 있습니다.

 - 프로그래밍이 쉬워집니다.

 - 프로그래밍이 재미있어집니다.

그래서 어떤 지식을 설명한 후에 그것의 이해를 돕기 위한 예를 충분히 제시하고자 합니다. 실체를 알기 위해서는 여러 관점으로 설명을 해야 하기 때문입니다. 장님이 코끼리 코만 만져보고 뱀이라고 말하는 동화 속 이야기처럼 되지는 말아야 합니다.

프로그래밍을 재미없게 만드는 가장 큰 요소로는 라이선스가 있습니다. 무엇이든 업(業)으로 하게 되면 재미가 없어집니다. 이는 통계적으로 많은 사람들이 동의하는 경험적 지식입니다. 만약 돈을 벌기 위해 프로그래밍을 한다거나 회사에서 시켜서 혹은 어쩔 수 없는 일로 해야 하는 프로그래밍은 재미가 없기 마련입니다. 또, 재미가 없으면 책을 끝까지 읽기도 힘듭니다. 프로그래밍은 발명, 공부, 수학, 놀이 등 여러 가지 개념이 복합적으로 합쳐진 용어입니다. 그리고 이 용어를 구성하는 하나하나의 개념들은 지난 역사상 많은 위인들이 업으로 삼으면서도 재미를 느꼈던 분야입니다. 재미를 알려드리기 위해 GPL(General Public License)를 제창한 FSF(Free Software Foundation)에 대해서 간단히 소개드리겠습니다. 다른 사람이 만든 소스를 보고, 또 자신이 만든 것을 오픈하는 라이선스와 문화를 이끄는 단체입니다. 리눅스라는 커널/운영체제도  그렇게 출발했고, 이제는 세계 TOP 100 슈퍼컴퓨터 대부분이 리눅스를 사용합니다. 한 가지 아쉬운 것은 국가에서 말하는 오픈소스와 LINUX FOUNDATION이라는 단체가 하고 있는 오픈소스와 프로그래밍은 사실 ‘재미’와는 매우 거리가 멉니다. 돈을 벌기 위해 복잡한 라이선스 관계를 알고 자신에게 유리하게 이용하며, 또 최종 목적인 자신의 이익을 채우는 구조로 되어있기 때문입니다. 이런 복잡함을 고려하기 전, 먼저 "프로그래밍은 CPU와 MEMORY의 장난"이라는 진리로 진정한 프로그래밍의 재미를 느꼈으면 합니다. 다만, 가장 효과적인 [웹서핑 공부법]을 추가적으로 이용할 때 기본 지식은 필요합니다. 어떤 것이 재미있는 것이고, 어떤 사람이 재미를 추구하는 사람이며 단체인지 구분할 변별력이 필요합니다. 초심자는 이런 변별력을 가지기가 힘들었기 때문에 프로그래밍이 재미가 없었고, 또 재미가 없으니 어려웠던 것입니다. 프로그래밍 세계에서 자유를 뜻하는 용어인 FSF, GNU, GPL 은 꼭 알아 두시기 바랍니다. 약어 풀이를 알 필요는 없습니다. 재미의 가장 큰 전제조건인 자유를 뜻한다고만 알면 됩니다. 

 웹서핑 공부법

요즘 책을 사서 보는 사람은 점점 줄어드는 추세입니다. 그 이유는 인터넷이라는 좋은 공부 방이 있기 때문입니다. 정보의 바다로 불리는 인터넷의 등장으로 정보를 저장하는 책의 역할은 인터넷이라는 커다란 바다를 항해할 수 있는 나침반의 역할로 바뀌어야 합니다. ‘Surfing the Internet’이란 용어가 20년 이상 사용되었지만 인터넷을 어떻게 이용하는지에 대해 명확히 모르고 사용하는 것에 대해서 아쉬움이 있었습니다. 그래서 소개하려고 하는 검색 방식이 바로 “구글링”입니다. 구글링은 google.com을 통해서 원하는 검색 키워드를 입력하고 검색하는 것을 말합니다. 매우 간단합니다. 수년 전에는 naver, lycos, yahoo, google, daum 等 다양한 검색 매체를 이용해서 나오는 검색 결과가 모두 조금씩 달랐습니다. 검색 엔진의 검색 범위가 넓어지면서 구글에서 해당 포털 사이트의 내용까지 검색이 되었습니다. 이에 각 기업이 자신의 콘텐츠가 무단으로 이용되는데 불만을 토로했고, 국제적 규약은 없지만 http://www.robotstxt.org/ 를 통해 검색이 되지 않도록 권고하고 있습니다. 간단히 말하면 google에서 제공하는 robot.txt 파일 내부의 태그(명령어)를 이용하면 검색되지 않도록 막을 수 있게 했습니다. 물론, 이 부분도 해외 사업을 하려면 구글을 이용해서 광고해야 하는데 국내 사업의 경우 자사 콘텐츠를 보호해야 하므로 ‘고무줄 법’ 정도로 보면 되겠습니다. 논란의 여지가 있기에 화사첨족이 많았으나 결론만 말하면 

구글링을 통해 원하는 내용을 검색하면 됩니다. 

구글 검색 방법에서 추천하는 방법은 두 가지입니다. filetype: , site:입니다. 제외시키는 - 키워드,  유사 어휘를 찾는 ~ 키워드, 범위를 지정하는 range 방법 等 여러 가지가 있으나 구글이 알아서 필요 없는 것을 제외하고 사람들이 원하는 것을 가져오도록 잘 만들어져 있습니다. 심지어 철자가 틀린 경우에도 유사 어휘로 검색을 해줍니다. 다만, 퀄리티 있는 자료 검색은 쉽지 않기에 실무에서는 DBPIA를 이용하여 논문을 검색하고 해당 논문을 구현하거나 구글링의 filetype:ppt, filetype:pdf, site:aplle.com 等 추가 기능을 이용합니다. 가령 이 책에서 설명하는 쉘 프로그래밍을 보고 싶다면, 크롬 브라우저 구글 검색 주소창(Ctrl+L)에 다음과 같이 타이핑을 하시면 됩니다. 

그러면 책 한 권 분량의 PDF 문서를 찾을 수 있습니다.

영어가 부담스럽다면 “도구-모든 언어-한국어 웹”을 이용하면 됩니다.

다만 영문 자료가 더 이해하기 쉬울 때가 많습니다. 뜻보다는 소리를 표현하는데 특화되어 있는 한글의 특성상 영어와 1:1로 매칭이 이루어지지 않아 개념 이해에 한계가 있습니다. 국내 서적의 경우 해외자료를 소화해서 작성된 자료가 많기 때문에 의역이나 오역으로 인해 원서의 의도와는 전혀 다른 방향으로 해석될 수도 있습니다.

Data Structure나 Algorithm 등 컴퓨터 관련 공부를 원서로 공부한 대학생이 나중에 국문 서적을 보고 오히려 원서가 더 이해하기 쉬웠다는 말을 했습니다. [웹서핑 공부법]은 웹서핑을 위한 서핑 방법이지, 바다나 파도 자체가 아닙니다. 올바른 검색을 위해서는 키워드를 분명히 알고 있어야 합니다. 구글에서 1592를 치면 임진왜란이 검색되고, 구글 이미지 검색에서 1932 4 29로 검색하면 윤봉길 의사가 나오는 것과 같은 이치입니다. 아는 것이 많을수록 더 많은 자료를 찾을 수 있습니다. 독자께서는 최소한의 지식을 쉽게 설명하고 웹이라는 거대한 바닷속에서 등대, 지도, 나침반 역할을 하는데 이 책을 잘 이용하셨으면 합니다. 한번 길을 찾고 나면 지도나 나침반은 큰 필요성을 느끼기 힘듭니다. 또한 초행길에 대한 어려움은 작가보다 초행길로 목적지에 온 사람의 첫 기억이 가장 정확합니다. 잘못된 부분이 있다면 다음에 올 초행자들을 위해 더 도움이 될 수 있도록, 언제든 ‘지앤선’ 출판사를 통해 제보 바랍니다. 더 나은 책이 될 수 있도록 도움을 주셨으면 합니다.

프로그래밍 경험이 있는 독자에게

1847년 George Boole 이 만든 개념이 프로그래밍에 적용되었습니다. boolean, bool, 이진트리, 퀵 소트 등 프로그래밍 패러다임에 큰 영향을 끼쳤습니다. 컴퓨터의 사고 과정을 배우는 것이 프로그래밍이라면 이분법적으로 생각하는 것은 매우 효율적입니다. CPU 역시 0과 1을 이용해 연산을 합니다. 그런데 조금 의문점이 듭니다. 우리가 생각하는 자료형도 컴퓨터는 이해하지 못하고 메모리 상에서는 모두 구조화되지 않은 채 바이트 단위로 저장됩니다.  통짜 프로그램(한 사람이 모든 파트를 만드는 것)을 만들 수 없기 때문에 모듈을 나누고 나누어진 모듈이 각기 다른 프로그래밍 언어로 만들어지기도 합니다. IPC, pipe, shared memory, COM, TCP/IP, NDK, AIDL 等 각종 프로토콜이 모듈 간의 인터페이스를 말합니다. 이렇게 모듈을 나누다 보니 만드는 사람도 나누어져 있고, 악의로 데이터의 무결성을 파괴하거나 시스템을 붕괴시켜 자신을 이익을 채우는 사람도 있습니다. 추가로 이익 관계나 이해관계에 의해서 나누어진 모듈 간의 보안도 필요하게 되었습니다. 0과 1에서 출발했지만 수없이 추상화되는 이 복잡함 속에서 굳이 0과 1의 시온으로 갈 필요가 있을까요? 그러다 보면 응용 프로그램 개발자는 프레임웍을 거쳐 운영체제, 커널, 스케줄러, SoC 프로그래밍, FPGA(비용 때문에)로 내려가다 결국 전기이론까지 공부를 해야 하고 우리의 머리가 대동소이한 이상 모든 분야를 다할 수는 없습니다. 수영선수 펠프스 같은 명성을 획득하기는 어려운 것이 IT는 명확한 하나의 분야가 아니기 때문입니다. IT 천재라는 말은 없습니다. 왜냐면 펠프스가 수영도, 육상도, 체조도 우승하는 것과 같은 말이기 때문입니다. 그래서 각 분야가 통합되기 힘들어 공통된 진리를 말하기 정말 힘듭니다. 이 와중에 머리 아픔을 해결해 줄 수  있는 유일한 진리가 있다면, ‘프로그래밍은 CPU와 MEMORY의 장난’이라는 것입니다. JVM위에 도는 자바만 해도 메모리에 직접 액세스 할 일이 없고, 웹 프로그래머는 프레임웍 상단인 웹 브라우저에서 동작하는 모듈을 만들기에 더더욱 메모리에 접근하지 않습니다. 그러나 해당 프로그래머도 항상 메모리를 걱정합니다. 다루는 데이터가 너무 커서 overflow가 나진 않을지, 플레이하는 동영상이 너무 크지는 않은지 말입니다. 포인터가 없다는 자바도 결국 null pointer exception이라는 것이 있습니다. SoC의 경우 Memory mapped I/O를 구현하기 전에는 메모리가 있다고 할 수도 없습니다. 상위 인터페이스를 제공하기 위해서는 결국 메모리를 매핑해 주어야 합니다.

프로그래밍을 배우려는 사람에게 우선 진리를 말해주고 지식을 주고, 정보를 주고 경험도 주어야 한다고 생각합니다. 그래야 어렵다고 느끼지 않을 수 있습니다. 경험 많은 프로그래머에게도 수없이 바뀌는 API나 프레임웍, 트렌드들이 그리 녹녹지만은 않기 때문입니다. 데이터가 정보가 되고 지식이 되고 진리가 되는 과정에서 즐거운 점이 있다면 머릿속에 넣어야 할 양이 기하급수적으로 줄어든다는 것입니다.

프로그래밍은 CPU와 메모리의 장난입니다. 

프로그래밍 개념 잡기

“코딩이 뭔지 잘 모르겠어요? 배열, 포인터는 어떤 것인가요?”

처음 프로그래밍을 접하시는 분은 생소한 용어를 가장 어렵다고 느낍니다. 프로그래밍을 배워 보려고 하면 많은 개발자들이 전부 인터넷에 있다고 합니다. 또, 책을 보라고 합니다. 또 다른 문제는 용어도 모르지만 어떤 것부터 시작을 해야 할지 모르는 경우가 많습니다. 일반적으로 초등학생이 수학 공부를 하고 싶다고 물었는데, 인터넷에 다 있다고 하는 것과 다를 바 없습니다. 책을 보면 된다고 하는데 어떤 책을 골라야 할지 모르는 상태에서는 선택도 쉽지 않습니다. 단순히 제목만 보고 고교 수학책을 선택할 수도 있습니다. 이미 필드에서 일하고 있는 엔지니어도 전체 숲을 보지 못한 체 공부를 하다 보니 유기적으로 결합된 지식을 얻기가 상당히 힘듭니다. 

IT 비(非) 전공자의 “프로그래밍이 뭔가요?”라는 물음에 우리는 “프로그래밍은 책 만들기입니다.” 라고 답을 합니다. 사람은 의사소통할 때 말과 글을 이용합니다. 즉, 언어로 소통을 합니다. 사람이 컴퓨터에 명령을 내릴 때도 마찬가지로 언어가 필요합니다. 이때 쓰이는 언어가 JAVA, C, C++ 과 같이 불리는 프로그래밍 언어입니다.

글은 문장으로 이루어져 있고, 문장은 단어로 이루어져 있습니다. 그리고 단어는 알파벳이나 한글 같은 글자들의 조합으로 만들어집니다. 단어는 언어를 사용하는 집단에서 특정 대상을 가리키기 위해서 암묵적, 또는 공개적으로 정한 약속과 같은 것입니다. 컴퓨터 언어도 마찬가지입니다. 컴퓨터 언어의 단어들은 소스 코드들이 모여서 만들어집니다. 그리고 이미 만들어져 있는 단어들을 API(Application Programming Interface)라고 합니다. 이런 단어들을 가져다 쓰기도 하고, 직접 만들기도 하면서 사용자가 컴퓨터에 시키고자 하는 명령 문장을 만드는 것을 코딩이라고 합니다. 코딩된 명령 문장들이 모여 프로그램을 만들어가는 과정을 프로그래밍이라고 합니다. 

글자 = (source)code

단어 = API

언어 = 프로그램 언어(JAVA, C, C++, 어셈블리어)

글쓰기 = 코딩(code를 키보드로 타이핑 하기)

책 만들기 = 프로그래밍(프로그램 만들기)

책 = 프로그램

좋은 작가가 쓴 글은 문장의 중복이 없고, 문체가 간결해서 군더더기 없이 쉽게 읽힙니다. 좋은 프로그래머가 만든 프로그램도 이와 같습니다. 잘 만들어진 소스 코드는 이해하기 쉽고 간결하게 짜여 같은 프로그래머가 보더라도 읽기 편합니다. 이런 코드를 가독성이 좋은 코드라고 합니다. 

프로그래밍 영역에는 ‘백문이 불여일견’이라는 말과 비슷하게, ‘백문이 불여일타’라는 말이 있습니다. 소스 코드만 계속 본다고 해서 본인의 코딩 실력이 늘지는 않습니다. 손으로 직접 코드를 쳐봐야 프로그래밍 실력이 늘기 마련입니다. 프로그래밍을 할 때 가장 먼저 하는 일은 개발 환경을 구축하는 일입니다. 책에서 설명하는 개발 환경은 시간이 지나면 금방 업데이트가 되어 구버전이 되어 버립니다. 따라서 개발 환경을 구축하지 않고 우리가 사용하는 Windows에 프로그래밍을 해 보겠습니다. 개발 환경을 구축하다 실패했을 때, 학원이라면 선생님께서 친절하게 가르쳐 주시겠지만, 책의 경우 한번 안되면 포기해 버리는 경우가 허다합니다. 쉘 프로그래밍을 하며 얻은 자신감으로 이후 겪게 될 수많은 버그(프로그램 오류)를 견뎌낼 수 있는 티타늄 멘탈을 얻으시길 바랍니다

사람이 만드는 프로그램 중에 버그 없는 프로그램은 없습니다.

전 세계의 우수한 프로그래머들이 만든 모든 프로그램에도 버그는 있습니다. 사람이 프로그램을 만드는 이상 버그가 없을 수 없습니다. 모든 상황을 고려해서 프로그램을 만든다면 버그가 없을 수 있겠지만, 사람은 모든 상황을 고려할 수 없습니다.

쉘(shell) 프로그래밍

‘백문이 불여일타'를 실천하기 위해 먼저 쉘(shell) 프로그래밍 실습을 해보려고 합니다.

쉘은 사용자가 내린 명령을 읽고 번역해서 커널에 전해주는 명령어 통역기입니다.  컴퓨터를 켜면 나오는 바탕 화면을 GUI 쉘(Graphic User Interface Shell)라고 합니다. 실행창에서 CMD 명령어를 쳐서 나오는 까만 화면의 창 또한 CUI 쉘(Character User Interface Shell)이라고 합니다. 초기에는 Windows에도 명령어 입력만 가능한 쉘이 있었지만, 사용자의 편의를 위해서 도입된 GUI Shell이 발전해 지금의 단계에 이르렀습니다. 현재는  부팅 시에 GUI Shell이 바로 실행이 되도록 하고 있습니다. GUI가 있는 어느 운영체제(Windows, Linux, MacOS)에도 쉘은 내장되어 있습니다. GUI 형태가 나오기 전에 쉘이 먼저 있었던 것도 이유겠으나, 커널에 명령을 내리는 가장 기본적인 프로그램이 쉘이기 때문입니다.

 데스크톱 운영체제 분야에서 가장 시장 점유율이 높은 Windows를 중심으로 실습 과정을 진행하면서 설명해 보겠습니다. 쉘 프로그래밍은 다른 프로그래밍 언어와는 달리 설치 과정이 필요 없습니다. 운영체제에 기본 내용된 유틸리티(유용한 프로그램)이기 때문입니다. 이에, 바로 실습해보기 적합한 프로그래밍 도구라는 장점이 있습니다.

컴퓨터에 명령어를 입력하기 위해서는 먼저, 명령어를 입력할 cmd 창을 띄워야 합니다. 키보드의 Windows key

와 R을 동시에 눌러봅시다. Windows key는 데스크톱 키보드를 기준, 가장 긴 Space Bar 근처 Alt 라고 쓰인 key의 옆에 위치하고 있습니다.


위의 창을 실행 창이라고 합니다. cmd를 입력하면 다음과 같은 cmd.exe 창이 뜹니다. 

이 창을 명령 프롬프트, 또는 도스 창이라고 부릅니다. 앞으로 진행될 실습에서는 이 실행 창을 ‘cmd 창’이라는 용어로 표기할 예정입니다. 여기에 기본 명령어를 코딩(글쓰기) 해보겠습니다. 기본 명령어로는 다음과 같은 것들이 있습니다.


cls 화면 지우기

dir 디렉터리 보기

 cd 디렉터리 바꾸기

md 디렉터리 생성

 rd 디렉터리 지우기

explorer . 현재 디렉터리 기준으로 탐색기 실행

위에 있는 명령어들을 이용해서 간단한 프로그래밍을 해봅시다. 처음 입력해볼 명령어는 dir(디렉터리, directory의 약어)입니다. dir은 현재 위치에 어떤 파일이나 디렉터리(폴더)가 있는지 보여주는 명령어입니다. 지금 우리가 사용하고 있는 cmd 창은 CUI(Command-line User Interface 혹은 Character User Interface 문자 사용자 인터페이스), 다시 말해 텍스트(글자) 기반의 사용 환경입니다. cmd 창에서는 내가 원하는 위치의 폴더로 들어가기 위해서 마우스를 이용할 수 없습니다. 글자로만 이루어진 cmd 창에서 위치 또한 글자로 파악해야 하기 때문에 명령어가 필요한 것입니다. 디렉터리나 폴더는 저장소의 방이라고 생각하시면 됩니다. 개미집에도 여러 방이 있듯 저장소에서도 여러 개의 방을 만들어 사용할 수 있습니다. 이미 IT 기기를 많이 쓰는 분들께는 생소한 용어가 아닙니다.

dir을 입력하면 사용자가 있는 장소인 C:\Users\SORASOFT 폴더 안의 파일과 그 정보들이 나타납니다. 

SORASOFT는 유저 이름으로 사용자 이름에 따라 다르게 나타납니다. 유저 이름이 ’철수'라면 C:\Users\철수 로 나타나게 됩니다. 유저 이름이 ’영희'라면 C:\Users\영희 로 나타나게 됩니다.


이번에는 폴더를 한번 만들어 보겠습니다. [md 폴더명]을 타이핑한 다음 Enter key를 치면 폴더가 생성됩니다. ‘실습’이라는 이름의 폴더를 만들었습니다.

폴더가 실제로 만들어졌는지 확인하기 위해 방금 전 해봤던 dir 명령어를 다시 입력해 보겠습니다.

[실습]이라는 폴더가 만들어진 것을 확인했습니다. cmd 창을 이용해서 컴퓨터에 명령을 내려 봤으니, cmd 창에서 명령한 내용이 실제로 컴퓨터에 적용되었는지 확인해 봅시다.

 cmd 창에 파일 탐색기를 통해서 현재의 디렉터리를 볼 수 있는 [explorer]라는 명령어를 입력해줍니다. [explorer .]이라고 타이핑하면 지금 사용자가 있는 디렉터리가 화면에 나옵니다. 코딩에서는 띄어쓰기가 중요한 만큼, 반드시 explorer를 타이핑 한 다음 한 칸을 띄우고 .을 찍어야 합니다.

새로운 윈도우에서 조금 전 cmd 창에서 만든 폴더가 생성된 것을 확인할 수 있습니다. 

 [rd 폴더명]을 입력하면 생성했던 폴더, 혹은 기존에 존재했던 폴더가 삭제됩니다. 

추가로 삭제하고자 하는 폴더에 파일과 하위폴더가 있을(비어있지 않은) 경우에는 /S 옵션을 이용하여 [rd /S 폴더명]을 입력하면 ‘폴더명, 계속하시겠습니까?<Y/N>‘ 이 화면에 출력됩니다.

이때, ‘Y’를 누를 경우 폴더 안의 파일과 하위폴더가 모두 삭제되며,  ‘N’을 누를 경우 명령어가 취소됩니다. 삭제를 하게되면 복구가 되지 않으므로 주의하여야 합니다. 

명령어 뒤에 /? 를 입력하면, 해당 명령어와 함께 사용가능한 옵션이 출력 됩니다.

쉘에서 명령어를 타이핑하는 것도 코딩입니다. 앞으로는 다양한 플랫폼의 적응을 위해, cmd 창도 ‘쉘’ 또는 ‘셸' 또는 ‘shell’ 이라는 용어로 통일하도록 하겠습니다. 하나의 대상을 두고 다양한 용어로 쓰는 방식은  서적과 인터넷에서 매우 빈번히 쓰입니다. 병원에서 의료진들이 쓰는 복잡한 용어처럼 대상을 명확히 구분하기 위해 쓰기도 합니다. 대부분은 외래어이기 때문에 개발자 내공이 쌓이면 다양한 용어로 혼돈이 없도록 직접, 영문 서적을 읽게 됩니다. 태권도의 종주국인 우리나라의 용어를 그대로 해외에서 쓰듯이 shell 역시 영문 그대로 shell이라고 쓰는 것이 옳은 표현입니다. 다만 용어에 익숙하지 못한 독자분들을 위해 ’폴더', ‘디렉터리', ‘folder’, ‘directory’ 혹은 ’쉘’, ‘셸', ‘shell’ 처럼 혼용해서 용어를 사용합니다. 마지막 챕터에서 이렇게 혼용해서 쓴 용어를 모두 정리합니다.

기본적인 명령어와 입력 방법을 익혔으니 쉘에 다음 명령을 코딩해 봅시다. 띄어쓰기는 매우 중요한 부분입니다. 더욱 주의하며 실습 해봅시다.                    

for %i in (1, 2, 3, 4, 5, 6, 7, 8) do md 새폴더%i


User 폴더에 새폴더1부터 새폴더8까지의 이름을 가진 8개의 폴더가 생성되었습니다.

 [explorer .]을 이용하여 User 폴더에서 새폴더를 직접 확인할 수 있습니다. 더불어 dir 명령어로 cmd 창에서 확인할 수도 있습니다. 

md가 폴더를 만드는 명령어였던 것처럼 다른 명령어에도 각기 역할이 있습니다. for는 문장을 반복하게 하고, i는 변수라고 불리며 데이터를 담아주는(저장하는) 일종의 그릇의 역할을 합니다. i 안에 괄호 안의 숫자들을 넣은 폴더가 생기는 것입니다. i가 변수라는 것을 표현하기 위해 앞에 %를 붙여줍니다. 가령 다음과 같은 명령문이 있다면,                    

for %i in (1, 2, 3, 4, 5, 6, 7, 8) do md 새폴더%i

〈반복해서[for] i라는 변수에[i] 1, 2, 3, 4, 5, 6, 7, 8의 숫자를 넣어서[in (1, 2, 3, 4, 5, 6, 7, 8)]  새폴더 i 이름의[새폴더 i] 폴더를 만들어라[do md]〉고 해석할 수 있습니다. 한 문장으로 쓰면 복잡하지만,

for (반복하세요)

%i (i 변수를 이용하세요)

in (값을 넣으세요)

(1, 2, 3, 4, 5, 6, 7, 8) (1~8까지 값을 넣으세요)

do (특정 작업을 하세요)

md 새폴더%i (새폴더+변수i 의 이름을 가지는 폴더를 생성하세요)

로 하나하나 풀이하면 이해하기 쉽습니다.

이제  9에서 20까지의 새 폴더를 만들어 봅시다.

                     

for /L %i in (9, 1, 20) do md 새폴더%i

for와 i 값은 그대로 넣되 /L이라는 옵션이 등장했습니다. 소괄호 안에 입력한 값도 이전의 코딩과는 다른 구조로 되어 있습니다(이 구문에서 소괄호 안의 값은 띄어쓰기하여도, 하지 않아도 같은 결과가 나옵니다).

/L 옵션을 이용하여 소괄호에 입력하는 값을 (시작 값,증감치, 종료값)으로 FOR 반복문 인자를 바꾸었습니다. 옵션을 이용하여 일정한 규칙에 따라 반복되는 값을 입력하는 수고를 줄인 것입니다.


지금까지 폴더를 만들어보았습니다. 새폴더를 만드는 실습에서 우리는 새폴더1부터 새폴더20까지, 스무 개의 폴더를 만들었습니다. 실습을 위해 만들었던 폴더를 삭제하고 싶다면, 위에서 입력해본 명령어와 구문을 응용할 수도 있습니다.

시작 값을 1로 두고 종단(종료) 값을 20으로 둔 뒤, 증감치를 1로 설정해줍니다. 폴더를 만드는 대신 이번엔 폴더를 삭제하는 명령어를 넣어 줍시다.

                     

for /L %i in (1, 1, 20) do rd 새폴더%i

User에서 결과물을 확인해봅시다!

명령어를 입력하여 작업하는 쉘 프로그래밍에서는 띄어쓰기나 점으로 명령하는 내용이 완전히 뒤바뀌는 때도 있습니다. 방금 입력해보았던 [cd](change directory)와 [explorer] 명령어를 예로 설명해보겠습니다.

[cd]는 현재 위치하고 있는 디렉터리에서 다른 디렉터리로 위치를 바꾸어주는 명령어입니다. cmd 창에서 ‘.’은 현재 폴더를, ‘..’은 상위 폴더 즉 한 단계 위의 폴더를 뜻합니다. 이 명령 단위들을 조합해 입력해봅시다.

‘.’이 하나일 경우에는 위치가 C:\Users\SORASOFT 그대로이지만 ‘..’을 사용하자 C:\Users\SORASOFT에서 상위 디렉터리인 C:\User로 바뀌었습니다. 한 번 더 사용하니 C:\ 최상위 디렉터리로 이동된 것을 확인할 수 있습니다. [cd] 명령어로는 cmd 창에서의 디렉터리가 바뀌는 것만을 확인할 수 있지만, [explorer]를 이용하면 좀 더 쉽게 눈으로 상위 폴더로 이동하는 것을 볼 수 있습니다. 똑같은 방법으로 [explorer]를 입력해봅시다.

‘.’이 하나 일 때는 C의 Users의 user 폴더 창이 뜨게 되고, ‘..’ 점이 두 개 일 때는 C의 Users 폴더 창이 뜨는 것을 확인하실 수 있습니다.

이것으로 아주 기초적인 코딩을 마쳤습니다. 이렇게 쉘에서 코딩을 해서 프로그래밍하는 것을 쉘 프로그래밍이라고 합니다. [explorer]로 간단히 실행할 수 있었던 탐색기의 모든 기능을 만들기 위해서는 고급 개발자가 한 달 이상 투자를 해야 합니다. 버그를 잡기 위해서는 또다시 한 달 이상의 시간을 투자해야 합니다. 사용자에게 베타 테스팅을 하고 시장에서 검증 받으려면 추가로 많은 돈과 시간이 들어갑니다. 그렇지 않았다면 누구나 TOTAL COMMAND와 같이 수십 억원(76억원 추정)의 수익을 올리는 탐색기를 만들 수 있었을 것입니다.

상황에 따라 최적의 솔루션을 만드는 데에는 쉘 프로그래밍만 한 것이 없습니다. 가령 [shutdown –s –t 3,600]을 입력한다면, 여러분은 1시간(3600초) 뒤에 컴퓨터가 자동으로 꺼지도록 할 수 있습니다. 물론 [shutdown –a]로 명령을 취소하는 것도 가능합니다.

지금까지 해온 일련의 과정을 바로 쉘 프로그래밍이라고 합니다. 혹은 Shell script coding이라고도 합니다. 이런 작업을 “프로그래밍하다”, “코딩을 하다”로 표현하며, 작업을 이루어내는 사람을 “프로그래머”나 “코더”라고 부르는 것입니다.

Chapter 2. 쉘 프로그래밍을 넘어서...

앞에서 우리는 쉘(shell)프로그래밍을 했습니다. 이번 장에서는 C와 JAVA를 통한 본격적인 프로그래밍을 해 보려고 합니다. 단, 쉽게 알려진 방식(IDE 이용)으로 시작하지 않으니 모르는 부분은 추가 학습과 카페(plandosee.org)에 질문을 통하여 확실히 알고 넘어갔으면 합니다.

Visual Studio 설치 (C/C++)

과거 컴파일러를 가장 잘 만들었던 업체는 Boralnd 社였습니다. 덴마크 회사였던 Boralnd는 Turbo C++, Borland C 나 builder 등의 제품을 생산했습니다. 그러나 개발 툴(tool)의 기술력보다 중요한 것은, 개발 툴인 컴파일러가 ‘어디서 실행되느냐‘는 것입니다. 컴파일러는 Windows용, 리눅스 용, 애플맥 용 등 플랫폼에 따라 컴파일러 프로그램이 따로 존재합니다. Boralnd 社의 제품이 더 좋았음에도 불구하고, Microsoft 社의 Windows와 같은 회사에서 나온 C 컴파일러인 Visual Studio가 여러 개발 툴들을 물리칠 수 있었던 이유가 그 때문입니다. 다수의 사용자를 가지고 있는 Windows용 프로그램을 만들기 위해서는 Visual Studio를 사용해야 하고, 따라서 책에서도  Windows용 프로그램의 실습을 위해 Visual Studio를 설치하고자 합니다. 본래 유료였던 Visual Studio는 Express Version에서 Community Version이라고 하는 무료 버전 또한 존재하게 되었습니다. 이에, Community Version을 설치하여 C/C++ 프로그래밍을 경험해보겠습니다. 지금부터는 운영체제가 Windows라는 전제하에 Visual Studio 2015 community version을 설치해봅시다.

0. 컴퓨터의 용량을 확인하자

비주얼 스튜디오는 약 11GB의 공간이 있어야 합니다. 용량 부족으로 설치 도중 오류가 뜨지 않도록, 사전에 Visual Studio를 설치할 공간을 마련해야 합니다.

Windows key와 E key를 동시에 누르면 컴퓨터(내 PC)에서 사용 가능한 용량을 확인할 수 있습니다. 설치하고자 하는 로컬 디스크(C; , C 드라이브)의 용량이 86GB 남았으니 충분히 설치가 가능합니다.

1. 프로그램 다운받기

주소창에 https://www.visualstudio.com/를 입력합니다.

‘모든 개발자 및 모든 앱을 위한 도구’라는 설명과 함께 다운로드 창이 뜹니다. 다운로드 종류 중 가장 처음 나오는 Community 2015 다운로드를 클릭하면 설치가 시작됩니다.

2. 설치 유형과 기능 선택

설치 위치는 기본적으로 C 드라이브의 Program File로 지정됩니다. 필자의 컴퓨터에서는 기본적으로 잡힌 설치 위치가 C:\Program Files (x86)\Microsoft Visual Studio 14.0 으로 설정되었습니다.  

설치 위치를 변경하고 싶을 경우, 

표시 아이콘을 눌러서 원하시는 위치를 지정하시면 됩니다.

설치 유형은 기본값과 사용자 지정 설치 두 가지로 나뉩니다. 대부분의 Visual Studio 설치 관련 글에서는 사용자 지정 설치를 권하고 있습니다. 사용자 지정 설치의 경우 인스톨 패키지를 지정할 수 있는 특징이 있습니다. 책에서도 사용자 지정 설치를 해보도록 하겠습니다.

사용자 지정 설치를 선택한 관계로, 우리는 다음 단계에서 프로그램의 설치를 위해 필요한 기능을 선택해야 합니다. 상단에 있는 [프로그래밍 언어]를 열어봅시다. [⦊버튼 클릭]

이 책에서 Visual Studio를 설치하는 목적은 C/C++ 프로그래밍을 하기 위해서 입니다. [프로그래밍 언어] 항목에서 Visual C++ 항목에 [모두 선택]을 해줍니다. 오른쪽 아래의 [다음] 버튼을 누르면 선택한 기능을 확인하는 창이 뜹니다. 확인 후 설치(I)를 클릭합니다. 

위 화면이 뜸과 동시에 설치가 완료되었습니다. 프로그램이 정상적으로 작동하는지 확인하기 위해서, 재부팅 후 Visual Studio 2015를 시작해 보도록 하겠습니다.

2-1. 2015 언어 팩 추가 설치

사용자 인터페이스에 표시되는 언어를 한국어로 전환해 줌으로써 좀 더 쉽게 이해할 수 있습니다.

3. 프로그램 열기

시작 프로그램에서 Visual Studio 2015를 열면 로그인 창이 뜹니다. [나중에 로그인]을 눌러도 서비스를 이용할 수 있지만, 설치 후 30일 이후부터는 등록을 해야 계속 Visual Studio 2015를 사용할 수 있습니다. 로그인은 Microsoft 계정으로 하며 메일 주소나 전화번호로 계정을 만들 수 있습니다.

로그인 화면을 넘기면 환경 설정을 해야 합니다. 개발 설정은 일반으로 고정되어 있습니다. 색 테마를 고르고 Visual Studio 시작(S)을 클릭하면 시스템 설정이 완료됩니다.

번외. 생길지도 모를 오류

Visual Studio 2015를 설치하는 도중, 다음과 같은 안내창이 뜨면서 설치가 자동으로 이루어지지 않는 경우가 있습니다. 이 경우 [인터넷에서 패키지 다운로드]를 선택해줍니다. 패키지는 팝업 창의 지시에 따라 쉽게 다운 받을 수 있으며, 이후 자동으로 설치가 계속 진행됩니다.

설치 패키지 오류가 나면 인터넷에 위 화면이 뜹니다. 설치가 완료되거나 패키지를 다운 받으면서 [확인]을 누르면 됩니다.

.

Path 설정

쉘 프로그래밍에서 dir,md,cd,rd 등은 쉘(shell)에 내장된 예약어, 즉 쉘이 가지고 있는 API입니다. 이들 API는 어느 곳에 있든지 항상 실행할 수 있습니다. 그러나 explorer, notepad는 예약어가 아닌 프로그램입니다. 아무데서나 호출할 수 있는 API가 아니라는 뜻도 됩니다. API가 아닌 프로그램을 실행하기 위해서는 어떻게 해야 할까요? 이때 필요한 것이 바로 PATH입니다.

PATH에 등록이 되어 있다면 내장되어 있지 않은 프로그램이라도 어떤 곳에서든 실행이 가능합니다.

만약에 path 설정이 되지 않은 cl(cl.exe)이라는 프로그램을 실행하려고 하면 다음과 같은 문구를 접하게 됩니다.


하지만 Path 설정을 하게 되면 다음과 같이 cl 명령어가 작동되는 것을 볼 수 있습니다.

혹, 오류가 발생할 경우 실행되고 있는 cmd창을 종료 후 새로운 창을 열어서 명령어를 입력 하면 됩니다. 이미 실행되고 있던 cmd창은 Path의 변경사항을 바로 적용하지 못하므로

새로운 cmd창을 실행시켜 Path의 변경사항을 알려 주기 위함 입니다.


 PATH는 단어 뜻 그대로 길, 통로라는 의미를 가지고 있습니다. 필요한 정보를 담고 있는 책이 A 도서관에 있다고 가정해봅시다. 그런데 A 도서관으로 가는 길을 모른다면, 소비자는 도서관의 주소를 가지고 책을 찾으러 갑니다. 이와 마찬가지로 우리가 사용하고자 하는 파일들의 주소를 path에 등록함으로써, 사용자는 어떤 곳에서든 그 프로그램을 사용할 수 있게 됩니다. library와 include의 사용과도 같은 맥락입니다.  

지금부터는 C의 경로(path, 패쓰, 패스, Path) 설정을 해 보도록 하겠습니다. path 설정 과정에서는 컴퓨터의 Windows 버전에 따라 팝업 창의 모양이 조금씩 달라집니다. 먼저 버전 10 이상의 화면을 예시로 설명해 보겠습니다.

Windows key와 Break key를 누르면 제어판의 시스템 창이 뜹니다. ‘컴퓨터에 대한 기본 정보 보기’에서 현재 자신의 운영체제 버전을 확인할 수 있습니다. 좌측 고급 시스템 설정에 들어가면 여러 탭이 보입니다. 

고급 탭에서 환경 변수를 클릭합니다.

[시스템 변수]에서 PATH 를 찾아 더블 클릭 합니다.

우리가 C 언어로 만든 프로그램의 컴파일과 링크를 하기 위해서는 cl.exe 와 link.exe가 있는 경로를 지정해 줘야 합니다. 

시스템 변수에 Visual Studio의 cl.exe가 있는 디렉터리를 찾아서 넣어줘야 합니다. cl.exe를 찾기 위해 탐색기를 이용하는 방법도 있습니다. Visual Studio가 있는 폴더 또는 내 PC에서 cl.exe를 검색하면 다음과 유사한 경로의 cl.exe 파일을 찾을 수 있습니다.


C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin 경로에 cl.exe가 많이 보입니다.

백슬래시( backslash, reverse solidus)는 폰트에 따라 \ 기호로 표현되기도 합니다. 따라서 경로에 있는 \ 표시는 \ 와 동일한 역할을 하는 것으로 이해하셔도 좋습니다. 경로를 복사하고 붙여넣는 과정에서 표기가 바뀌는 경우도 있지만 실제로 이상이 있는 것은 아닙니다.

보통 자신의 컴퓨터에 Visual Studio가 설치되면 C 드라이브에 설치가 되지만, D나 E 혹은 F 드라이브에 설치되어 있다면 위와 비슷한 경로를 설치된 드라이브에서 찾아서 넣어주시면 됩니다.  

새로 만들기 버튼을 클릭해서 경로를 넣어주시면  path 설정이 끝납니다. 이제 우리는 {자신의 드라이브}:\Program Files (x86)\Microsoft Visual Studio14.0\VC\bin에 있는 파일들을 어떤 곳에서든지 사용할 수 있게 되었습니다.


윈도우 10 미만 버전에서의 path 설정 화면은 다음과 같습니다. 표시 방법에 차이가 있을 뿐 path 설정 방법은  똑같습니다. 시스템 변수에서 path를 선택해서 편집 버튼을 누릅니다.

다음과 같이 path에 추가되어있는 많은 경로가 보입니다. ; 이 표시는 ‘구분자’라고 하며, 말 그대로 구분을 지어주는 역할을 합니다. 경로;경로;경로 식의 구분을 짓습니다. 

변숫값 항목에  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin 경로를 추가해줍니다. 추가 방법은 아래와 같이 기존에 있던 경로에 ‘;’을 붙이고 바로 path를 추가하면 됩니다.                    

경로;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin 

다음과 같이 변숫값의 마지막 부분을 정리해줍니다. 마지막에 슬래쉬(\)를 추가하면 위 사진과 같은 변수 값이 완성됩니다. 확인을 누르면 path 설정이 끝납니다.

컴파일(Compile)/링크(Link) 

 코딩을 하게 되면 컴파일, 링크, 라이브러리와 같은 용어들을 많이 듣게 됩니다. 많이 등장하는 용어란 기본이고 중요하다는 뜻과도 같습니다.

컴파일과 링크는 우리가 코딩한 프로그램이 실제로 컴퓨터에서 동작할 수 있는 실행 파일이 되는 과정을 뜻합니다. Windows에서의 실행 파일은 확장자(. 뒤에 붙는 영문자)가 .com 혹은 .exe인 파일입니다. .com은 작은 메모리를 사용하는 유틸리티에서 많이 사용되었던 확장자입니다. Windows의 실행 파일은 .exe라고 알아 두셔도 되겠습니다.

위 그림의 KaKaoTalk.exe 파일이 카카오톡의 실행 파일입니다. 확장자가 .exe인 실행 파일에 해당합니다.

  이전 장에서는 만들어진 프로그램을 책에 비유했습니다. 책의 저자가 한국인이기 때문에 〈비전공자를 위한 프로그래밍〉은 한글로 쓰였습니다. 만약 한국어를 배우지 않은 미국인이 이 책을 읽고자 한다면, 번역가가 책을 영어로 번역해주어야 합니다. 프로그램도 마찬가지입니다. 사람이 알아보기 쉬운 고급 언어(C,C++,JAVA 등)로 만들어진 프로그램을 컴퓨터가 이해할 수 있는 기계어로 변환시켜주는 작업을 컴파일이라고 합니다. 컴파일 과정이 끝나고 라이브러리(library)와 링크하는 과정을 거치면 컴퓨터가 실행할 수 있는 실행 파일이 생성됩니다.  

컴파일 과정을 조금 더 깊이 들여다보면 다음과 같습니다. 

그림에서 표시된 Preprocessor, Parser, Translation, Assembler 과정을 컴파일(compile)이라고 합니다. 프리프로세서 과정은 컴퓨터가 알아보기 쉽게 코드를 정리하는 단계입니다.

 #include, #define과 같은 매크로나 지시자를 소스 코드로 변환해 줍니다. 여기서 소스 코드 파일인 source.c는 source.i 파일로 변환 생성됩니다.

Parser는 코드에 문법적으로 이상이 있는지 문법 검사를 하고, Translation 과정이 각 명령어에 대응하는 코드를 어셈블리어로 바꿔주는 역할을 합니다. 여기서 source.i 파일은 C 컴파일러인 cc1에 의하여 어셈블리 코드인 source.s로 변환됩니다.

Assembler는 어셈블리 코드를 기계어로 코드를 바꿔줍니다. Translation 과정의 결과물인 source.s 파일은 이 과정에서 source.o 파일로 변환됩니다.

여기까지가 컴파일 과정입니다. 그러나 이 과정에서 생긴 파일은 실행 파일이 되기에는 반쪽 짜리 결과물밖에 되지 않습니다. 라이브러리 링크 과정을 거치지 않았기 때문입니다.

그렇다면 링크는 무엇일까요? 링크는 프로그램이 돌아가는 데 필요한 라이브러리를 이어주는 작업을 수행합니다. 

 앞 장에서 API를 단어 사전이라고 했던 설명을 기억하시나요? 라이브러리는 바로 이 API를 모아 놓은 장소라고 생각하시면 쉽게 이해가 될 겁니다. 도서관에 모여있는 다양한 책 중에서, 우리가 정보를 얻는 데 필요한 단어의 뜻을 찾아서 넣으면 됩니다. 

링크에는 동적 링크와 정적 링크가 있는데, 정적 라이브러리로 분류된 부분은 링크 시 프로그램에 합쳐집니다. 동적 라이브러리는 필요할 때만 접근하면 되기 때문에 실행 파일에는 포함되지 않고 따로 배포됩니다.

확장자가 .dll 인 dbghelp.dll 가 동적 라이브러리 이며,  실행파일(.exe)과 함께 배포 되어있는 것을 확인할 수 있습니다.

소스가 컴파일된 오브젝트 파일(source.o 10MB)과 정적 라이브러리(60MB), 동적 라이브러리(50MB)가 있으면, 링크 과정을 거쳐서 실행 파일(source.exe) 70MB 가 생성됩니다. 

코딩한 소스는 이렇게 컴파일과 링크 과정을 거쳐서 생성된 실행 파일을 컴퓨터가 인식해 동작하는 것입니다.

C/C++ 프로그래밍

지금까지 배운 내용들을 C/C++ 프로그래밍을 통해서 실습을 해보겠습니다. 

먼저 cmd 창을 열어보겠습니다.

쉘 프로그래밍에서 배웠던 예약어를 복습하면서, 앞서 설치했던 Visual Studio 디렉터리를 찾아가 보겠습니다. 앞에서는 [cd..] 명령어를 통해서 상위 디렉터리로 이동을 했다면, 이번에는 우리가 원하는 디렉터리로 바로 들어가 볼 예정입니다.

다음과 같이 cd 명령어 뒤에 원하는 디렉터리의 경로를 넣어주시면 됩니다. 이때 반드시 드라이브가 포함된 완전한 경로를 넣어야 명령어가 실행됩니다. 

64비트 운영체제일 경우 Visual Studio를 설치할 때, 기본 설정을 따랐다면 주소는 아래와 같습니다. 드라이브와 (x86)의 유무에 주의하며 입력해봅시다.                    

cd C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin

이번에는 현재 위치에서 제가 원하는 파일들을 찾아보겠습니다.                     

dir *.exe

위 명령문에서 명령어 dir 뒤에 붙은 애스터리스크 마크(*)는 모든(all)을 뜻합니다. 즉 이 파일 안에 있는 exe 확장자를 가진 모든 파일을 보여달라는 것입니다. 

이 exe 파일들이 컴파일에 필요한 실행 파일들 입니다. 즉, 개발툴 입니다.

[cd %HOMEPATH%] 를 입력하여 user폴더로 다시 돌아옵니다. 

프로그래밍 실습전에 소스파일을 저장할 디렉터리를 생성 하는데,

나의 첫번째 C언어 프로그래밍 이므로 디렉터리명은 my_first_c 로 하겠습니다.

그리고 생성된 디렉터리로 이동 합니다.

새 파일을 만드시겠습니까? 질문에 예를 누르면 메모장을 통해 helloworld.cpp라는 파일이 생성됩니다. [explorer ..] 명령어를 통해서 파일이 생성되어 있는 것을 확인해보겠습니다. 

파일이 생성된 것을 창에서 확인할 수 있습니다.

이번에는 메모장으로 돌아가서 ‘hello world’라는 문자가 출력되는 내용을 코딩해보겠습니다.            

#include <iostream>


int main()

{

   printf("hello world");

   return 0;

}

이렇게 만들어진 helloworld.cpp를 소스나 소스 파일, 혹은 원시파일이라고도 합니다. 앞으로는 간단히 소스(source)라고 하겠습니다.

메모장이 아닌 cmd 창에서 바로 코딩하기 위해서는 [copy con]  명령어를 이용할 수도 있습니다.

소스 코드의 타이핑 후 ^Z(Ctrl key + Z key) key를 눌러줍시다. “1개 파일이 복사 되었습니다.”라는 문구와 함께 파일이 생성됩니다. 

컴파일 과정

cl.exe 파일은 C/C++ 소스파일의 컴파일과 링크를 수행하는 실행파일입니다.

다음과 같이 타이핑 하고 Enter key를 누르게 되면 helloworld.cpp파일은 컴파일과 링크 과정을 거치게 됩니다.                      

cl.exe helloworld.cpp

이렇게 옵션(/c)을 주면 링크를 생략하고 컴파일만 하게 됩니다.                    

cl.exe /c helloworld.cpp

옵션을 주던, 주지 않던 에러가 발생했습니다. 에러의 발생 이유를 살펴보고 에러를 고쳐보도록 하겠습니다. 발생한 에러를 고치는 것을 ‘디버깅’이라고 하며, ‘버그를 잡는다.’고도 표현합니다.

에러 메시지를 보면 다음과 같습니다. 

helloworld.cpp(1) : helloworld.cpp 파일의 첫 번째 줄에서 에러가 발생했다. 

에러 내용 : iostream 포함 경로를 설정하지 않았습니다. 

에러 내용을 보면 #include <iostream> 구문에서 에러가 발생하였다는 점을 알 수 있습니다. iostream은 입력과 출력을 위한 헤더 파일이고, ‘include’는 이 헤더 파일을 가져오는 동작을 뜻합니다. ‘포함 경로를 설정하지 않았습니다’라는 에러 문구에서 알 수 있듯, iostream의 경로가 설정되지 않아 include가 되지 않는 문제가 발생한 것입니다. 이 문제를 해결하기 위해서는 include라는 변수에 iostream의 경로(Path)를 넣어 주어야 합니다. 사실 이 부분은 쉬운일이 아닙니다. 쉘프로그래밍으로 얻은 자신감으로 인내하고 실습해 보아야 하는 부분입니다. 요지는 필요한 것(API)을 쓰기 위해 필요한 파일(헤더, 파이브러리)을 포함시킨다고 이해하면 됩니다. 헤더와 인클루드의 개념은 다음과 같습니다.

헤더(header)

 헤더는 라이브러리의 색인(index) 이라고 이해하시면 됩니다. 라이브러리가 실제적인 내용을 담고 있는 책이라면 헤더는 라이브러리의 제목과도 같습니다. 그 때문에 헤더 파일은 본체는 없고 형식만 있습니다. 라이브러리를 사용하는 데 있어서 우리는 헤더를 Include 해서 라이브러리 파일을 참조했다는 것을 표시합니다.

 본체는 없고 형식만 있다는 것을 확인하기 위해서 우리가 C/C++ 프로그래밍을 하면서 가장 먼저 접하는 stdio.h 파일을 살펴보겠습니다.

탐색기에서 stdio.h 파일을 찾아서 메모장에서 열어보았습니다.

 우리는 이미 hello, world를 만들어 보았습니다. { } 가 나오고 그 안에 입력과 출력에 관련되어 동작을 구현하는 내용들이 있어야 하는데 보이지 않습니다. 입력과 출력을 구현한 ‘본체’는 라이브러리 파일에 구현 되어 있습니다.

인클루드(include)

 ‘~을 ~에 포함시키다’라는 단어의 뜻이 그대로 반영된 명령어입니다. include는 헤더 파일을 가져오는 것을 뜻합니다. 사용하고자 하는 라이브러리 파일을 불러오기 위해서 해당 헤더를 가져오는 것을 ‘인클루드 한다’라고 표현합니다. 

사용 방법은 아래와 같으며 프로그램 작성 시 제일 먼저 등장해야 합니다.                    

#include <stdio.h>

 앞에서 설명한 ‘PATH 설정’에서 했던 것과 같이 [시스템 환경] 변수에서 path 설정을 하는 것도 가능하지만, 이번에는 shell에서 명령어로 path를 설정해 보겠습니다. 우리가 쓸 명령어는 다음과 같습니다.

명령어에서 ‘set INCLUDE’는 값과 같습니다. 여기서 INCLUDE는 “변하는 수”인 변수이기도 합니다. 해당 변수에 iostream 경로를 넣어주어야 합니다. 아래 경로에서 iostream을 검색해 보시기 바랍니다.                    

C:\Program Files (x86)\Microsoft Visual  Studio 14.0

C:\ 일 수도 있고 D:\ 일수도 있습니다. Visual Studio가 설치된 폴더에서 검색하면 됩니다. 컴퓨터 전체 검색으로 찾아도 되겠습니다.

우리의 경우, iostream이 C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include 경로에 있는 것이 확인되었습니다. 이제 이 경로를 INCLUDE 변수에 넣어줍시다.                    

set INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\

그리고 다시 한 번 실행을 시켜 줍니다. cl.exe에서 .exe는 제외해도 됩니다.                                             

cl /c helloworld.cpp

이번에는 다음과 같은 에러가 발생합니다.

밑줄이 그어진 에러 메시지에서 corecrt.h 파일이 필요하다는 것을 유추할 수 있습니다. corecrt.h 파일을 찾아서 추가해야 합니다.

corecrt.h 파일의 경로와 앞서서 추가했던 경로를 다음과 같이 넣어주면 됩니다.                    

set INCLUDE=C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt;%INCLUDE%C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\

 이렇게 경로를 추가할 때 한 글자라도 틀리게 되면 제대로 추가가 되지 않습니다. 경로가 틀릴 가능성과 매번 장문의 경로를 추가하는 수고를 줄이기 위해 앞에서 배웠던 변수를 재 사용하는 방법을 쓰겠습니다.                     

set INCLUDE=추가할 경로;%INCLUDE%

이처럼 세미콜론(;)을 붙이고 %INCLUDE%로 덧붙이게 되면, 기존의 INCLUDE에 들어가 있던 경로(C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include)부터 이번에 새로 추가할 경로까지 한 번에 들어가게 됩니다. 

set INCLUDE 에 %INCLUDE% 를 추가 하지 않을 경우 기존에 INCLUDE된 경로는

인식하지 못하므로 위와 같이 할 경우 “iostream 포함 경로를 설정하지 않았습니다 .”라는

오류가 다시 나타나게 됩니다.

해당 경로를 넣었으니 다시 컴파일 명령어를 입력해보겠습니다.  이번에는 링크 제거(/c) 옵션을 제외하고 명령어를 실행해 보겠습니다.                     

cl helloworld.cpp

helloworld.obj 파일이 생성되었습니다( obj는 object의 약자 입니다). 이로써 컴파일 과정은 완료했다는 것을 확인했습니다. 하지만 ‘libcpmt.lib 파일을 열 수 없습니다.’ 라는 에러 문구를 통해 링크 과정에서 문제가 생긴 것을 알 수 있습니다. 

먼저 a.obj 파일이 제대로 생성되었는지 확인해야 합니다. 다음 명령어를 실행해봅시다.                    

dir helloworld.obj

SORASOFT 디렉터리 안에 helloworld.obj 파일이 생성되었습니다. 

 링크 에러는 발생하였지만 helloworld.obj 파일이 생겼습니다. 링크 에러를 보고 싶지 않다면

cl /c helloworld.cpp를 통하여 컴파일 과정만 진행하면 됩니다. 경고(warning)는 발생했지만 그러나 obj 가 만들어 집니다. 이를 통하여 warning 은 error 처럼 .obj 파일을 만들지 못하게 할 수는 없다는 것을 알 수 있습니다.

링크 과정으로 돌아와 봅시다. libcpmt.lib 파일을 열 수가 없다고 합니다. corecrt.h 파일이 없었을 때 문제를 해결한 방식과 똑같은 과정을 거치면 됩니다. 해당 파일을 찾아서 LIB이라는 변수에 넣어줍시다.

[set LIB=경로;경로;경로]

경로를 넣어주고 실행합니다. 에러가 또 나면 에러 메시지를 보고 해당 파일을 찾아서 다시 넣어 줍니다. 이렇게 하는 디버깅을 RUN & FIX 디버깅이라고 하며 본 책에서는 이러한 디버깅을 간단히 “디버깅”으로 부르겠습니다.

저의 경우 다음과 같이 경로 지정을 해주었습니다.                                             

set LIB=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86

라이브러리 경로 지정 후 컴파일을 한 결과 예외 처리에 대한 경고가 있지만 helloworld.exe가 생성되었습니다.  

해당 디렉터리를 열어보면 소스 파일(helloworld.cpp)과 컴파일 과정을 거치면서 만들어진 오브젝트 파일(helloworld.obj), 그리고 링크 과정을 통해 실행파일(helloworld.exe)이 생성된 것을 보실 수 있습니다. 

이제 helloworld.exe를 실행시켜봅시다. 이때는 helloworld 만 적어도 실행이 됩니다. 

‘hello world’ 문자열이 출력 되었다면 성공입니다.

지금까지 여러분은 C/C++언어로 코딩에서 컴파일과 링크 과정을 거쳐서, 실행 파일 생성과 실행까지의 과정을 모두 해보았습니다.

JDK / Eclipse 설치 (JAVA)

앞서 우리는 C/C++을 다루어보기 위해 Visual Studio를 설치했습니다. 이번에는 JAVA 언어를 다루기 위한 JDK(Java Development Kit)와, IDE의 종류 중 하나인 Eclipse를 설치해보겠습니다. JDK(Java Development Kit)는 쉽게 말해 JAVA의 응용 프로그램 개발을 위한 프로그램입니다. JDK는 JAVA 언어를 이용한 소스 파일을 컴파일할 수 있는 컴파일러, 디버깅 툴 등으로 이루어져 구성되어 있습니다.

0. 설치환경 점검

JDK는 컴퓨터 환경에 따라 설치 파일이 다르므로, 설치 전 컴퓨터의 bit를 확인해 보아야 합니다. Windows는 정보 처리의 속도에 따라 32bit와 64bit로 나뉩니다. 컴퓨터의 운영체제에 따라 알맞은 파일을 다운받아야 합니다. 운영체제는 다음과 같은 방식으로 확인할 수 있습니다. 실행 창에서 dxdiag를 입력해 봅시다.


운영체제에 bit가 표시되어 있습니다. 제 컴퓨터는 64bit인 것으로 나오는군요. 자신의 컴퓨터 정보를 보고 해당하는 비트에 맞는 JDK 버전을 다운로드 하시면 됩니다. 버전에 따른 자세한 설명은 뒤에서 이어지므로, 운영체제만 확인한 뒤 단계를 넘어가셔도 좋습니다.

1. 프로그램 다운받기

주소창에

를 입력합니다.

다운로드 탭에 마우스를 가져가면 카테고리가 뜹니다. 좌측 상단 Popular Downloads 목록에 있는 JAVA for Developers를 클릭합니다.

화면 중앙에 있는 JDK Download 버튼을 눌러서 다음 화면으로 넘어갑니다.

JAVA SE (왼쪽 위 카테고리의 맨 위에 있으며, 보통 이 Java SE 다운로드 창으로 연결됩니다) Development Kit 8u101 버전을 다운로드 하겠습니다. 이때 라이센스에 동의를 해야 다운로드가 가능합니다. Accept License Agreement에 체크를 하고, 아래쪽에 있는 windows 중 알맞은 파일을 다운받으면 됩니다. 운영체제에서 bit를 확인했던 것이 이때 필요합니다. 정보 처리 속도가 32bit인 컴퓨터는 Windows x86을, 64bit인 컴퓨터는 Windows x64를 다운받아 주시면 됩니다.

여기에서 JAVA SE Development Kit 8u101 버전과 JAVA SE Development Kit 8u102 버전이 있는 것을 볼 수 있습니다. 큰 차이는 없지만, 차이점을 아시고 싶으시면 각 버전의 release note를 읽어보시면 됩니다.

설치 파일을 클릭하시면 아래쪽에 다음과 같은 팝업창이 뜹니다.                    

download.oracle.com 의 jdk-8u101-windows-x64.exe(193MB)을(를) 실행하거나 저장하시겠습니까?

저장을 눌러서 실행 파일을 다운로드 받아 실행해도 되지만, 저는 바로 실행 버튼을 눌러서  설치하겠습니다.

프로그램 접근을 허용하는 창이 뜨면 ‘예’를 선택하고, 프로그램 설치 창이 뜨면 Next 버튼을 눌러줍니다.

Next 버튼을 누릅니다.

설치 준비 중인 화면입니다.

설치할 공간을 설정할 차례입니다. 원하는 위치가 있으면 변경 버튼을 이용해 위치를 지정할 수 있습니다. 저는 위치를 변경하지 않고, 디폴트로 잡혀있는 설치 위치에 바로 설치하도록 하겠습니다.

다음 버튼을 누릅니다.

설치가 진행 중입니다.

Complete! 설치가 완료되었습니다. close 버튼을 누릅니다. 이로써 JAVA의 설치가 끝났습니다.

이번에는 JAVA의 IDE 중 하나인 Eclipse를 설치해보려고 합니다. C/C++과 C#의 경우 Visual Studio라는 IDE를 사용합니다. 마찬가지로 JAVA 언어를 위한 개발툴(tool) 중 주로 쓰이는 IDE가 바로 Eclipse입니다.

1. 프로그램 다운받기

주소창에

를 입력합니다.


화면 우측 상단의 다운로드 버튼을 누릅니다.

다운로드 화면으로 넘어왔습니다. 자신의 운영체제가 Windows이고 64bit라면 화면에 있는 DOWNLOAD 64 BIT 버튼을 눌러줍시다. 

운영체제가 다르거나 64bit가 아닐 경우 버튼 밑에 있는 Download Package 글씨를 눌러 알맞은 버전을 찾을 수 있습니다. JDK와는 달리, 32bit 버전과 64bit 버전 모두 운영체제의 bit와 같은 숫자로 구분되어 있습니다.

DOWNLOAD 버튼을 클릭하면, 화면 하단에 다음과 같은 팝업 창이 뜹니다. 

ftp.jast.ac.jp의 eclipse-inst-win64.exe(44.7MB)을(를) 실행하거나 저장하시겠습니까? 

실행(R) 버튼을 클릭해서 설치합니다. 저장 버튼을 눌러서 실행 파일을 실행 시키셔도 됩니다.

eclipse installer 화면으로 넘어갑니다. 우리가 설치하고자 했던 Eclipse IDE for Java Developers를 선택해 설치하도록 하겠습니다.

Eclipse 설치 경로 설정 화면입니다. 설치를 원하는 경로가 있으면 폴더

를 클릭해서 지정하시면 됩니다. 본 책에서는 기본 경로 그대로 설치를 진행하도록 하겠습니다.

INSTALL 버튼을 클릭합니다.

설치가 끝났습니다.  LAUNCH 버튼을 누르면 프로그램이 실행이 됩니다.

Path 설정

앞선 C/C++ path 설정에 이어, 이번에는 JAVA의 패스 설정을 해보겠습니다. JAVA 컴파일 파일인 javac.exe 파일을 찾아봅시다.

제 컴퓨터의 경우 javac.exe가 C:\Program Files\Java\jdk1.8.0_101\bin에 있는 것을 볼 수 있습니다. 이 폴더에 JAVA 컴파일에 관련된 파일들이 있습니다. 보통 자신의 컴퓨터에 JAVA가 설치되면 C 드라이브에 설치가 되지만, D나 E 혹은 F 드라이브에 설치되어 있다면 위와 비슷한 경로를 설치된 드라이브에서 찾아서 넣어주시면 됩니다. 탐색기를 이용해도 가능합니다.

그럼 지금부터 JAVA의 path 설정을 해 보도록 하겠습니다. 설정 방법은 C의 path 설정 방법과 똑같습니다. Windows key와 Break key를 눌러 시스템 창을 열어줍니다. 좌측 고급 시스템 설정으로 들어갑시다.

고급 탭에서 환경 변수를 클릭합니다.

[시스템 변수]에서 PATH 를 찾아 더블 클릭 합니다.

새로 만들기 버튼을 클릭해서 경로를 넣어주시면 path 설정이 끝납니다.


이제 우리는 {자신의 드라이브}:\Program Files\Java\jdk1.8.0_101\bin에 있는 파일들을 어떤 곳에서든지 사용할 수 있게 되었습니다. 

컴파일(Compile)/링크(Link) 

JAVA컴파일 과정은 C/C++의 컴파일 과정과 같지만 조금은 달라 보일 수 있습니다. 그 이유는 JVM(Java Virtual Machine, 자바가상머신)이 존재하기 때문입니다. 

 일반 프로그램은 운영체제를 통해서 하드웨어에 접근하지만 자바는 중간에 JVM을 거쳐서 접근합니다. 이것은 JAVA의 객체 지향이라는 개념을 잘 표현해주는 것입니다. 일반 프로그램은 운영체제를 통해서 하드웨어에 접근하기 때문에 운영체제에 종속적입니다. 하지만 JAVA는 JVM 덕분에 운영체제에 상관없이 실행할 수 있습니다. 조금 복잡한 아래 그림이 JAVA 프로그램의 컴파일에서 실행이 되는 과정을 보여줍니다. 

그림에 등장하는 용어들을 하나씩 설명해보겠습니다. 우리가 만든 자바코드(Source.java)는 JAVA 컴파일러를 통해서 자바 가상머신이 이해할 수 있는 코드인 자바 바이트 코드(Source.class)로 변환됩니다. Class Loader가 코드를 읽어서 JVM에 할당된 메모리 영역(Interim Memory)에 필요한 라이브러리와 함께 로드합니다. 로드된 코드들은 실행 엔진(JVM)에 의해, 각 운영체제에 맞게 변환되어 실행됩니다. 한마디로 자바 가상머신이 하는 일은 프로그램 동작에 필요한 자바 바이트 코드들을 읽어 들여서 운영체제가 이해할 수 있게 바꿔주는 것입니다.

 JRE(JAVA Runtime Envirionment)는 단어 그대로 JAVA가 실행되는 환경을 뜻합니다. 다시 말해서 JAVA를 실행하는 주체인 JVM이 실행되는 환경을 뜻합니다.

JAVA 프로그래밍 

이번 장에서는 JAVA의 코딩부터 컴파일 과정까지를 연습해보겠습니다.

먼저 cmd 창을 열어서 코딩해봅시다. [copy con] 명령어로 ‘hello world’를 출력하는 소스를 타이핑하는 것이 첫 번째입니다.            

copy con Practice.java

public class Practice {

  public static void main (String [] args){

       System.out.print("hello world");

 } 

}


[copy con] 명령어를 이용해 Practice.java 파일을 만들었습니다. 제대로 파일이 생성되었는지 확인하기 위해 [exploere .] 명령어를 입력해줍니다.

Practice.java 파일이 생성된 것을 확인할 수 있습니다.

이제 자바 컴파일러(javac.exe)를 이용해서 Practice.java 파일을 컴파일 해보겠습니다.                     

javac Practice.java

이전에 열어봤던 디렉터리를 보면 Practice.class 파일이 생성된 것을 확인할 수 있습니다. 자바 컴파일러가 제대로 작동이 되어서 클래스 파일을 생성 했습니다.

클래스 파일이 생성 되었으니, 자바 실행파일(java.exe)을 통해서 프로그램을 실행해보겠습니다.

’hello world’가 출력 되었습니다. 우리가 만든 프로그램이 제대로 컴파일 되고 실행(Execution) 되었습니다.



by HAJUNHO Aug 14. 2016

Chapter 01. 프로그래밍이 뭐야?

프로그래밍 개념 잡기


‘코딩이 뭐야? 포인터는 뭐고, 연산자는 뭐야?’


처음 프로그래밍을 접하시는 분들은 생소한 용어와 어려운 개념 때문에 첫 단계에서 좌절하시는 경우도 많습니다. 컴퓨터에 익숙하지 않으신 분들은 책에서 시키는 대로 힘들게 IDE(Integrated Development Environment) 프로그램을 깔아서 ‘Hello World’를 출력한 이후 프로그래밍을 접거나 아예 그 전에 포기하시는 분들도 많습니다. 모든 공부가 그렇듯이, 프로그래밍도 쉽게 하기 위해서는 개념을 잡고 능숙해지게 연습을 해야 합니다. 따라서 프로그래밍을 배우고자 하는 우리가 해야 될 첫 번째 일은 바로 프로그래밍에 대한 개념을 잡는 것입니다.


비(非) 전공자의 “프로그래밍이 뭡니까?” 라는 물음에 필자는 “프로그래밍은 책 만들기입니다.” 라고 답을 합니다. 

사람은 의사소통을 말과 글, 즉 언어로 합니다. 사람이 컴퓨터에게 명령을 내릴 때에도 마찬가지로 언어가 필요한데, 이 때 쓰이는 언어가 JAVA, C, C++ 같은 프로그래밍 언어입니다.


글은 문장으로 이루어져 있고, 문장은 단어로 이루어져 있습니다. 그리고 단어는 알파벳이나 한글 같은 글자들의 조합으로 만들어집니다. 단어는 집단에서 추상적인 특정 대상을 가리키기 위해서 암묵적, 또는 공개적으로 정한 약속과 같은 것입니다. 컴퓨터 언어도 마찬가지입니다. 컴퓨터 언어의 단어들은 소스 코드들이 모여서 만들어 지고 이미 만들어져 있는 단어들을 API(Application Programming Interface)라고 합니다. 이런 단어들을 가져다 쓰기도 하고, 만들기도 해서 사용자가 컴퓨터에게 시키고자 하는 명령 문장을 만드는 것을 코딩이라고 합니다.  이렇게 만들어진 명령 문장들이 모여서 프로그램을 만들어가는데 이 과정을 프로그래밍이라고 합니다. 


책 = 프로그램


책 만들기 = 프로그래밍(프로그램 만들기)


글쓰기 = 코딩(code 키보드로 타이핑 하기)


단어 = API


글자 = (source)code


언어 = 프로그램 언어(JAVA, C, C++, 어셈블리어)

달필가가 쓴 글은 중복이 없고, 문체가 간결해서 군더더기 없이 읽혀지기 쉽습니다. 좋은 프로그래머가 만든 프로그램도 똑같습니다. 더 나은 글을 쓰기 위해서 문장이 맞았는지 틀렸는지 알 수 있게 문법을 배우는 과정이 필요하듯, 프로그래밍을 잘하기 위해서는 좀 더 간결하면서 동시에 컴퓨터가 명령을 빠르고 효율적으로 수행할 수 있는 구조로 글쓰기(코딩)를 연습하면 되는 것입니다.


이제 코딩과 프로그래밍에 대한 개념을 어느 정도 살펴보았습니다. 개념을 잡은 뒤엔 실전으로 부딪혀 봐야 합니다. 프로그래밍에는 ‘백문이 불여일견’이라는 말과 비슷하게 ‘백문이 불여일타’라는 말이 있습니다. 백날 소스 코드를 본다고 해서 실력이 늘진 않습니다. 실력은 손으로 직접 코드를 쳐봐야 늘기 마련입니다.



예방주사1

API(Application Programming Interface)

 API는 이미 만들어져 있는 함수(프로그램)의 집합입니다. 조금 더 쉽게 이해하기 위해서  API를 단어 사전이라고 생각하면 이해하기가 더욱 쉽습니다. API는 이미 다른 사람들이 단어를 만들어 놓은 것입니다. 글을 쓸 때 단어가 생각이 안 나면 사전에서 단어가 어떤 뜻인지 찾아보고 적절한 단어를 가져다 쓰듯이, 프로그래밍을 하면서 내가 필요한 부분을 API에서 찾아보고 가져다 쓰면 되는 것입니다.

쉘(shell)

위에서 설명했다시피 컴퓨터가 정보를 주고받기 위해서는 언어가 필요합니다. 컴퓨터는 작동하는 과정에서 0과 1이라는 전기적 신호로 의사소통을 합니다. 무수히 많은 0과 1이 반복되는 컴퓨터 언어는 사람이 알아보기 힘들다는 단점이 있었습니다. 그 결과 사람이 알아볼 수 있도록 어셈블리어라는 언어가 만들어지게 되었습니다. 그런데 어셈블리어를 만들어서 기계에 명령을 내리려고 하자, 이 또한 양이 방대해서 사용하기에 불편했습니다. 그래서 만들어진 것이 커널입니다. 어셈블리어로 만들어진 커널은 컴퓨터의 핵심으로 동작처리, 메모리관리, 입출력 연산 등 컴퓨터가 작동되는 모든 연산들이 프로그래밍 되어있습니다.

 쉘은 이러한 커널에 명령을 내리기 위해서 만들어진 프로그램입니다.

프로그래밍을 모르시는 분들은 ‘마우스 더블 클릭으로 명령을 내리면 되는데, 왜 굳이 쉘에 대해 알아야 하나’고 하시는 분도 있을 수 있습니다. 지금 우리가 사용하고 있는 이 바탕화면을 GUI(Graphic User Interface)라고 합니다. 그리고 쉘이 없으면 GUI는 개발이 되지 않습니다. 쉘이 프로그래밍에서 중요한 이유가 이것입니다.



OS(operating system)

사용자가 컴퓨터를 사용할 수 있게 해주는 프로그램입니다. 흔히 사용하는 windows, MAC, Linux 등이 여기에 속합니다.


CUI(Character User Interface) = TUI(Text User Interface) 

단어 그대로 키보드를 통해서 텍스트로 명령어를 입력해서 컴퓨터가 작업을 사용할 수 있게 하는 환경입니다.

GUI(Graphic User Interface)

지금 우리가 사용하고 있는 컴퓨터처럼, 마우스를 움직여 화면에 있는 아이콘을 클릭해 컴퓨터가 작업을 하게 하는 환경입니다


CMD(command의 줄임말) 

windows에서 키보드를 통해서 명령어를 입력 작업을 수행 할 수 있는 창입니다. 여러분이 아는 까만 바탕화면에 흰 글씨가 적혀있는 창을 커맨드 창이라고 하며, 주로 cmd라고 표기합니다.


디렉터리(directory) 

일상생활에서 문서를 작성한 뒤, 폴더에 넣고 이름과 정보(위치)를 쓴 다음 책장에 꽂아 놓으면 필요할 때 그 폴더를 찾을 수 있습니다. 마찬가지로 시스템 안에서 파일을 생성했을 때 그것이 어디에 있는지 나타내줄 수 있는 정보가 표시된 것을 디렉터리라고 합니다.


변수,상수

 변수는 변하는 값입니다. 수학 시간에 우리는 x+y=5를 배운적이 있습니다. x와 y가 자연수라는 가정하에도 x와 y에는 많은 수가 들어갈 수 있습니다. 마치 빈 그릇과 같습니다. 비어있는 그릇이니까 채웠다 비웠다 할 수 있습니다.  상수는 이와 반대로 바뀌지 않고 한번 정하면 변하지 않는 값을 상수라고 합니다. 

프로그래밍을 해보자 <쉘(shell) 프로그래밍>

먼저 쉘(shell) 프로그래밍 실습을 해봅시다. 시장 점유율이 높은 Windows 운영체제를 중심으로 실습 과정을 진행하면서 코드에 대해 설명해 보겠습니다. 쉘 프로그래밍은 다른 프로그래밍 언어와는 달리 설치 없이 바로 실행할 수 있기 때문에, 바로 실습을 해보기 적합한 프로그래밍이라는 장점이 있습니다.

컴퓨터에 명령어를 입력하기 위해서는 먼저 명령어를 입력할 cmd 창을 띄워야 합니다. 키보드의 Windows key

와 R을 동시에 눌러봅시다. Windows key는 데스크 탑 키보드를 기준으로 보통 Alt key의 옆에 있습니다.


위의 창을 실행 창이라고 합니다. cmd를 입력하면 다음과 같은 cmd.exe 창이 뜹니다. 

이 창을 명령 프롬프트, 또는 도스창이라고 부릅니다. 앞으로의 실습에서는 이 실행창을 ‘cmd 창’이라는 용어로 표기할 예정입니다. 여기에 기본 명령어를 코딩(타이핑) 해보겠습니다. 기본 명령어로는 다음과 같은 것들이 있습니다.

 cls 화면 지우기

dir 디렉터리 보기

 cd 디렉터리 바꾸기

md 디렉터리 생성

  rd 디렉터리 지우기

explorer 현재 디렉터리 기준으로 탐색기 실행

위에 있는 명령어들을 이용해서 간단한 프로그래밍을 해봅시다. 처음 입력해볼 명령어는 dir(디렉터리)입니다. dir은 현재 위치에 어떤 파일이나 디렉터리가 있는지 보여주는 명령어입니다. 지금 우리가 사용하고 있는 cmd 창은 CUI, 즉 텍스트(글자)기반의 사용 환경입니다. cmd 창에서는 내가 원하는 위치의 폴더로 들어가기 위해서 마우스를 이용할 수 없습니다. 글자로만 이루어진 cmd 창에서 위치 또한 글자로 파악해야 하기 때문에 명령어가 필요한 것입니다.

dir을 입력하면 사용자가 위치해 있는 장소인 C:\Users\SORASOFT 폴더 안의 2개 파일과 25개의 디렉터리, 그리고 그 정보들이 나타납니다.

이번에는 폴더를 한번 만들어 보겠습니다. ‘md 폴더명’을 타이핑한 다음 Enter key를 치면 폴더가 생성됩니다.  ‘실습’이라는 이름의 폴더를 만들었습니다.

폴더가 실제로 만들어졌는지 확인하기 위해 방금 전 해봤던 dir 명령어를 다시 입력해 보겠습니다.

2016-07-28 날짜에 실습이라는 폴더가 만들어진 것을 확인했습니다. cmd 창을 이용해서 컴퓨터에게 명령을 내려 봤는데, cmd 창에서 명령한 내용이 실제로 컴퓨터에 적용되었는지 확인해 봅시다.

 cmd 창에 파일 탐색기를 통해서 현재의 디렉터리를 볼 수 있는 explorer 라는 명령어를 입력해줍니다.  ‘explorer .’ 이라고 타이핑하면 지금 제가 있는 디렉터리가 화면에 나오는데, 이때 반드시 explorer를 타이핑 한 다음 한 칸을 띄우고 .을 찍어야 합니다.

새로 뜬 창에서 방금 전 cmd 창에서 만든 폴더가 생성되어 있는 것을 확인할 수 있습니다. 

 ‘rd 폴더명’을 입력하면 생성했던 폴더, 혹은 기존에 존재했던 폴더가 삭제됩니다. 쉘에서 명령어를 타이핑하는 것도 코딩입니다. 앞으로는 다양한 플랫폼의 적응을 위해, cmd 창도 ‘쉘’이라는 용어로 통일하도록 하겠습니다.

기본적인 명령어와 입력 방법을 익혔으니 쉘에 다음 명령을 코딩해 봅시다. 코딩에서 띄어쓰기는 매우 중요한 부분이니 주의해서 입력해 봅시다.

for %i in (1, 2, 3, 4, 5, 6, 7, 8) do md 새폴더%i

User 폴더에 새폴더1부터 새폴더8까지의 이름을 가진 8개의 폴더가 생성되었습니다. 위에서 했던 것과 같이 ‘explorer .’을 이용해서 User 폴더에서 새폴더를 직접 확인할 수도 있고, dir 명령어로 cmd 창에서 확인할 수도 있습니다.  갑자기 약간 복잡해진 명령어 코딩 때문에 혼란스러웠을 수 있지만 하나하나 풀어보면 별것 아닙니다. md가 폴더를 만드는 명령어였던 것처럼 다른 명령어에도 각기 역할이 있습니다. for는 문장을 반복하게 하고, %i는 변수라고 불리며 그릇의 역할을 합니다. i 안에 괄호 안의 숫자들을 넣은 폴더가 생기는 것입니다. 

for %i in (1, 2, 3, 4, 5, 6, 7, 8) do md 새폴더%i

       반복해서 i라는 변수에 1,2,3,4,5,6,7,8 숫자를 넣어서 폴더를 만들어라 새폴더i 이름의 

조금 다른 코딩을 이용해 9에서 20까지의 새 폴더를 만들어 봅시다.


for /L %i in (9, 1, 20) do md 새폴더%i

for과 %i 값은 그대로 넣되 /L이라는 옵션이 등장했습니다. 소괄호 안에 입력한 값도 이전의 코딩과는 다른 구조로 되어 있습니다(이 구문에서 소괄호 안의 값은 띄어쓰기를 하여도, 하지 않아도 동일한 결과가 나옵니다).

/L 옵션을 이용하여 소괄호에 입력하는 값을 (시작값, 증가치, 종단값)으로 FOR LOOP 문 인자를 바꾸었습니다. 옵션을 이용하여 일정한 규칙에 의해 반복되는 값을 입력하는 수고를 줄인 것입니다.

여기까지 폴더를 만들어보았습니다. 실습을 위해 만들었던 폴더를 삭제하고 싶다면, 위에서 입력해본 명령어와 구문을 응용할 수도 있습니다.

새폴더를 만드는 실습에서 우리는 새폴더1부터 새폴더20까지, 스무 개의 폴더를 만들었습니다. 시작값을 1로 두고 종단값을 20으로 둔 뒤, 증가치를 1로 설정해줍니다. 폴더를 만드는 대신 이번엔 폴더를 삭제하는 명령어를 넣어줍시다.


for /L %i in (1, 1, 20) do rd 새폴더%i

User에서 결과물을 확인해봅시다!


이렇게 명령어를 입력하여 작업을 하는 쉘 프로그래밍에서는 띄어쓰기나 점으로 명령하는 내용이 완전히 뒤바뀌는 경우도 있습니다. 방금 전 입력해보았던 cd(change directory)와 explorer 명령어를 예로 설명해보겠습니다.

cd는 디렉터리를 바꾸어주는 명령어입니다. cmd 창에서의 .은 현재 폴더를, ..은 상위 폴더 즉 한 단계 위의 폴더를 뜻합니다. 이 명령 단위들을 조합해 입력해봅시다.


‘.’이 하나일 경우에는 위치가 C:\Users\SORASOFT 그대로이지만 ‘..’을 사용하자 C:\Users\SORASOFT에서 상위 디렉터리인 C:\User로 바뀌었습니다. 한번 더 사용하니 C:\ 최상위 디렉터리로 이동 되어진 것을 확인할 수 있습니다. .cd 명령어로는 cmd 창에서의 디렉터리가 바뀌는 것 만을 확인할 수 있지만, explorer를 이용하면 좀 더 쉽게 눈으로 상위 폴더로의 이동을 볼 수 있습니다. 똑같은 방법으로 explorer를 입력해봅시다.

‘.’이 하나 일때는 C의 Users의 user 폴더창이 뜨게 되고, ‘..’ 점이 두 개 일때는 C의 Users 폴더창이 뜨는 것을 확인하실 수 있습니다.


이것으로 아주 기초적인 코딩을 마쳤습니다. 이렇게 쉘에서 코딩을 해 프로그래밍 하는 것을 쉘 프로그래밍이라고 합니다. explorer로 간단히 실행할 수 있었던 탐색기의 모든 기능을 만들기 위해서는 고급 개발자가 한 달 이상 투자를 해야 합니다. 버그를 잡기 위해서는 다시 한 달 이상을 투자해야 합니다. 사용자에게 베타 테스팅을 하고 시장에서 검증 받으려면 추가로 많은 돈과 시간이 들어갑니다. 그렇지 않았다면 누구나 TOTAL COMMAND와 같이 수십 억(76억 추정)의 수익을 올리는 탐색기를 만들 수 있었을 것입니다.

상황에 따라 최적의 솔루션을 만드는 데에는 쉘 프로그래밍만한 것이 없습니다. 가령 shutdown –s –t 3600을 입력한다면, 여러분은 1시간(3600초) 뒤에 컴퓨터가 자동으로 꺼지도록 할 수 있습니다. 물론 shutdown –a로 명령을 취소하는 것도 가능합니다.

지금까지 해온 일련의 과정을 바로 쉘 프로그래밍이라고 합니다. 혹은 Shell script coding이라고도 합니다. 이런 작업들을 “프로그래밍 하다”, “코딩을 하다”로 표현하며, 작업을 이루어내는 사람을 “프로그래머”나 “코더”라고 부르는 것입니다.

Chapter 2. 프로그램을 실행시켜 보자

 앞선 장에서 우리는 쉘(shell)프로그래밍을 통해서 간단하게 프로그래밍의 맛을 봤습니다. 이번장에서는 C와 JAVA를 통한 프로그래밍을 해 보려고 합니다. 

Visual Studio 설치 (C/C++)

이번 장에서는 C 프로그래밍을 도와줄 수 있는 IDE인 Visula Studio의 설치를 해 보겠습니다.

앞서 ‘왜 Visual Studio여야 하는가?’라는 질문을 해결해보았습니다. 지금부터는 운영체제가 Windows라는 전제 하에 Visual Studio 2015 community version을 설치해봅시다.

0. 컴퓨터의 용량을 확인하자

Visual Studio는 소위 말하는 용량 괴물입니다. 설치 안내에서는 약 11GB의 공간을 확보해야 한다고 나와 있지요. 용량 부족으로 설치 도중 오류가 뜨지 않도록, 사전에 Visual Studio를 설치할 공간을 마련해야 합니다.

Windows key와 E키를 동시에 눌러봅시다. 컴퓨터(내 PC)에서 사용 가능한 용량을 확인할 수 있습니다. 로컬 디스크(C; , C드라이브)의 용량이 96.9GB 남았으니 충분하게 설치가 가능합니다.

1. 프로그램 다운받기

주소창에 https://www.visualstudio.com/를 입력합니다.

‘모든 개발자 및 모든 앱을 위한 도구’라는 설명과 함께 다운로드 창이 뜹니다. 다운로드 종류 중 가장 처음 나오는 Community 2015 다운로드를 클릭하면 설치가 시작됩니다.

2. 설치 유형과 기능 선택

설치 위치는 기본적으로 C드라이브의 Program File로 지정됩니다. 설치 위치를 변경하고 싶을 경우, 

표시 아이콘을 눌러서 원하시는 위치를 지정하시면 됩니다.

설치 유형은 기본값과 사용자 지정 설치 두 가지로 나뉩니다. 대부분의 Visual Studio 설치 관련 글에서는 사용자 지정 설치를 권하고 있습니다. 사용자 지정 설치의 경우 인스톨 패키지를 지정할 수 있는 특징이 있습니다. 책에서는 사용자 지정 설치를 해보도록 하겠습니다.

사용자 지정 설치를 선택한 관계로, 우리는 다음 단계에서 프로그램의 설치를 위해 필요한 기능을 선택해야 합니다. 상단에 있는 [프로그래밍 언어]를 열어봅시다. [⦊버튼 클릭]

이 책에서 Visual Studio를 설치하는 목적은 C/C++ 프로그래밍을 위해서 입니다. [프로그래밍 언어] 항목에서 Visual C++ 항목에 [모두 선택]을 해줍니다. 우측 하단의 ‘다음’ 버튼을 누르면 선택한 기능을 확인하는 창이 뜹니다. 확인 후 설치(I)를 클릭합니다. 설치 과정에는 상당한 시간이 걸립니다.

위 화면이 뜸과 동시에 설치가 완료되었습니다. 프로그램이 정상적으로 작동하는지 확인하기 위해서, 재부팅 후 Visual Studio 2015를 시작해 보도록 하겠습니다.

3. 프로그램 열기

시작 프로그램에서 Visual Studio 2015를 열면 로그인 창이 뜹니다. ‘나중에 로그인’을 눌러도 서비스를 이용할 수 있지만, 설치 후 30일 이후부터는 등록을 해야 계속 Visual Studio 2015를 사용할 수 있습니다. 로그인은 Microsoft 계정으로 하며, 메일 주소나 전화번호로 계정을 만들 수 있습니다.

로그인 화면을 넘기면 환경 설정을 해야 합니다. 개발 설정은 일반으로 고정되어 있습니다. 색 테마를 고르고 Visual Studio 시작(S)을 클릭하면 시스템 설정이 완료됩니다.

번외. 생길지도 모를 오류

Visual Studio 2015를 설치하는 도중, 다음과 같은 안내창이 뜨면서 설치가 자동으로 이루어지지 않는 경우가 있습니다. 이 경우 [인터넷에서 패키지 다운로드]를 선택해줍니다. 패키지는 팝업 창의 지시에 따라 쉽게 다운 받을 수 있으며, 이후 자동으로 설치가 계속 진행됩니다.

설치 패키지 오류가 나면 인터넷에 위 화면이 뜹니다. 설치가 완료되거나 패키지를 다운 받으면서 [확인]을 누르면 됩니다.

예방주사2

드라이브 (Drive)

라이브러리(library)

라이브러리란 기계어로 번역된 바이너리 파일입니다. 프로그램에서 자주 사용되는 프로그램이나 부분들을 모아놓은 것입니다. 단어의 뜻 그대로 도서관이라고 생각하시면 이해가 쉽게 될 것입니다.  책을 쓰는데 필요한 자료들을 도서관에서 찾는 것과 같다고 생각하시면 됩니다.  

라이브러리에는 동적라이브러리와 정적 라이브러리가 있습니다.

정적 라이브러리의 경우 프로그램이 동작되는데 있어서 자주 접근해야 하는 부분들이기 떄문에 링크 시 프로그램에 합쳐집니다. 

동적 라이브러리는 필요할 때만 접근하기 

헤더(header)

Y 199.1 2583 c.2 

stdio.h  이것이 헤더 파입니다.  이 말은 표준 입출력 라이브러리 내용을 가져다 쓰기 위해서 프로그램에 저렇게 명시를 한 것입니다. 

 헤더는 라이브러리의 색인(index) 이라고 이해 하시면 쉽습니다. 라이브러리의 설명에서 이어 말을 하면, 책을 쓰는데 필요한 자료를 모두 다 넣다보면 책의 분량이 너무 방대해지기 때문에, 간단하게 그 책의 제목이나 정보를 넣어서 참조했다는 것을 표시하는 개념인 것입니다.

직역해서 객체 라고 부를 수 있습니다. iostream은 헤더 파일입니다. ‘함수 원형’으로 불리기도 합니다. JAVA의 인터페이스(*향후 나올 자바의 주요 개념) 와 같이 본체는 없지만 형식만 있는 것입니다. 프로토타입으로 자주 불리기도 합니다. 이처럼 여러 이름을 가지고 있습니다. 앞으로는 간단히 header(헤더) 로 하겠습니다. 명확한 의미상으로는 모두 ‘프로토타입’으로 말하고 싶으나 파일 확장자가 .h로 되어 있습니다. .h 파일을 찾아서 열어 봅시다. math.h 파일을 열어 봤습니다.

우리는 이미 hello, world를 만들어 보았습니다. 왠지 { } 가 나오고 그 안에 내용들이 들어가는 형식이 나와야 하는데 없습니다. 구현 내용이 없다고 생각하시면 됩니다.

헤더와 헤더의 내용이 구현된 소스와 결합된 오브젝트 파일은 다른 프로그램에 연결해서 사용할 수도 있기에 라이브러리라고 할 수 도 있습니다. 링커의 입장에서 보면 .obj 확장자 파일과 .lib확장자 파일의 차이가 없습니다. 이처럼 소스에서 obj 파일로 변환하는 과정을 컴파일 과정이라고 합니다. 컴파일 과정은 WINDOWS 뿐 아니라 LINUX, MAC에서도 동일합니다. 컴파일러의 차이가 있습니다.

include

메모리

Path 설정

쉘 프로그래밍에서 dir,md,cd,rd 등은 쉘(shell)에 내장된 예약어 입니다. 즉 쉘이 가지고 있는 API 입니다. 이들 API는 어느 곳에 있던지 항상 실행할 수 있습니다.  그러나 explorer, notepad 는 예약어가 아닌 프로그램입니다. 즉, 아무데서나 호출할 수 있는 API가 아닙니다. 그런데 어떻게 호출할 수 있었을까요? 이 때 필요한 것이 바로 PATH 입니다.

PATH에 등록이 되어 있다면 어떤 곳에서든 실행이 가능합니다.

만약에 path 설정이 되지 않은 cl(cl.exe)이라는 컴파일 명령어를 사용하려고 하면 다음과 같은 문구를 접하게 됩니다. 

하지만 path 설정을 하게 되면 다음과 같이 cl명령어가 작동되는 것을 볼 수 있습니다. 

 PATH는 단어 뜻 그대로 길, 통로입니다. 가령 책을 쓰는데, 참고할만한 내용이 있는 책이 A도서관에 있습니다. 그런데 그 도서관이 어디 있는지 가는 길을 모릅니다. 그러면 우리는 도서관의 주소를 가지고 책을 찾으러 갑니다.  이와 마찬가지로 우리가 사용하고자 하는 파일들의 주소를 paht에 등록함으로써 우리는 어떤 곳에서든 그 프로그램을 사용할 수 있게 되는 것입니다.

 이 개념은 나중에 다시 설명하겠지만 library와 include의 사용과도 같은 맥락입니다.  

자 그럼 지금부터 C의 path 설정을 해 보도록 하겠습니다. path 설정은 컴퓨터의 Windows 버전에 따라 팜업 창의 모양이 조금씩 다릅니다. 먼저 버전 10 이상의 화면을 예시로 설명해 보겠습니다.

윈도우키와 Break 키를 누르면 제어판의 시스템 창이 뜹니다. ‘컴퓨터에 대한 기본 정보 보기’에서 현재 자신의 운영체제 버전을 확인할 수 있습니다. 좌측 고급 시스템 설정에 들어가면 여러 탭이 보입니다. 

고급 탭에서 환경 변수를 클릭합니다.

[시스템 변수]에서 PATH 를 찾아 더블클릭 합니다.

우리가 C언어로 만든 프로그램의 컴파일과 링크를 위해서는 cl.exe 와 link.exe가 있는 경로를 지정해 줘야 합니다. 컴파일과 링크에 대해서는 바로 다음 장에 설명을 하니 여기에서는 넘어가도록 하겠습니다.  


시스템 변수에 Visual Studio의 cl.exe가 있는 디렉토리를 찾아서 넣어주세요. cl.exe를 찾기 위해 탐색기를 이용하는 방법도 있습니다. Visual Studio가 있는 폴더 또는 내 PC에서 cl.exe를 검색하면 다음과 유사한 경로의 cl.exe 파일을 찾을 수 있습니다.

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin 경로에 cl.exe가 많이 보입니다.


경로에 있는 \ 표시를 슬래쉬라고 합니다. \와 똑같다고 이해하셔도 좋습니다. 경로를 복사하고 붙여넣는 과정에서 표기가 바뀌는 경우도 있지만 실제로 이상이 있는 것은 아닙니다.

보통 자신의 컴퓨터에 Visual Studio가 설치되면 C드라이브에 설치가 되지만, D나 E 혹은 F드라이브에 설치되어 있다면 위와 비슷한 경로를 설치된 드라이브에서 찾아서 넣어주시면 됩니다.  

새로 만들기 버튼을 클릭해서 경로를 넣어주시면  path 설정이 끝납니다. 이제 우리는 {자신의 드라이브}:\Program Files (x86)\Microsoft Visual Studio14.0\VC\bin에 있는 파일들을 어떤 곳 에서든지 사용할 수 있게 되었습니다. 


윈도우 10 이하 버전에서의 path 설정 화면은 다음과 같습니다. 표시 방법에 차이가 있을 뿐 path 설정 방법은  똑같습니다. 시스템 변수에서 path를 선택해서 편집 버튼을 누릅니다.

다음과 같이 path에 추가되어있는 많은 경로들이 보입니다.  ; 이 표시는 ‘구분자’라고 하며, 말 그대로 구분을 지어주는 역할을 합니다. 경로;경로;경로와 같은 식의 구분을 짓습니다. 

변수 값 항목에  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin 경로를 추가합니다. 추가 방법은 아래와 같이 기존에 있던 경로에 ‘;’을 붙이고 바로 path를 추가하시면 됩니다.                    

경로;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin