Faits :
A.
Par jugement du 28 janvier 2019, le Tribunal pénal de l'arrondissement de la Sarine a condamné A._, pour crime contre la LStup, à une peine privative de liberté de 45 mois, ainsi qu'au paiement d'une créance compensatrice de 20'000 francs. Il a en outre ordonné la confiscation et la destruction de stupéfiants et de divers effets, ainsi que la confiscation de la somme de 6'150 fr. et sa dévolution à l'Etat.
B.
Par arrêt du 27 janvier 2020, la Cour d'appel pénal du Tribunal cantonal de l'Etat de Fribourg a rejeté l'appel formé par A._ contre ce jugement et a confirmé celui-ci.
Il en ressort les faits suivants.
En 2008, A._ a commencé à s'adonner au trafic de cocaïne, activité qu'il a poursuivie jusqu'au 14 septembre 2015. Durant cette période, le prénommé a vendu une quantité de 2'137 g de cocaïne brute. Son trafic a consisté dans la vente, la remise gratuite et la possession en vue de la vente d'une quantité d'au moins 2'220 g de cocaïne brute, soit 666 g de cocaïne pure. Dans ce cadre, A._ a réalisé un chiffre d'affaires d'au moins 213'700 francs.
C.
A._ forme un recours en matière pénale au Tribunal fédéral contre l'arrêt du 27 janvier 2020, en concluant, avec suite de frais et dépens, principalement à sa réforme en ce sens qu'il est acquitté, que la confiscation et la destruction de 28 g bruts de cocaïne, de 6 g bruts de marijuana, d'une assiette, d'un papier et d'un plastique avec résidus de cocaïne sont confirmées, tous les autres objets séquestrés lui étant restitués, que la somme de 6'150 fr. lui est restituée, qu'une indemnité lui est allouée à titre de l'art. 429 CPP à hauteur de 47'952 fr. 80, de même qu'une indemnité à titre de réparation du tort moral à hauteur de 24'000 fr., une indemnité à titre de l'art. 429 CPP lui étant en outre octroyée pour la procédure d'appel. Subsidiairement, il conclut à son annulation et au renvoi de la cause à l'autorité précédente pour nouvelle décision. En tous les cas, il conclut de surcroît à ce qu'une indemnité de 5'000 fr. lui soit allouée pour ses dépens dans la procédure devant le Tribunal fédéral.
D.
Invités à se déterminer concernant le grief portant sur la violation du droit à la confrontation et à un procès équitable, la cour cantonale a renoncé à formuler des observations, tandis que le ministère public a conclu au rejet du recours.
Considérant en droit :
1.
Le recourant conteste tout d'abord le caractère exploitable des moyens probatoires versés au dossier à la suite de la perquisition effectuée le 14 septembre 2015 à son domicile.
1.1. Aux termes de l'art. 131 CPP, en cas de défense obligatoire, la direction de la procédure pourvoit à ce que le prévenu soit assisté aussitôt d'un défenseur (al. 1). Si les conditions requises pour la défense obligatoire sont remplies lors de l'ouverture de la procédure préliminaire, la défense doit être mise en oeuvre après la première audition par le ministère public et, en tout état de cause, avant l'ouverture de l'instruction (al. 2). Les preuves administrées avant qu'un défenseur ait été désigné, alors même que la nécessité d'une défense aurait dû être reconnue, ne sont exploitables qu'à condition que le prévenu renonce à en répéter l'administration (al. 3).
Selon l'art. 245 CPP, a u début de la perquisition, les personnes chargées de l'exécution présentent le mandat de perquisition (al. 1). S'ils sont présents, les détenteurs des locaux qui doivent faire l'objet d'une perquisition sont tenus d'assister à celle-ci. S'ils sont absents, l'autorité fait, si possible, appel à un membre majeur de la famille ou à une autre personne idoine (al. 2).
1.2. La cour cantonale a indiqué que, dès l'ouverture de la procédure préliminaire, il s'était agi d'un cas reconnaissable de défense obligatoire au sens de l'art. 131 CPP. Selon elle, l'art. 245 al. 2 CPP constituait une prescription d'ordre, de sorte que son éventuelle violation n'empêchait pas que les preuves recueillies en l'absence du recourant ou de son défenseur fussent exploitées, conformément à l'art. 141 al. 3 CPP. Ainsi, il n'existait aucun droit des parties, au sens de l'art. 147 CPP, de participer à une perquisition, car celle-ci ne constituait pas une mesure d'administration de preuve à proprement parler.
1.3. Le recourant soutient que, dès lors que l'on se trouvait dans un cas de défense obligatoire, un défenseur aurait dû être désigné immédiatement en sa faveur afin d'être en mesure de l'assister lors de la perquisition de son domicile.
En l'occurrence, il ressort du dossier de la cause que la police a reçu un mandat d'amener, de perquisition et de séquestre concernant le recourant. Elle a donc interpellé ce dernier le 14 septembre 2015 à 21 h 30 à son domicile et a procédé à la perquisition dans la foulée (cf. pièce 2000 du dossier cantonal, p. 14 et pièce 2030 du dossier cantonal). On peine à comprendre comment, selon le recourant, il aurait convenu de lui adjoindre l'assistance d'un défenseur dès son arrestation et avant la perquisition de son domicile, sauf à avoir désigné un tel défenseur avant même l'appréhension de l'intéressé.
De toute manière, la façon de procéder à une perquisition est réglée par l'art. 245 CPP. Il ressort en particulier de l'art. 245 al. 2 CPP que l'autorité peut procéder à une perquisition même en l'absence des détenteurs des locaux ou de leurs représentants (cf. Message du 21 décembre 2005 relatif à l'unification du droit de la procédure pénale, FF 2006 1057, 1220), donc a fortiori hors la présence du prévenu. Dès lors qu'une perquisition peut être valablement menée en l'absence du prévenu, elle peut l'être sans que ce dernier soit assisté d'un défenseur.
D'ailleurs, comme l'admet la doctrine, il n'existe en principe pas de droit des parties ou de leur avocat - au sens de l'art. 147 CPP - de participer à une perquisition, car celle-ci ne constitue pas une mesure d'administration de preuve (cf. CATHERINE HOHL-CHIRAZI, in Commentaire romand, Code de procédure pénale suisse, 2e éd. 2019, n° 18a ad art. 245 CPP; KUHN/JEANNERET, Précis de procédure pénale, 2e éd. 2018, no 10002; SCHMID/JOSITSCH, Schweizerische Strafprozessordnung, Praxiskommentar, 3e éd. 2018, n° 6 ad art. 245 CPP; MOREILLON/PAREIN-REYMOND, Petit commentaire, Code de procédure pénale, 2e éd. 2016, n° 5a ad art. 245 CPP; ANDREAS J. KELLER, in Donatsch/ Hansjakob/Lieber [éd.], Kommentar zur Schweizerischen Strafprozessordnung [StPO], 2e éd. 2014, n° 6 ad art. 245 CPP; THORMANN/ BRECHBÜHL, in Basler Kommentar StPO, 2e éd. 2014, n° 13 ad art. 245 CPP; JO PITTELOUD, Code de procédure pénale suisse, 2012, no 552 ad art. 244 ss CPP). Le Tribunal fédéral a certes admis qu'en vue d'une éventuelle demande de mise sous scellés le prévenu devait pouvoir se faire conseiller par un avocat (cf. arrêts 1B_24/2019 du 27 février 2019 consid. 2.2; 1B_454/2016 du 15 décembre 2016 consid. 3.1), mais aucunement qu'il y aurait lieu, pour l'autorité pénale, de prendre des dispositions pour que le prévenu soit automatiquement assisté par un défenseur lorsqu'une perquisition est effectuée.
Au vu de ce qui précède, le fait que l'on se fût trouvé dans un cas de défense obligatoire et que la perquisition du 14 septembre 2015 eût été conduite sans que la direction de la procédure eût pourvu le recourant d'un défenseur n'entache aucunement l'exploitabilité des moyens probatoires recueillis en cette occurrence. Le grief doit être rejeté.
2.
Le recourant soutient que certaines déclarations faites à sa charge durant l'instruction seraient inexploitables en raison de la qualité en laquelle les personnes intéressées ont été entendues.
2.1. Aux termes de l'art. 141 CPP, les preuves administrées en violation de l'art. 140 CPP ne sont en aucun cas exploitables. Il en va de même lorsque le présent code dispose qu'une preuve n'est pas exploitable (al. 1). Les preuves qui ont été administrées d'une manière illicite ou en violation de règles de validité par les autorités pénales ne sont pas exploitables, à moins que leur exploitation soit indispensable pour élucider des infractions graves (al. 2). Les preuves qui ont été administrées en violation de prescriptions d'ordre sont exploitables (al. 3).
Selon l'art. 158 al. 1 CPP, au début de la première audition, la police ou le ministère public informent le prévenu dans une langue qu'il comprend qu'une procédure préliminaire est ouverte contre lui et pour quelles infractions (let. a), qu'il peut refuser de déposer et de collaborer (let. b), qu'il a le droit de faire appel à un défenseur ou de demander un défenseur d'office (let. c), qu'il peut demander l'assistance d'un traducteur ou d'un interprète (let. d). Les auditions effectuées sans que ces informations aient été données ne sont pas exploitables (art. 158 al. 2 CPP).
L'art. 180 al. 1 CPP dispose que les personnes appelées à donner des renseignements au sens de l'art. 178 let. b à g CPP, ne sont pas tenues de déposer; au surplus, les dispositions concernant l'audition de prévenus leur sont applicables par analogie.
Selon l'art. 181 CPP, au début de l'audition, les autorités pénales attirent l'attention des personnes appelées à donner des renseignements sur leur obligation de déposer ou sur leur droit de refuser de déposer ou de témoigner (al. 1). Les autorités pénales attirent l'attention des personnes appelées à donner des renseignements qui ont l'obligation de déposer ou qui s'y déclarent prêtes sur les conséquences pénales possibles d'une accusation calomnieuse, de déclarations visant à induire la justice en erreur ou d'une entrave à l'action pénale (al. 2).
2.2. Sur ce point, la cour cantonale a indiqué que B._, C._, D._, E._, F._, G._, H._, I._, J._, K._ et L._ avaient été entendus en qualité de prévenus dans le cadre de procédures pénales parallèles dirigées contre eux. Les procès-verbaux de ces auditions avaient par la suite été versés au dossier de la cause. Enfin, le recourant avait été confronté aux prénommés afin que ces derniers s'expriment à nouveau sur sa mise en cause. Ceux-ci avaient alors été entendus avec la qualité de prévenu. Selon l'autorité précédente, les intéressés auraient alors dû être entendus comme personnes appelées à donner des renseignement. Cela dit, cette "erreur de statut" n'avait eu aucune incidence sur les droits du recourant, car au début de chaque audition ceux-ci avaient été rendus attentifs aux droits découlant de l'art. 158 al. 1 let. b à d CPP. Un éventuel défaut d'information ne pouvait ainsi concerner que l'avis relatif aux conséquences pénales d'une accusation calomnieuse, de déclarations visant à induire la justice en erreur ou d'une entrave à l'action pénale au sens de l'art. 181 al. 2 CPP. Un tel défaut n'avait pas pour conséquence une inexploitabilité absolue des preuves au sens de l'art. 141 al. 1 CPP, mais une inexploitabilité relative au sens de l'art. 141 al. 2 CPP. Or, en l'occurrence, les preuves devaient être considérées comme exploitables puisqu'elles étaient indispensables pour élucider une infraction grave, soit un crime contre la LStup.
2.3. Le Tribunal fédéral a déjà eu l'occasion de signaler la controverse doctrinale existant à propos des conséquences d'un défaut d'information, par les autorités pénales, des personnes appelées à donner des renseignements (cf. ATF 141 IV 20 consid. 1.2.3 p. 26 s.; arrêts 6B_998/2017 du 20 avril 2018 consid. 1.2.2; 6B_1039/2014 du 24 mars 2015 consid. 2.4.3). Il a également déjà relevé que l'art. 181 al. 2 CPP ne prévoyait pas l'inexploitabilité de la preuve (cf. art. 141 al. 1 CPP) en cas de manquement aux prescriptions concernées, de sorte que l'art. 141 al. 2 CPP trouvait application (cf. arrêt 6B_1039/2014 précité consid. 2.4.3). Tel a bien été le raisonnement suivi par la cour cantonale, qui a conclu à l'exploitabilité des preuves en question sur la base de l'art. 141 al. 2 CPP.
Le recourant se borne quant à lui à faire état de la controverse doctrinale précitée et à signaler qu'il se rallie à l'avis selon lequel un défaut de communication des informations énoncées à l'art. 181 al. 2 CPP devrait conduire à une inexploitabilité des preuves concernées. Il ne prétend cependant pas qu'il s'agirait d'une inexploitabilité absolue au sens de l'art. 141 al. 1 CPP, ni ne discute l'argumentation de la cour cantonale relative à la possibilité d'exploiter les moyens probatoires concernés en application de l'art. 141 al. 2 CPP. On ne voit donc pas en quoi l'autorité précédente aurait pu violer le droit fédéral en exploitant les déclarations faites par les personnes intéressées avec la qualité de prévenu. Au demeurant, comme l'a relevé la cour cantonale, les consommateurs de drogue - s'ils pouvaient avoir un intérêt à minimiser leur propre consommation de stupéfiants - n'en auraient eu aucun à charger le recourant.
Le recourant prétend encore que certaines déclarations faites en procédure par K._ seraient inexploitables car fondées sur un SMS qui avait été déclaré inexploitable par le tribunal de première instance. Outre que l'argumentation du recourant sur ce point ne répond pas aux exigences de motivation découlant de l'art. 42 al. 2 LTF - l'intéressé ne précisant même pas dans quelle mesure l'autorité précédente aurait pu fonder son état de fait sur les déclarations en question, qu'il ne détaille aucunement -, il n'apparaît pas qu'un tel grief aurait été traité par la cour cantonale, sans que l'intéressé se plaigne, à cet égard, d'un déni de justice formel. Le grief est donc de toute manière irrecevable à défaut d'épuisement des instances cantonales (cf. art. 80 al. 1 LTF).
3.
Le recourant conteste par ailleurs l'exploitabilité des déclarations faites à sa charge par des tiers, en se plaignant d'une violation de son droit à la confrontation et de celui à un procès équitable.
3.1. L'art. 6 par. 3 let. d CEDH garantit à tout accusé le droit d'interroger ou de faire interroger les témoins à charge et d'obtenir la convocation et l'interrogation des témoins à décharge dans les mêmes conditions que les témoins à charge. Cette disposition exclut qu'un jugement pénal soit fondé sur les déclarations de témoins sans qu'une occasion appropriée et suffisante soit au moins une fois offerte au prévenu de mettre ces témoignages en doute et d'interroger les témoins, à quelque stade de la procédure que ce soit (ATF 140 IV 172 consid. 1.3 p. 176; 133 I 33 consid. 3.1 p. 41; 131 I 476 consid. 2.2 p. 480 s.; arrêt 6B_383/2019 du 8 novembre 2019 consid. 8.1.2 non publié aux ATF 145 IV 470). En tant qu'elle concrétise le droit d'être entendu (art. 29 al. 2 Cst.), cette exigence est également garantie par l'art. 32 al. 2 Cst. (ATF 144 II 427 consid. 3.1.2 p. 435; 131 I 476 consid. 2.2 p. 480).
L'art. 147 al. 1 1ère phrase CPP consacre le principe de l'administration des preuves en présence des parties durant la procédure d'instruction et les débats. Il en ressort que les parties ont le droit d'assister à l'administration des preuves par le ministère public et les tribunaux, ainsi que de poser des questions aux comparants. Ce droit spécifique de participer et de collaborer découle du droit d'être entendu (art. 107 al. 1 let. b CPP). Les preuves administrées en violation de l'art. 147 al. 1 CPP ne sont pas exploitables à la charge de la partie qui n'était pas présente (art. 147 al. 4 CPP; ATF 143 IV 397 consid. 3.3.1 p. 403; 457 consid. 1.6.1 p. 459; 140 IV 172 consid. 1.2.1 p. 174 s.).
3.2. La cour cantonale a exposé que des auditions de confrontation avaient été mises en oeuvre. Les personnes ayant désigné le recourant comme un individu leur ayant fourni de la cocaïne avaient été entendues à tour de rôle par le ministère public. Elles avaient été invitées à confirmer leurs précédentes déclarations. La majorité des intéressés avait confirmé les déclarations faites précédemment, tandis que certains étaient - en partie du moins - revenus sur celles-ci, en rectifiant à la baisse les quantités de cocaïne achetées. Après cette étape, le recourant était systématiquement conduit à entrer dans la salle d'audition. Les personnes auditionnées et le recourant étaient alors amenés à confirmer qu'ils se connaissaient, ce que celles-ci avaient toujours admis. Le procureur donnait ensuite lecture au recourant des accusations portées à son encontre, en présence de la personne concernée. Ainsi, selon la cour cantonale, le recourant s'était retrouvé face à chacun des tiers l'ayant mis en cause, dans une salle d'audition, en présence de son défenseur, lequel pouvait intervenir à tout moment, ce qu'il avait fait à de nombreuses reprises.
3.3. Selon la jurisprudence, le prévenu a en principe le droit de participer à l'audition de ses coprévenus, une violation dudit droit rendant inexploitables les déclarations faites à sa charge (cf. ATF 143 IV 457 consid. 1.6.1 p. 459). Le droit de participer à l'administration des preuves selon l'art. 147 al. 1 CPP ne vaut que pour la procédure dans laquelle le prévenu est partie et ne concerne pas les procédures conduites séparément (cf. ATF 141 IV 220 consid. 4.5 p. 229 s.).
En l'espèce, le recourant ne peut donc rien déduire du fait qu'il n'eût pas été invité à participer aux auditions des personnes concernées dans le cadre d'autres procédures pénales. Cela dit, le recourant avait le droit d'être confronté aux intéressés avant que leurs déclarations fussent retenues à sa charge par les autorités pénales (cf. ATF 141 IV 220 consid. 4.5 p. 230).
Le recourant ne prend pas la peine de détailler systématiquement, dans son recours, la situation procédurale de chaque personne ayant fait des déclarations pouvant l'incriminer. Ces informations ne ressortent pas non plus de l'arrêt attaqué. Il n'appartient pas au Tribunal fédéral de rechercher, pour chaque tiers entendu durant l'instruction, si celui-ci a tout d'abord été entendu dans le cadre d'une autre procédure pénale ou directement dans la présente procédure. A défaut d'une motivation suffisante sur ce point (cf. art. 42 al. 2 LTF), le Tribunal fédéral n'examinera que les situations expressément mentionnées par le recourant dans son recours.
3.4. Le droit à la confrontation dont pouvait se prévaloir le recourant ne devait pas conduire l'autorité pénale à mettre en oeuvre une confrontation purement formelle entre ce dernier et les personnes l'ayant mis en cause, laquelle aurait consisté dans une simple confirmation des déclarations faites en son absence (cf. arrêts 6B_542/2016 du 5 mai 2017 consid. 2.4 et les références citées; 6B_369/2013 du 31 octobre 2013 consid. 2.3.3). Des déclarations faites en l'absence du recourant et qui n'auraient pas été confirmées lors des auditions ultérieures conduites en sa présence ne pouvaient en particulier être exploitées à charge de celui-ci, conformément à l'art. 147 al. 4 CPP (cf. ATF 143 IV 457 consid. 1.6.1 p. 459; arrêts 6B_1385/2019 du 27 février 2020 consid. 1.1; 6B_1133/2019 du 18 décembre 2019 consid. 1.3.2; 6B_76/2018 du 15 octobre 2018 consid. 1; 6B_1035/2017 du 20 juin 2018 consid. 1.3.3; 6B_321/2017 du 8 mars 2018 consid. 1.5.2, in SJ 2018 I 356).
Le recourant prétend que, de manière générale, la façon de procéder aux auditions des personnes intéressées, dans le cadre de la procédure dans laquelle il était impliqué, ne lui aurait pas véritablement permis d'exercer son droit à la confrontation. La critique du recourant tombe à faux dans la mesure où elle s'attache au déroulement des auditions, rapporté par la cour cantonale dans l'arrêt attaqué. Certes, la manière de procéder adoptée par le ministère public peut surprendre, puisque le recourant a systématiquement été amené à entrer et à sortir de la salle d'audition afin de n'être confronté aux personnes entendues que de manière limitée. On ne perçoit pas pourquoi sa présence continue dans cette salle aurait été exclue. Force est cependant de constater, à la suite de l'autorité précédente, que le défenseur du recourant a, pour sa part, assisté à l'intégralité des auditions. Le recourant et son défenseur savaient que ces auditions étaient conduites dans le but de garantir le droit de l'intéressé à la confrontation. Or, il ne ressort nullement de l'arrêt attaqué que le recourant ou son défenseur se serait, sur le moment, plaint d'une quelconque manière du déroulement des auditions. La cour cantonale a en revanche constaté que le recourant avait été confronté à toutes les personnes qui avaient fait des déclarations à sa charge, de sorte que tant ce dernier que son défenseur avaient eu la possibilité d'interroger directement les intéressés. Le recourant n'ayant pas manifesté une éventuelle désapprobation concernant la mise en oeuvre des auditions par le ministère public - a fortiori par l'intermédiaire de son défenseur -, il convient d'admettre que celui-ci a renoncé à faire davantage valoir son droit tiré de l'art. 147 al. 1 CPP (cf. à cet égard arrêt 6B_383/2019 précité consid. 8.1.2 et les références citées non publié aux ATF 145 IV 470) et cherche uniquement à obtenir le retrait du dossier de procès-verbaux l'incriminant. Au demeurant, dès lors que le recourant a systématiquement nié les mises en cause émanant de tierces personnes, on voit mal ce que sa présence physique constante aurait pu lui permettre de déceler, ni ce qu'il aurait pu déduire du "comportement non-verbal" des intéressés.
Le recourant ne peut donc prétendre obtenir une inexploitabilité générale - fondée sur l'art. 147 al. 4 CPP - des déclarations faites par les différentes personnes l'ayant mis en cause dans le cadre des auditions tenues par le ministère public. Cela ne l'empêche pas, cependant, de tenter de démontrer que des déclarations faites en son absence auraient ensuite été retenues à sa charge sans avoir été confirmées devant le ministère public (cf. consid. 3.5 infra).
3.5.
3.5.1. Le recourant évoque tout d'abord les déclarations de M._. Le recourant a été condamné pour avoir vendu à cette dernière une quantité de 847 g de cocaïne au prix de 100 fr. le gramme, entre 2008 et le 14 septembre 2015, ainsi que pour lui avoir remis gratuitement 62 g de cocaïne (cf. jugement du 28 janvier 2019, p. 13 et 17, ainsi que l'arrêt attaqué, p. 14). Ces éléments ont été obtenus à l'occasion d'une audition de police de la prénommée, qui a été entendue comme prévenue le 3 juin 2016 (cf. pièce 2120 du dossier cantonal, p. 3 s.).
Il ressort du procès-verbal de l'audition tenue par la suite par le ministère public que la prénommée a été amenée à revenir sur ses précédentes déclarations, qu'elle n'a pas intégralement confirmées, en indiquant ne pas se souvenir de tous les éléments concernés. En définitive, M._ a confirmé avoir acheté une "certaine quantité" de cocaïne au recourant, en précisant avoir également "fait la fête" avec ce dernier (cf. pièce 3051 du dossier cantonal, p. 7 ss).
Compte tenu de ce qui précède, la cour cantonale a violé le droit en retenant, à charge du recourant, les quantités indiquées par M._ à la police et qui n'ont pas été confirmées dans leur intégralité lorsque l'intéressé a pu être confronté à la prénommée.
3.5.2. Le recourant s'attache ensuite aux propos de K._. Il n'apparaît pas que le prénommé aurait mis en cause le recourant durant son audition de police - en qualité de prévenu - du 10 mars 2016 (cf. pièce 2092 du dossier cantonal). On ne voit pas davantage que K._ aurait incriminé d'une quelconque manière le recourant durant l'audition du ministère public à laquelle ce dernier a pris part (cf. pièce 3030 du dossier cantonal). Le grief du recourant se révèle donc infondé sur ce point.
3.5.3. Le recourant évoque les déclarations de N._. Le recourant a été condamné pour avoir vendu à ce dernier une quantité de 120 g de cocaïne au prix de 100 fr. le gramme, dans le courant 2015 (cf. jugement du 28 janvier 2019, p. 13, ainsi que l'arrêt attaqué, p. 14). Le prénommé a tout d'abord été entendu - en qualité de personne appelée à donner des renseignements dans le cadre de l'instruction ouverte contre le recourant - à l'occasion d'une audition de police, le 3 juin 2016, en présence du défenseur de ce dernier (cf. pièce 2137 du dossier cantonal). Durant l'audition tenue par le ministère public, il a expressément répété les propos tenus lors de son audition précédente, ajoutant qu'il avait en réalité acheté davantage de cocaïne au recourant, ce qui a finalement été retenu (cf. pièce 3051 du dossier cantonal, p. 2). On ne distingue donc pas, à cet égard, une violation du droit à la confrontation du recourant.
3.5.4. Le recourant revient sur les déclarations de L._. Le prénommé a tout d'abord été auditionné par la police, le 23 mai 2016, en qualité de prévenu. A cette occasion, il a indiqué avoir acquis au moins 50 g de cocaïne auprès du recourant, par l'intermédiaire de N._. Il a également déclaré avoir entendu que le recourant vendait de la cocaïne depuis des années (cf. pièce 2097 du dossier cantonal, p. 4). Durant l'audition tenue par le ministère public, L._ a confirmé avoir entendu que le recourant vendait de la cocaïne depuis des années et s'être fourni en stupéfiants auprès de ce dernier, par le biais de N._ (cf. pièce 3055 du dossier cantonal, p. 5 s.). La cour cantonale a finalement retenu que, dans les 120 g de cocaïne acquis par N._ auprès du recourant, étaient compris un certain nombre de grammes achetés en faveur de L._, tout en relevant que ce dernier savait que l'intéressé vendait cette substance depuis des années (cf. jugement du 28 janvier 2019, p. 9 et 13, ainsi que l'arrêt attaqué, p. 14). Il n'apparaît donc pas que l'autorité précédente aurait pu retenir à la charge du recourant des déclarations faites en son absence et qui n'auraient pas été confirmées par la suite.
3.5.5. Le recourant se borne ensuite à relever, à propos des déclarations le mettant en cause faites par F._, O._, B._ et C._, qu'il n'y aurait eu "aucune véritable audition de confrontation", sans développer, sur ce point, son grief (cf. art. 42 al. 2 LTF).
3.5.6. Le recourant évoque les déclarations de P._. Le prénommé a tout d'abord été auditionné par la police, en qualité de prévenu, le 23 mars 2016. A cette occasion, il a notamment déclaré que, environ 10 années auparavant, le recourant avait commencé à vendre de la cocaïne, et qu'il avait lui-même, entre 2008 et l'été 2015, servi d'intermédiaire entre ce dernier et des tiers, pour accomplir des transactions portant sur une quantité totale de 290 g de cocaïne, pour un montant de 36'000 fr. (cf. pièce 2176 du dossier cantonal, p. 2 s.). Au cours de l'audition tenue par le ministère public, P._ n'a pas confirmé ces propos, mais a au contraire déclaré avoir dit "n'importe quoi" à la police (cf. pièce 3061 du dossier cantonal, p. 3). Le prénommé a été derechef auditionné par la suite - mais hors la présence du recourant ou de son défenseur - et a confirmé la quantité totale de 290 g de cocaïne évoquée précédemment (cf. pièce 3066 du dossier cantonal, p. 2).
La cour cantonale a pour sa part retenu que le recourant avait vendu à P._ une quantité de 290 g de cocaïne, pour un montant de 29'000 fr., entre 2008 et 2011, et que, selon le prénommé, le recourant s'était adonné au trafic depuis une dizaine d'années (cf. jugement du 28 janvier 2019, p. 9 et 13, ainsi que l'arrêt attaqué, p. 14). Pour ce faire, elle s'est fondée sur des déclarations de P._ qui ont été faites en l'absence du recourant, puis ont été confirmées par la suite, mais hors la présence de ce dernier. L'autorité précédente a ainsi violé le droit à la confrontation du recourant.
3.5.7. Le recourant évoque les propos tenus par Q._.
Le prénommé a tout d'abord été auditionné par la police, en qualité de personne appelée à donner des renseignements, le 6 janvier 2016, dans le cadre de la procédure ouverte contre le recourant, sans la présence de ce dernier ou de son défenseur. Le recourant prétend que son défenseur n'aurait pourtant jamais renoncé à y prendre part. A cette occasion, Q._ a déclaré qu'il avait acheté au recourant deux fois 10 g de cocaïne (cf. pièce 2114 du dossier cantonal, p. 2).
Certes, comme le relève le recourant - et sans qu'il soit besoin de déterminer si lui-même ou son défenseur aurait renoncé à prendre part à l'audition précitée -, si des déclarations faites lors d'auditions conduites en violation du droit de participer en vertu de l'art. 147 al. 1 CPP sont textuellement présentées aux personnes interrogées lors d'auditions de confrontation ultérieures, ces déclarations sont utilisées de manière inadmissible au sens de l'art. 147 al. 4 CPP (ATF 143 IV 457 consid. 1.6.1 p. 459; arrêt 6B_1385/2019 précité consid. 1.1 et les références citées).
Cependant, durant l'audition tenue par le ministère public le 13 juin 2016, Q._ ne s'est pas contenté de confirmer ses précédentes déclarations qui lui ont été relues, mais a derechef expliqué comment s'étaient passées les transactions, en fournissant de nouveaux détails qui n'avaient pas été révélés auparavant. Le prénommé a, en particulier, expressément confirmé avoir acquis deux fois 10 g de cocaïne auprès du recourant, par l'intermédiaire d'un ami, ce qui a été en définitive retenu par la cour cantonale (cf. jugement du 28 janvier 2019, p. 13, ainsi que l'arrêt attaqué, p. 14). L'autorité précédente n'a donc pas violé le droit en retenant les déclarations de Q._ à charge du recourant.
3.5.8. Le recourant mentionne enfin les déclarations faites par R._. Ce dernier a été auditionné par la police, le 13 janvier 2016, en qualité de prévenu. Il a alors déclaré avoir acheté au recourant 390 g de cocaïne, pour un total de 39'000 fr. (cf. pièce 2086 du dossier cantonal, p. 5).
Le recourant indique que le prénommé se trouvait alors dans un cas de défense obligatoire mais qu'il n'avait pas été assisté par un défenseur durant l'audition. Il en déduit que les déclarations en question seraient inexploitables.
L'argumentation du recourant tombe à faux. Il convient en premier lieu de relever que le droit à la mise en oeuvre d'une défense obligatoire, garanti par les art. 130 et 131 CPP, appartient exclusivement au prévenu concerné. Un tiers - y compris un coprévenu -, qui n'est pas titulaire de ce droit, ne dispose d'aucun intérêt juridique à en dénoncer la violation (cf. arrêt 6B_321/2017 précité consid. 1.3; cf. aussi l'arrêt 1B_245/2018 du 5 juin 2018 consid. 2). En second lieu, durant l'audition de confrontation tenue le 29 février 2016, R._ a intégralement confirmé ses précédentes déclarations, en y ajoutant de nouvelles précisions (cf. pièce 3016 du dossier cantonal, p. 6 ss).
Finalement, la cour cantonale a seulement retenu que le prénommé avait acquis, auprès du recourant, une quantité totale de 270 g de cocaïne, pour un montant de 27'000 fr., entre juillet 2014 et juin 2015 (cf. jugement du 28 janvier 2019, p. 13, ainsi que l'arrêt attaqué, p. 14). L'autorité précédente n'a donc pas violé le droit à la confrontation du recourant à cet égard.
3.6. Au vu de ce qui précède, le recours doit être admis s'agissant de l'exploitation des déclarations faites à charge du recourant P._ (cf. consid. 3.5.6 supra). Aucune des déclarations faites par le prénommé lors de son audition de police qui n'aurait pas été expressément confirmée lors de l'une des auditions mises en oeuvre par le ministère public ou à l'occasion d'une audition ultérieure - que l'autorité cantonale restera libre de mener à l'avenir - n'est exploitable à charge du recourant. Il incombera par conséquent à l'autorité cantonale de procéder à une nouvelle appréciation des preuves sans se fonder sur les déclarations inexploitables en question.
S'agissant des déclarations faites par M._ (cf. consid. 3.5.1 supra), il appartiendra à l'autorité cantonale de procéder à une nouvelle appréciation des preuves, en examinant quelles quantités de stupéfiants peuvent être retenues à la charge du recourant, compte tenu de la consommation admise par la prénommée et des achats de cocaïne auprès de celui-ci ayant été reconnus.
4.
Le recourant reproche par ailleurs à l'autorité précédente d'avoir violé son droit d'être entendu, établi les faits de manière arbitraire et violé l'art. 82 al. 4 CPP.
Dans l'arrêt attaqué, la cour cantonale a indiqué que le recourant avait, par le biais de la plaidoirie de son défenseur, axé "l'essentiel de son argumentation autour du caractère prétendument inexploitable des moyens de preuves versés au dossier", et qu'il n'avait développé aucune critique - durant la procédure d'appel - "concernant l'établissement des faits opéré par les premiers juges". L'autorité précédente n'a donc pas procédé à sa propre appréciation des preuves mais a renvoyé au jugement de première instance en application de l'art. 82 al. 4 CPP.
Dès lors que le recourant ne se réfère pas à une éventuelle déclaration écrite d'appel et que le procès-verbal des débats d'appel ne reproduit pas la plaidoirie de son défenseur, le Tribunal fédéral ne peut examiner si et dans quelle mesure la cour cantonale aurait pu violer son droit d'être entendu ou l'art. 82 al. 4 CPP. Il convient donc d'entrer en matière sur le grief du recourant concernant l'arbitraire dans l'établissement des faits.
4.1. Le Tribunal fédéral n'est pas une autorité d'appel, auprès de laquelle les faits pourraient être rediscutés librement. Il est lié par les constatations de fait de la décision entreprise (art. 105 al. 1 LTF), à moins qu'elles n'aient été établies en violation du droit ou de manière manifestement inexacte au sens des art. 97 al. 1 et 105 al. 2 LTF, soit pour l'essentiel de façon arbitraire au sens de l'art. 9 Cst. Une décision n'est pas arbitraire du seul fait qu'elle apparaît discutable ou même critiquable; il faut qu'elle soit manifestement insoutenable et cela non seulement dans sa motivation mais aussi dans son résultat. Le Tribunal fédéral n'entre pas en matière sur les critiques de nature appellatoire (ATF 145 IV 154 consid. 1.1 p. 155 s. et les références citées).
4.2. La cour cantonale a repris à son compte l'appréciation des preuves à laquelle s'était livrée le tribunal de première instance. Il en ressortait notamment, s'agissant du trafic de stupéfiants, que la police avait séquestré, le 14 septembre 2015 au domicile du recourant, un montant de 6'150 fr. en liquide, 28 g bruts de cocaïne - dans trois sachets - et 6 g bruts de marijuana. Les analyses de cette cocaïne avaient permis de déterminer un taux de pureté de 30%. B._, C._, F._, R._, L._, O._, Q._, M._, N._, S._, T._ et P._ avaient déclaré avoir été clients du recourant ou avoir été fournis gratuitement par ce dernier. Les déclarations des prénommés s'étaient recoupées sur de nombreux points concernant la manière de procéder et les habitudes du recourant. Les dénégations de ce dernier - lequel avait nié toute implication dans le trafic et avait prétendu être victime d'un "coup monté" -, n'avaient pas été crédibles. L'intéressé n'avait en définitive admis, avec une certaine réserve, que sa propre consommation de stupéfiants. Afin de déterminer les quantités de stupéfiants impliquées dans le trafic du recourant, il convenait de se fonder, d'une part, sur les jugements et ordonnances pénales définitifs et exécutoires qui avaient été rendus à l'encontre des personnes ayant acquis des stupéfiants auprès de celui-ci et, d'autre part, sur les déclarations des tiers entendus dans la présente procédure. Ces derniers n'avaient eu aucune raison de mentir, dès lors qu'ils savaient que leurs propos seraient ensuite utilisés contre eux dans le cadre des procédures pénales dont ils faisaient l'objet. Lorsque des fourchettes de quantité de drogue ou de prix avaient été avancées, seule devait être retenue la valeur la plus basse, le recourant devant bénéficier du doute.
4.3. Il convient tout d'abord de relever que, nonobstant la nouvelle appréciation des preuves qui devra être opérée par l'autorité cantonale s'agissant des déclarations faites par M._ et P._ (cf. consid. 3.6 supra), l'appréciation globale des preuves impliquant le recourant dans un trafic de stupéfiants peut être confirmée, de nombreuses autres personnes ayant en particulier mis en cause l'intéressé.
4.4. Le recourant reproche à la cour cantonale d'avoir retenu que N._ avait acquis auprès de lui une quantité totale de 120 g de cocaïne au prix de 100 fr. le gramme dans le courant 2015, et que la cocaïne achetée par ce dernier pour le compte de L._ et les 20 boulettes d'un gramme chacune partagées entre eux étaient comprises dans cette quantité.
Selon le recourant, les déclarations des deux prénommés seraient contradictoires concernant les quantités impliquées, puisque L._ aurait indiqué avoir toujours pris 5 g sur les 10 g acquis périodiquement par N._, alors que ce dernier aurait soutenu n'avoir rien donné à l'intéressé. Cette contradiction ne fait cependant aucunement apparaître comme arbitraire la quantité totale de cocaïne retenue par la cour cantonale, laquelle a précisé que dans les 120 g de cocaïne que N._ admettait avoir acquis était comprise la drogue qui avait ensuite été consommée par L._. On ne voit pas en quoi ce qui précède ferait apparaître un doute "sur le principe même d'un achat auprès du recourant". La manière dont les deux prénommés ont été identifiés par la police, sur laquelle revient le recourant, ne fait pas davantage apparaître les faits retenus comme insoutenables.
4.5. Le recourant fait ensuite grief à l'autorité précédente d'avoir retenu qu'il avait vendu à B._ et O._ une quantité totale de 310 g de cocaïne, à 100 fr. le gramme.
A cet égard, son argumentation se révèle purement appellatoire et, partant, irrecevable, puisque l'intéressé se borne à émettre des conjectures concernant les circonstances qui auraient amené B._ et O._ à le mettre en cause, sans démontrer en quoi les faits retenus par la cour cantonale seraient insoutenables. On ne voit pas, au demeurant, pourquoi les deux prénommés, clients du recourant, auraient entrepris de "charger" celui-ci en admettant avoir acquis des quantités qui n'auraient pas correspondu à la réalité.
4.6. Le recourant critique les faits établis à propos de M._. Le Tribunal fédéral peut, en l'état, se dispenser d'examiner son grief sur ce point, dès lors que l'autorité cantonale devra procéder à une nouvelle appréciation des preuves concernant les événements impliquant la prénommée (cf. consid. 3.6 supra).
4.7. Le recourant reproche à la cour cantonale d'avoir retenu que S._ avait acquis auprès de lui 10 g de cocaïne au prix de 100 fr. le gramme, entre mars et avril 2015.
Durant son audition par la police, le prénommé a déclaré avoir acquis chez le recourant, durant la période en question, de la cocaïne pour un montant total de 1'000 à 1'500 fr. (cf. pièce 2148 du dossier cantonal, p. 3 s.). Dès lors qu'il ressort par ailleurs de l'arrêt attaqué que le recourant vendait ordinairement de la cocaïne au prix de 100 fr. le gramme, on ne voit pas en quoi il aurait été arbitraire, pour l'autorité précédente, de retenir que S._ avait acquis 10 g de cette substance. Au demeurant, le recourant n'explique pas quel prix - s'écartant de son tarif habituel - il aurait pratiqué à l'égard du prénommé.
5.
Le recourant reproche à la cour cantonale d'avoir violé la maxime d'accusation.
5.1. L'art. 9 CPP consacre la maxime d'accusation. Selon cette disposition, une infraction ne peut faire l'objet d'un jugement que si le ministère public a déposé auprès du tribunal compétent un acte d'accusation dirigé contre une personne déterminée sur la base de faits précisément décrits. En effet, le prévenu doit connaître exactement les faits qui lui sont imputés et les peines et mesures auxquelles il est exposé, afin qu'il puisse s'expliquer et préparer efficacement sa défense (ATF 143 IV 63 consid. 2.2 p. 65; 141 IV 132 consid. 3.4.1 p. 142 s.). Le tribunal est lié par l'état de fait décrit dans l'acte d'accusation (principe de l'immutabilité de l'acte d'accusation), mais peut s'écarter de l'appréciation juridique qu'en fait le ministère public (art. 350 al. 1 CPP), à condition d'en informer les parties présentes et de les inviter à se prononcer (art. 344 CPP). Le principe de l'accusation est également déduit de l'art. 29 al. 2 Cst. (droit d'être entendu), de l'art. 32 al. 2 Cst. (droit d'être informé, dans les plus brefs délais et de manière détaillée, des accusations portées contre soi) et de l'art. 6 par. 3 let. a CEDH (droit d'être informé de la nature et de la cause de l'accusation).
Les art. 324 ss CPP règlent la mise en accusation, en particulier le contenu strict de l'acte d'accusation. Selon l'art. 325 CPP, l'acte d'accusation désigne notamment les actes reprochés au prévenu, le lieu, la date et l'heure de leur commission ainsi que leurs conséquences et le mode de procéder de l'auteur (let. f); les infractions réalisées et les dispositions légales applicables de l'avis du ministère public (let. g). En d'autres termes, l'acte d'accusation doit contenir les faits qui, de l'avis du ministère public, correspondent à tous les éléments constitutifs de l'infraction reprochée au prévenu (arrêts 6B_189/2020 du 16 juin 2020 consid. 1.1; 6B_125/2020 du 8 juin 2020 consid. 1.1). L'acte d'accusation définit l'objet du procès et sert également à informer le prévenu (fonction de délimitation et d'information) (ATF 143 IV 63 consid. 2.2 p. 65; 141 IV 132 consid. 3.4.1 p. 142 s. et les références citées).
5.2. L'acte d'accusation du 27 décembre 2017 reprochait notamment ce qui suit au recourant (cf. pièce 10000 du dossier cantonal, p. 2 s.) :
"Durant la périodeen cause, [le recourant] a vendu une quantité minimale de l'ordre de 2'300 grammes de cocaïne brute. Les transactions portaient souvent sur la quantité de 10 grammes pour la somme de CHF 1'000.00. [...]
[...]
[Le recourant] a agi par métier. A l'époque des faits, il n'assumait pas d'activité professionnelle et ne disposait que de CHF 1'000.00 par mois que lui versait son épouse. Dans le cadre de son trafic, il a réalisé un bénéfice total supérieur à CHF 10'000.00. II faut relever que la Police a séquestré une somme de CHF 6'150.00 à son domicile. "
5.3. Le recourant a, pour les faits en question, été condamné sur la base de l'art. 19 al. 1 let. c et al. 2 let. a et c aLStup.
La cour cantonale a considéré que le recourant avait réalisé un bénéfice de 20'000 fr. durant les huit années au cours desquelles il s'était adonné au trafic. Pour le reste, elle a repris à son compte la qualification juridique des faits opérée par le tribunal de première instance. Il en ressortait que le recourant avait réalisé un chiffre d'affaires de 213'700 fr. durant des années où - hormis un montant mensuel de 1'000 fr. versé par son épouse - il n'avait bénéficié que de revenus occasionnels et modestes provenant de missions temporaires.
5.4. Le recourant se réfère à la jurisprudence selon laquelle constituent un chiffre d'affaires ou un gain important - au sens de l'art. 19 al. 2 let. c aLStup - le chiffre d'affaires atteignant 100'000 fr., respectivement le gain s'élevant à 10'000 fr. (cf. ATF 129 IV 188 consid. 3.1 p. 190 ss; 253 consid. 2.2 p. 255 s.; plus récemment arrêt 6B_1263/2018 du 28 janvier 2019 consid. 2.1.2). Il soutient que l'acte d'accusation ne ferait "nullement mention d'un quelconque chiffre d'affaires" et que rien ne laisserait penser, dans ce document, que le chiffre en question aurait été supérieur à 100'000 francs. Il en déduit que la cour cantonale n'aurait pu retenir qu'il avait, au total, réalisé un chiffre d'affaires de 213'700 fr. pour retenir l'aggravante du métier.
Cette argumentation tombe à faux. En effet, l'acte d'accusation énumère les différentes transactions dont le recourant a été accusé, en indiquant presque systématiquement la quantité de cocaïne censée avoir été vendue ainsi que le prix pratiqué (cf. pièce 10000 du dossier cantonal, p. 2 s.). La simple addition des quantités vendues en tenant compte du prix pratiqué selon le ministère public permet de constater que le recourant était censé avoir réalisé un chiffre d'affaires supérieur à 100'000 francs. On ne voit donc pas comment celui-ci aurait pu ignorer qu'il lui était reproché de s'être adonné à un trafic de stupéfiants par métier - selon les seuils fixés par la jurisprudence - ni en quoi l'intéressé aurait été empêché de préparer efficacement sa défense sur ce point.
Ce qui précède permet déjà d'écarter le grief du recourant concernant une prétendue violation de la maxime d'accusation.
6.
Le recourant conteste sa condamnation pour crime contre la LStup en raison de l'aggravante du métier.
Il ressort de l'arrêt attaqué que l'intéressé a été condamné pour crime contre la LStup sur la base de l'art. 19 al. 2 let. a et c aLStup. Le recourant ne présente aucun grief spécifique concernant l'aggravante de l'art. 19 al. 2 let. a aLStup. Sa condamnation sur la base de cette disposition ne peut qu'être confirmée compte tenu de l'échec du recourant à obtenir l'inexploitabilité de la plupart des éléments probatoires ayant fondé l'état de fait de la cour cantonale, dont celui-ci n'a pas non plus démontré l'arbitraire.
Partant, dès lors que le cas grave pouvait de toute manière être retenu, il est superflu de se demander s'il pouvait également l'être pour un autre motif, notamment en raison de l'art. 19 al. 2 let. c aLStup (cf. ATF 124 IV 286 consid. 3 p. 295; 122 IV 265 consid. 2c p. 268). Le grief est sans objet.
7.
Compte tenu de ce qui précède, le recours doit être partiellement admis (cf. consid. 3.6 supra). L'arrêt attaqué doit être annulé et la cause renvoyée à l'autorité cantonale pour nouvelle décision. Pour le reste, le recours doit être rejeté dans la mesure où il est recevable.
Le recourant, qui succombe partiellement, supportera une partie des frais judiciaires (art. 66 al. 1 LTF). Il peut prétendre à des dépens réduits, à la charge du canton de Fribourg (art. 68 al. 1 LTF).
Par ces motifs, le Tribunal fédéral prononce :
1.
Le recours est partiellement admis, l'arrêt attaqué est annulé et la cause est renvoyée à l'autorité cantonale pour nouvelle décision. Pour le surplus, le recours est rejeté dans la mesure où il est recevable.
2.
Une partie des frais judiciaires, arrêtée à 2'000 fr., est mise à la charge du recourant.
3.
Le canton de Fribourg versera au recourant une indemnité de 1'000 fr. à titre de dépens réduits pour la procédure devant le Tribunal fédéral.
4.
Le présent arrêt est communiqué au recourant, au Ministère public de l'Etat de Fribourg et au Tribunal cantonal de l'Etat de Fribourg, Cour d'appel pénal.
Lausanne, le 14 août 2020
Au nom de la Cour de droit pénal
du Tribunal fédéral suisse
Le Président : Denys
Le Greffier : Graa