1. 좌 <- 우 스와이프 삭제 버튼 사용 (기본 UI) 

2. 좌 <-> 우 스와이프 커스텀 버튼 사용

import UIKit

class ViewController: UIViewController {
	let sections = ["Section1", "Section2", "Section3"]
    var menus = [
                ["VC1","VC2","VC3"],
                ["VC4","VC5","VC6"],
                ["VC7","VC8","VC9"],
    ]
    
    @IBOutlet weak var tableView: UITableView!
    
    var beginningItemSection: Int = -1
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    self.tableView.delegate = self
	self.tableView.dataSource = self
    
    //dragDelegate 설정
	self.tableView.dragInteractionEnabled = true
	self.tableView.dragDelegate = self
	self.tableView.dropDelegate = self
         
	self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "UITableViewCell")
}

extension ViewController: UITableViewDelegate {
    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sections[section]
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return menus[section].count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = UITableViewCell(style: .default, reuseIdentifier: .none)
        cell.textLabel?.text = menus[indexPath.section][indexPath.row]
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        let section = indexPath.section
        let row = indexPath.row

		let vc: ViewController = UIStoryboard(storyboard: .Main).instantiateViewController()
                
		guard let topVC = UIApplication.currentTopViewController() else {
			return
		}
		topVC.navigationController?.pushViewController(vc, animated: true)
    }
    
    // Move Row Instance Method
    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        
        print("moveRowAt : \(sourceIndexPath.row) -> \(destinationIndexPath.row)")
        // 변경된 Cell의 순서에 맞게 menus List 순서 변경
        if sourceIndexPath.section == destinationIndexPath.section {
            // Cell 이름 리스트
            let moveCell = self.menus[sourceIndexPath.section][sourceIndexPath.row]
            self.menus[sourceIndexPath.section].remove(at: sourceIndexPath.row)
            self.menus[sourceIndexPath.section].insert(moveCell, at: destinationIndexPath.row)
        }
    }
    
    // MARK: 셀 스와이프 커스텀 버튼
    // 우 -> 좌 스와이프 "1" 버튼 추가
    func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let actions1 = UIContextualAction(style: .normal, title: "1", handler: { action, view, completionHaldler in
            print("action performed")
            completionHaldler(true)
        })
        
        let configuration = UISwipeActionsConfiguration(actions: [actions1])
        configuration.performsFirstActionWithFullSwipe = false
        
        return configuration
    }
    
    // 좌 -> 우 스와이프 마이크 on/off 버튼 추가
    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let action = UIContextualAction(style: .destructive, title: nil) { (action, view, completion) in
            completion(true)
        }
        
        let action1 = UIContextualAction(style: .destructive, title: nil) { (action, view, completion) in

            completion(true)
        }
        //버튼 1
        action.backgroundColor = .barbiePink
        action.image = UIImage(named: "mic_on_icon")
        //버튼 2
        action1.backgroundColor = .azure
        action1.image = UIImage(named: "mic_off_icon")
        /*
        action1.image = UIGraphicsImageRenderer(size: CGSize(width: 30, height: 30)).image { _ in
            UIImage(named: "mic_off_icon")?.draw(in: CGRect(x: 0, y: 0, width: 30, height: 30))
        }*/
        
        let configuration = UISwipeActionsConfiguration(actions: [action, action1])
        configuration.performsFirstActionWithFullSwipe = false
        
        return configuration
    }
    
    // 좌 <-> 우 스와프 버튼 노출 여부 결정한다.
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }
    
    /* Swipe Right-to-left 삭제버튼 표시 (기본 버튼 사용시만 호출됨)
       trailingSwipeActionsConfigurationForRowAt 우 -> 좌 스와이프
       leadingSwipeActionsConfigurationForRowAt  우 <- 좌 스와이프
     두 개의 함수 사용시에는 호출되지 않음
     *** 기본 삭제 버튼 사용시 호출되는 함수
     */
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        
        if (editingStyle == .delete) {
            self.menus[indexPath.section].remove(at: indexPath.row)
            
            DispatchQueue.main.async { [weak self] in
                self?.tableView.reloadData()
            }
        }
    }
}

+ Recent posts