구현할 것:
- width가 고정인 CollectionViewCell의 자동 높이 계산.
필요한 것:
- CollectionViewLayout의 estimatedSize 설정해주기.
- CollectionViewCell에서 메소드 구현해주기.
- Autolayout을 통해 width 고정 시키기.
 
CollectionViewLayout의 estmatedSize 설정해주기.
collectionViewLayout.itemSize = UICollectionViewFlowLayout.automaticSize
collectionViewLayout.estimatedItemSize = CGSize(width: 100, height: 100)
CollectionViewCell에서 메소드 구현해주기.
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    setNeedsLayout()
    layoutIfNeeded()
    let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
    var frame = layoutAttributes.frame
    frame.size.height = ceil(size.height)
    layoutAttributes.frame = frame
    return layoutAttributes
}
Autolayout을 이용해 width 고정시키기.
override func awakeFromNib() {
    ...
    contentView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
    ...
}
전체 코드
class ViewController: UIViewController {
    @IBOutlet weak var collectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        
        // setting estimatedSize
        collectionView.collectionViewLayout.itemSize = UICollectionViewFlowLayout.automaticSize
        collectionView.collectionViewLayout.estimatedItemSize = CGSize(width: 100, height: 100)
        
        ...
    }
}
class CollectionViewCell: UICollectionViewCell {
    ...
    
    // self-sizing cell height
    override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
        setNeedsLayout()
        layoutIfNeeded()
        
        let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
        var frame = layoutAttributes.frame
        frame.size.height = ceil(size.height)
        
        return layoutAttributes
    }
    
    // fixing cell width
    override func awakeFromNib() {
        contentView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
    }
}