When your backend is an actual app (not S3), CloudFront can still sit in front of it. Two ways to connect — depends on whether your infra is private or public.

Your EC2 / ALB lives in a private subnet — never exposed to the internet. CloudFront connects to it over AWS's private network via a VPC Origin.
Users --> CloudFront Edge --> VPC Origin --> Private ALB / NLB / EC2

If you are not using VPC Origins, your EC2 or ALB must be public. You then lock it down so only CloudFront IPs can reach it — not random users.
Users --> Edge Location --> EC2 (must be public)
http://d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ipsUsers --> Edge Location --> ALB (must be public) --> EC2 (can be private)