[Swift5] 문제해결 : AVPlayer에서 Temp폴더 내 영상이 재생되지 않는 문제


몇 일전 개발 중 이런 문제가 생긴적이 있었습니다.

영상이 Temp폴더에 저장이 된 상태고, 이 Temp 폴더에 저장된 영상을 사진갤러리로 등록하고,

AVPlayer에 Temp폴더에 저장된 Path를 넣어줬는데도 재생이 되지 않는 문제(아무 반응이 없는 문제)가 있었습니다.

오늘은 이 문제를 어떻게 해결했는지 적어볼까 합니다.


원인

사람마다 조금씩 차이는 있을지도 모르겠는데, 저의 경우 사진갤러리로 영상을 등록하고 Temp성 파일을 삭제하는(ㅡㅡ)문제 였습니다. (사진갤러리로 영상 등록 후 바로 Temp 파일을 삭제하는 로직이 동작하는 문제)

뭐.. 조금만 분석해보면 나오는거긴했는데, 처음엔 AVPlayer에서 에러도 안뱉어내고 무슨문젠지도 모르는상태로 삽질만 죽어라고 했네요.. (AVPlayer에 이상한 Path넣어도 에러 안나오더라구요. 저는 나올줄 알았습니다;;)

혹시라도 영상이 재생이 안된다 싶으시다면 우선 지정된 영상 Path가 제대로 된 Path인지를 확인하시는걸 추천드립니다. 그리고 Path에 해당하는 파일이 있는지를 확인해보시는걸 추천드려요. 보통 exists 함수 사용하면 true/false로 떨어지니..

 

해결

언제나 원인만 알면 해결은 쉽습니다.

저의 경우 일단 임시방편으로 Temp성 파일을 삭제하는 로직을 주석처리 해두었는데요,

해당 부분은 나중에 Directory를 좀 더 세분화해서 어떻게 쓸건지 프로세스 등을 정해놓고 대대적인 공사를 하는걸로 하고 일단은 문제가 없도록 로직의 주석처리로써 해결을 해두었습니다.

 


어쩌다 한번씩 별거아닌거가지고 크게 삽질하는 경우가 있는데, 이번이 그 경우였네요 ㅋㅋㅋㅋㅋㅋㅋ

 

java와 차이가 있다보니 자꾸 헷갈..ㅋㅋㅋ

 

 

버전정보 (v1.0)

 - v1.0 2020.07.21 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com


[Swift5] 특정 View만 화면 회전 (UINavigationController)


아까 공부하러 간다고 말씀을 드렸습니다만.. 오늘의 공부는 바로 iOS(Xcode-Swift)공부였습니다. ㅋㅋㅋ

 

iOS개발을 하다보면 가끔 특정 View에서만 화면을 회전해야하는 경우가 있습니다.

예를들어 가로->세로->가로로 하나의 화면을 세로로 보여야한다던가,

세로->가로->세로 등의 화면으로 보여줘야한다는 등 특정한 요구가 있는 경우가 있습니다.

 

그런 경우 코드로 어떻게 처리를 하는지를 알아보겠습니다.

 

특히 제가 사용하는 소스의 경우 UINavigationController가 적용된 UIViewController에서 강제적으로 화면을 회전시키는 소스입니다.

뭐, 다른 방법이 있을 수 있으나..(supportedInterfaceOrientations를 이용해 변경을 해보려했는데 잘 되지 않더군요. 저의 방법이 잘못된거일지도 모르겠지만, 대략적인 느낌은 전역으로 지정된 UINavigationController 혹은 제가 커스텀한 CustomUIViewController가 override된 supportedInterfaceOrientations를 무시하는 것 같았습니다.)

한동안 삽질을 하던 저는 이 방법을 통해 해결하였습니다.

(더 좋은 방법이 있다면 알려주시면 감사하겠습니다! 감사히 배우겠습니다!!)


 

우선 이 코드를 이해하기 위해서는 viewWillAppear 함수와 viewWillDisappear 함수에 대해 대강 이해하고 계셔야합니다.

이 함수들을 이해하기 위해서는 View Controller의 생명주기에 대해서 알고 계셔야 이해가 쉬운데요.

이 부분은 나중에 다시한번 다루도록 하겠습니다. (... 시간관계상)

 

간단히 말하면 viewWillAppear 함수와 viewWillDisappear 함수는 뷰의 생명주기에 있어 뷰가 나타날때, 뷰가 사라질때 사용(Override)하는 함수입니다. (짤막..)

네.. 지금은 뷰의 생명주기를 알려드리는 시간은 아니니 대강 그렇다는것만 이해하시면 그나마 이해하시는데 큰 문제는 없을겁니다.

 

바로 소스를 보시죠

화면을 시작할 때 회전시키기 (가로 회전 혹은 세로 회전)

override func viewWillAppear(_ animated: Bool) {

  // 화면 회전하기 (가로 회전)
  let orientation = UIInterfaceOrientation.landscapeRight.rawValue
  
  // 세로로 회전 (주석제거)
  // let orientation = UIInterfaceOrientation.portrait.rawValue

  UIDevice.current.setValue(orientation, forKey: "orientation")

  UINavigationController.attemptRotationToDeviceOrientation()

}

 

화면이 종료될 때 원상복귀시키기 (세로->가로->세로 혹은 가로->세로->가로)

override func viewWillDisappear(_ animated: Bool) {
  // 기존 세로에서 가로로 변경했었다면 다시 세로로 원상복구
  let orientation = UIInterfaceOrientation.portrait.rawValue

  // 기존 가로에서 세로로 변경했었다면 다시 가로로 원상복구 (주석제거)
  // let orientation = UIInterfaceOrientation.landscapeRight.rawValue
  
  UIDevice.current.setValue(orientation, forKey: "orientation")

  UINavigationController.attemptRotationToDeviceOrientation()

}

 

보시면 크게 어려운 건 없습니다.

세로모드 혹은 가로모드의 값을 orientation 변수에 담아서

UIDevice 클래스에 접근하여 Value, Key 형태로 저장해줍니다.

 

그리고 attemptRotationToDeviceOrientation함수에서 새로운 인터페이스 방향을 수동으로 적용해줍니다.

 

 

UIDevice - Use a UIDevice object to get information about the device such as assigned name, device model, and operating-system name and version.

대충 UIDevice 객체는 디바이스의 정보를 가져오는 용도로 사용할 수 있다는 모양입니다.

=> 그 정보로는 이름, 모델명, os 이름, 버전 등

출처 : developer.apple.com (https://developer.apple.com/documentation/uikit/uidevice)

 

Apple Developer Documentation

 

developer.apple.com

다들 아시다시피 UINavigationController 클래스도 UIViewController를 상속하여 만들어진 클래스입니다.

그러다보니 UINavgiationController만의 함수가 아닌 상속되어진 UIViewController에도 있는것으로 보입니다.

단지 제 생각이지만, 제가 supportedInterfaceOrientations 함수를 사용함에 있어서 계속해서 실패한 까닭은 이러한 상속여부에 따라 UIViewController에서는 Override가 적용이 불가하지 않았나 싶네요. (쉽게말해 무시)

 

UINavigationController.attemptRotationToDeviceOrientation - If your view controller does this, when those conditions change, your app should call this class method. The system immediately attempts to rotate to the new orientation.

대충 ViewController에서 상태의 변경이 필요한 경우 해당 메소드를 부르면 사용자가 원하는 새로운 방향으로 즉각적으로 회전을 시도한다는 모양입니다.

출처 : developer.apple.com (https://developer.apple.com/documentation/uikit/uiviewcontroller/1621400-attemptrotationtodeviceorientati)

 

Apple Developer Documentation

 

developer.apple.com


버전정보 (v1.0)

 - v1.0 2020.07.14 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com


[Swift5] 화면 전환하기

(storyboard와 show함수 사용)


Android에서 화면전환을 할때에는 Intent를 생성하여 startActivityForResult 함수를 사용하여 다른 액티비티로 전환을 했습니다. (Manifest도 적용을 해줘야 에러가 안난다는건 잊지말아야 하구요!)

 

하지만 iOS에서는 화면전환시 어떠한형식으로 전환을 하면 좋을까요?

사실 화면전환 방법은 다양한 방법이 있지만, 오늘은 storyboard에 id를 입력해주고, controller클래스에서 show 함수를 사용하여 화면을 전환하는 형식을 배워보도록 하겠습니다.

사실 storyboard의 경우 저는 Android의 xml에 대응한다고 생각을 하고 있습니다. (조금 다른면이 많이 있지만)

때문에 Android에서의 Intent 형식과 비슷한 형식을 취하는 방법을 알려드릴까 합니다.

 

요약해서 보기

프로젝트를 생성하시고,

Main.storyboard에서 기본생성된 ViewController에는 버튼을 생성하고(다음화면으로 이동할 이벤트 발생용),

이동할 ViewController를 추가로 생성합니다.

이동할 ViewController를 선택하시고 Identity의 Storyboard ID input 상자를 입력해줍니다.

입력된 Storyboard Id를 잘 기억하고 계시고,

초기 생성된 ViewController의 class로 이동합니다.

class에서 Button의 멤버생성 및 action이벤트를 생성합니다.

생성된 action이벤트에 아래와 같은 코드를 생성합니다.

//생성된 Main.storyboard와 연동작업 (변수에 담는 작업)
let myStoryBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
//aController에 이동할 storyBoard의 ID를 지정합니다. (다음화면의 ID)
let aController = myStoryBoard.instantiateViewController(widthIdentifier: "여기에 기억하고 계신 StoryBoard ID를 입력")
//show함수에 생성한 aController 변수를 매개변수로 넘겨줌으로써 클릭이벤트가 발생하면 이동할 storyBaord ID와 매칭되어 화면이 전환됩니다.
self.show(aController, sender: self)

 

따라해보기

0. 프로젝트를 생성하시고,

1. Main.storyboard로 이동하여 기본 생성된 ViewController와 별개로 두개의 ViewController를 생성하겠습니다.

  -> 기호에 따라 저처럼 NavigationController를 붙이셔도 됩니다!

ViewController를 추가합니다.

 

2. View를 이동하기 위한 이벤트를 걸어줄 Button을 생성합니다.

Button을 생성하고 Title를 지정합니다. (저의 경우 A Controller, B Controller라고 지었습니다.)

 

 2.1. Button에 Title을 지정하는 방법입니다.

버튼을 더블클릭해도 쉽게 변경이 가능합니다.

 - 생성된 버튼 클릭

 - 우측 상단의 Show the Attributes inspector 아이콘을 선택합니다. (선택되어있는지 확인)

 - 하단의 Title input 상자에 버튼에 보여질 Title을 입력하시면 됩니다.

 

3. 알아보기 쉽게 생성된 Controller에 각각 Label을 추가합니다.

저의 경우 A와 B로 입력했습니다. (Label의 추가 및 Title변경도 위 Button 추가하시는것처럼 진행하시면 됩니다.)

4. A를 입력한 Controller를 선택하시고,

    우측 상단의 Show the Identity Inspector 아이콘을 클릭하신 후,

    Storyboard ID input 상자를 입력해줍니다. (입력한 Storyboard ID는 잘 기억해둡니다.)

왼쪽 상자부터 클릭해가면서 차근히 따라해봅니다.

 

5. B를 입력한 Controller도 4번과 동일하게 만들어줍니다.

   단, Storyboard ID는 고유해야하므로 B는 BController등의 형식으로 입력해줍니다.

Label에 B를 입력한 Controller도 A와 동일한 작업을 해줍니다. (Storyboard ID는 다르게)

 

 -> 여기까지 Storyboard ID를 지정해 줌으로써 Android에서 xml의 android:id="@+id/~~~"와 동일한 작업을 했다고 생각하시면 되겠습니다.

 

6. 기본 생성되었던 View에 연결된 ViewController class를 storyboard와 함께 보이게 합니다.

   - 함께 보이는 방법은 우측 상단의 Add Editor on Right 버튼을 찾아 클릭하신 후, 하나는 class를 선택하시고, 하나는 storyboard를 선택하시면 됩니다.

Add Editor on Right 버튼은 이미지에 표시된 상자입니다.

7. 버튼을 우클릭한 상태로 클래스로 드래그하여 변수로 연결시켜줍니다.

여기서는 편리상 btn_a, btn_b로 생성하였습니다.

8. 7번처럼 동일한 방식으로 Action(onClick) 이벤트 함수도 생성시켜줍니다.

여기서도 편리상 onClick_a, onClick_b로 생성하였습니다.

 

9. 아래와 같이 myStoryBoard 변수의 추가와, onClick 이벤트 내 코드를 추가합니다.

여기까지 따라오셨다면 끝!

10. 실행을 해보시면 A와 B button을 누름에 따라 다른 화면(A, B)이 나옴을 확인할 수 있습니다.

 

기본 Main View
A Controller 버튼을 클릭했을때 나오는 A View

 

B Controller 버튼을 클릭했을때 나오는 B View

 

완성된 코드

class ViewController: UIViewController {


    @IBOutlet weak var btn_a: UIButton!
    @IBOutlet weak var btn_b: UIButton!
    
    //추가
    let myStoryBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    
    @IBAction func onClick_a(_ sender: Any) {
        //추가
        let aController = myStoryBoard.instantiateViewController(withIdentifier: "AController")
        
        self.show(aController, sender: self)
    }
    
    @IBAction func onClick_b(_ sender: Any) {
        //추가
        let bController = myStoryBoard.instantiateViewController(withIdentifier: "BController")
        
        self.show(bController, sender: self)
    }
    
}

 

금방 정리할 줄 알았더니 시간이 좀 걸려버렸네요.ㅠㅠㅠ

 

테스트 장비 : 맥미니(2020)

 

버전정보 (v1.0)

 - v1.0 2020.07.02 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com


[Swift5] 버튼 보이게 / 보이지 않게 하기

(Android와 비교)


iOS 앱 개발을 하다보면 버튼을 보이게 하거나 보이지 않게 해야하는 경우가 있습니다.

이런 경우 코드로는 어떻게 표현을 해야하는지를 알아보겠습니다.

 

우선 안드로이드에서 사용하는 버튼을 보이거나 보이지 않게하는 방법입니다. (setVisibility함수 사용)

 

Android에서 사용하는 방법(Java)

private Button btn_test

//init
btn_test = findViewById(R.id.btn_test);

//버튼을 보이지 않게
btn_test.setVisibility(View.INVISIBLE);

//버튼을 보이게
btn_test.setVisibility(View.VISIBLE);

 

iOS에서는 @IBOutlet으로 Storyboard에서 간단하게 드래그로 변수 선언을 해주시고, layer의 isHidden을 이용해 컨트롤합니다.

 

iOS에서 사용하는 방법입니다.(Swift5)

@IBOutlet weak var btn_test: UIButton!

//버튼 보이지 않게
btn_test.layer.isHidden = true

//버튼 보이게
btn_test.layer.isHidden = false

 

단, 위 코드는 UIBarButtonItem 컴포넌트에서는 먹히지 않습니다. (layer가 선언이 되는 컴포넌트는 전부 가능 - Button, View 등)

 

컴포넌트가 UIBarButtonItem인 경우(Swift5)

@IBOutlet weak var navigation_btn_test: UIBarButtonItem!

//버튼 보이지 않게
navigation_btn_test.isEnabled = false
navigation_btn_test.tintColor = UIColor.clear

//버튼 보이게
navigation_btn_test.isEnabled = true
navigation_btn_test.tintColor = UIColor.black

 

UIBarButtonItem 컴포넌트의 경우 아무래도 isHidden을 사용할 수 없는 모양입니다.

(객체 내에서 Hidden을 시킬 수 있는 함수나 멤버가 없는 모양)

따라서 위의 소스는

1. 버튼을 사용하지 못하게 막음.

2. 색상을 없애버려 없는 버튼처럼 만들어 줌.

두가지를 이용했다고 보시면 됩니다.

 

단, 이는 제가 아직 부족한 부분이 많아서 다른 좋은 방법이 있을 수 있으므로, 좋은 방법이 있다면 업데이트 해두도록 하겠습니다.

(소스의 표현방식은 각양각색이니까요!)

 

 

테스트 장비 : 맥미니(2020)

 

버전정보 (v1.0)

 - v1.0 2020.07.01 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com


[Xcode] sotryboard에 UI Component 추가하기


솔직히 이건 아실분들은 다 아시겠지만..

Xcode 10부터는 UI Component의 위치가 달라졌습니다.

(저는 이거 몰라서 헤맸다죠 ㅋㅋㅋㅋㅋㅋ)

 

예전엔 분명 우측 하단에 존재했을 UI Component의 위치가 이제는 우측 상단 + 버튼으로 변경되었습니다.

(간만에 iOS개발하느라 바뀐걸 몰랐...)

 

- UI Componet 버튼의 위치

 -> 우측 상단 + 버튼을 찾아보세요. 아래 이미지의 파란색 상자

UI Component는 우측 상단의 + 버튼으로 변경되었습니다.

 

- UI Component 추가하는 방법

 -> 예전처럼 추가하기 원하시는 Component를 마우스로 클릭하신 상태로 드래그 해주시면 됩니다.

Label, Button 등 원하시는 Component를 클릭해서 그대로 드래그하시면 됩니다.

 

예시) Label 추가

Label을 추가한 화면

 

사실 다들 숙지하고 계시리라고는 생각하는데, 저처럼 간만에 Xcode를 만지거나, 옛날 책으로 Xcode에 입문하시는 분들이 아까운 시간을 버릴까봐 작성해봤습니다.

(이러는 저도 저거 하나 찾겠다고 진짜로 뻥아니고 몇십분 날려먹었습..)

 

테스트 장비 : 맥미니(2020)

 

버전정보 (v1.0)

 - v1.0 2020.07.01 배포

 

* 본 게시글의 이미지 및 사진의 출처는 전부 작성자 본인이 직접 제작 및 촬영하였습니다.

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com


[Swift5] intro 화면 만들기

LaunchScreen.storyboard에서 x초간 딜레이 주기


어플을 만들다보면 초기화면에서 x초간 딜레이 후 메인화면으로 이동하는 경우가 있습니다.

 

그런 경우에는 여러 방법이 있겠지만,

제가 사용하는 방법은 LaunchScreen.storyboard에서 1초정도 딜레이를 주는 방법을 사용하고 있습니다.

 

1. LaunchScreen.storyboard 작업

LaunchScreen.storyboard 클릭

 1.1. ViewController에 원하는 로고 등 작업을 합니다.

Image View를 추가한다던가 작업을 진행합니다.

 

2. AppDelegate.swift 작업

AppDelegate.swift 클릭

 2.1. // Override point for customization after application launch 주석을 찾고, 해당 주석 아래에 sleep(1); 코드를 추가

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        sleep(1)
        return true
    }

  --> sleep 함수는 파라미터로 받아온 시간동안 딜레이를 생성 시켜주는 함수입니다. 여기서는 1을 넣었으니 1초가 됩니다.

 

3. 실행 

 --> 실행을 해보시면 1초간 LaunchScreen.storyboard의 내용이 나오고 이후 Main.storyboard로 넘어감을 확인할 수 있습니다.

 

 

 

테스트 정보

 - 맥 미니 (2020) - iPhone SE (1st Gen)

 

버전정보 (v1.0)

 - v1.0 2020.06.30 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com



 


[독서계획] 2020년 7월 독서계획 0 + 2권


이번 7월에는 0+2권입니다!

뭐지? 싶으실텐데요;;

본래 제가 책을 읽을때에는 어지간하면 전공책은 안읽기로 했었는데..

회사 프로젝트라던가, 개인적인 공부때문에 전공책을 2권이나 구입하게 되었습니다. ㅜ.ㅜ

모두 아시겠지만, 전공책이 저렴한 가격도 아니다보니..

(2권 사는데 벌써 5만원이 훌쩍 넘.. 이 금액이면 소설이라던가의 책이 5권... )

 

0 + 1. 스위프트 프로그래밍 (Swift5)

 - 선택 이유 : 공부 + 프로젝트 스킬 업

 

0 + 1. 나의 첫 머신러닝/딥러닝 (파이썬)

 - 선택 이유 : 공부 + 읽어보고 싶어서

 

간만에 프로그래밍 책 사니까 두근대긴하네요 ㅋㅋ

저는 보통 프로그래밍 언어 하나 배울때 책한권사서 너덜해질때까지 읽고 따라하는 타입이라..

 

다음달에는 좀 제대로된 독서계획을 세울 수 있었으면 좋겠네요 ㅠㅠ


[Swift] 네비게이션 바의 하단 그림자(line) 제거하기

(Custom Navigation Bar)


iOS 개발 중 네비게이션 바를 커스텀하여 뒤에 있는 배경과 같은 색상으로 지정해주고 하단 그림자(혹은 선, line)까지 제거해야하는 경우가 있습니다.

오늘은 네비게이션 바의 하단 그림자 제거하는 방법을 알아보려합니다.

 

코드를 먼저 살펴보시죠.

 

코드 (Swift5 대응)

navigationBar.setBakcgroundImage(UIImage(), for : UIBarMetrics.default)
navigationBar.shadowImage = UIImage()

 

navigationBar에 setBackgroundImage 함수 설정과, shadowImage 변수 설정만 초기화해주시면 그림자가 제거되는 것을 확인하실 수 있습니다.

 

그림자는 배경이미지가 있는 경우 기본적으로 그림자 이미지가 사용되는 모양입니다.

따라서 아무 값을 넣지 않는 객체 UIImage로 BackgroundImage와 shadowImage를 초기화하면 빈 이미지를 가진 객체로 선언되어 그림자가 들어가지 않게 됩니다. 

 

버전정보 (v1.0)

 - v1.0 2020.06.20 배포

 

* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.

* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.

* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.

 

Karzin

abbeea@naver.com

 

+ Recent posts